---
question: Which email adapter do I set in config?
kind: task
via_web: na
via_cli: na
via_python: na
via_api: na
via_config: available
ref_config: services.email.email_adapter
prereq: A project made by `abi new project`, with its `config.yaml` and `.env`.
next:
  - /capabilities/build/platform/send-an-email
  - /capabilities/build/platform/email-overview
---

# Choose a provider

`services.email.email_adapter` picks the one adapter every send goes through. Its `config:` block is required, except for a `custom` adapter.

## Web UI

Not applicable. Nexus does not edit `config.yaml`. Super admins can see the adapter a config file sets at `/organizations/<org>/settings/services` (Organization Settings › Services, not listed in the settings menu). Use the Config steps on this page.

## CLI

Not applicable. No `abi` command picks a provider. After you edit the block, `abi config validate` checks it: see the Config steps on this page.

## Python

Not applicable. The engine builds the email service from `config.yaml` when it starts. Use the Config steps on this page.

## REST API

Not applicable. `GET /api/admin/services` lists the adapter names a config file sets, for super admins; nothing changes them. Use the Config steps on this page.

## Config

### Pick the adapter

| Adapter | Keys |
|---|---|
| `filesystem` | `directory` (default `storage/email`) |
| `smtp` | `host` (default `localhost`), `port` (default `1025`), `username`, `password`, `use_tls` (STARTTLS), `use_ssl` (implicit TLS), `timeout` (default `10`) |
| `ses` | `region_name`, `aws_access_key_id`, `aws_secret_access_key`, `aws_session_token`, all optional |
| `sendgrid` | `api_key` (required), `base_url` (default `https://api.sendgrid.com/v3`) |
| `microsoft_outlook` | `tenant_id`, `client_id`, `client_secret`, `user`, all required |
| `nats_rpc` | `nats_url`, `jwt_secret` (required), `service_identity` |

`use_tls` and `use_ssl` cannot both be true.

### Keep the credentials in `.env`

```bash title=".env"
SMTP_USERNAME=mailer@example.com
SMTP_PASSWORD=...
```

See [Use a secret in config](/user-guide/build/secrets/use-a-secret-in-config).

### Write the block

For development, write messages to disk instead of sending them:

```yaml title="config.yaml"
services:
  email:
    email_adapter:
      adapter: filesystem
      config:
        directory: storage/email
```

To send through an SMTP server:

```yaml title="config.yaml"
services:
  email:
    email_adapter:
      adapter: smtp
      config:
        host: smtp.example.com
        port: 587
        username: "{{ secret.SMTP_USERNAME }}"
        password: "{{ secret.SMTP_PASSWORD }}"
        use_tls: true
```

### Check it

```bash
abi config validate
```

It prints `Configuration is valid`, or names the adapter whose `config` is wrong.

### Restart and send a test

The engine reads `config.yaml` when it starts. Restart it, then [send an email](/user-guide/build/platform/send-an-email). With `filesystem`, the message appears as an `.eml` file in `directory`.
