How to configure and use multiple SES accounts in a Laravel app
Tags: php, laravel, mail
Published: 2020-03-16 09:48:22

When working on [Mailcoach](https://mailcoach.app), it was unclear to me how I could use multiple SES (or Mailgun or Postmark) accounts inside a Laravel app. In this short blog post, I'd like to explain that to you.

<!--more-->

Laravel 7 introduced the ability to configure multiple mailers. Inside the `mail.php` config file, there's now a `mailers` key when an entry for each email provider.

```php
// in config/mail.php

'mailers' => [
    'smtp' => [
        'transport' => 'smtp',
        'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
        'port' => env('MAIL_PORT', 587),
        'encryption' => env('MAIL_ENCRYPTION', 'tls'),
        'username' => env('MAIL_USERNAME'),
        'password' => env('MAIL_PASSWORD'),
    ],

    'ses' => [
        'transport' => 'ses',
    ],

    'mailgun' => [
        'transport' => 'mailgun',
    ],

    'postmark' => [
        'transport' => 'postmark',
    ],

    'sendmail' => [
        'transport' => 'sendmail',
        'path' => '/usr/sbin/sendmail -bs',
    ],

    'log' => [
        'transport' => 'log',
        'channel' => env('MAIL_LOG_CHANNEL'),
    ],

    'array' => [
        'transport' => 'array',
    ],
],
```

For some of these mailers, the Laravel documentation [specifies](https://laravel.com/docs/7.x/mail#driver-prerequisites) that you should add some extra configuration values in `config/services.php`. Here's what you should add to that file if you want to use `ses`.

```php
// in config/services.php

'ses' => [
    'key' => 'your-ses-key',
    'secret' => 'your-ses-secret',
    'region' => 'a-ses-region',
],
```

Here's how you could send a mail using one of these configured mailers.

```php
// send a mail using ses
Mail::mailer('ses')
    ->to($request->user())
    ->send(new YourAwesomeMailable());

// send a mail using smtp
Mail::mailer('smtp')
    ->to($request->user())
    ->send(new YourAwesomeMailable());
```

This works fine when you want to send mail using different email providers. But how would you send mail using different accounts on the same service? Let's say, for instance, you want to use two SES mailers? How would you do that, there's only one entry in the `config/services.php` file.

![source](https://freek.dev/uploads/media/mailconfig/source.png)

The answer lies in the source code! Let's take a look at the code where Laravel is [reading the mail config to build the SES transport](https://github.com/laravel/framework/blob/bd67cc22af6fbc1f5745b0e3ce79e0a12b092048/src/Illuminate/Mail/MailManager.php#L255-L269).

```php
protected function createSesTransport(array $config)
{
    if (! isset($config['secret'])) {
        $config = array_merge($this->app['config']->get('services.ses', []), [
            'version' => 'latest', 'service' => 'email',
        ]);
    }

    $config = Arr::except($config, ['transport']);

    return new SesTransport(
        new SesClient($this->addSesCredentials($config)),
        $config['options'] ?? []
    );
}
```

Here you can see that if there's no `secret` set on the config, Laravel will look in the `services` config file if there are configuration values present in the `ses` key. So, if you specify a `secret` in the `ses` mailer in the `mail` config file, Laravel will use those values.

So here's how you can define and use multiple SES accounts in one Laravel app:

```php
// in config/mail.php

'mailers' => [
    'ses' => [
        'transport' => 'ses',
		'key' => 'your-ses-key',
		'secret' => 'your-ses-secret',
		'region' => 'a-ses-region',
		'version' => 'latest',
		'service' => 'mail',
    ],
    
    'another-ses' => [
        'transport' => 'ses',
		'key' => 'another-ses-key',
		'secret' => 'another-ses-secret',
		'region' => 'another-ses-region',
		'version' => 'latest',
		'service' => 'mail',
    ],
],
```

Those `versions` and `service` keys are required too. In the source code above, you can see that Laravel only automatically adds those when you've put your configuration in `services.php`.

With all this in place, you can start using the mailers.

```php
// send a mail using ses
Mail::mailer('ses')
    ->to($request->user())
    ->send(new YourAwesomeMailable());

// send a mail using another ses account
Mail::mailer('another-ses')
    ->to($request->user())
    ->send(new YourAwesomeMailable());
```

Laravel reads the config for the other mailers like Mailgun and Postmark [in a similar fashion](https://github.com/laravel/framework/blob/bd67cc22af6fbc1f5745b0e3ce79e0a12b092048/src/Illuminate/Mail/MailManager.php#L302-L329). So, if you need to use multiple accounts of the same service, define the config in the `mail.php` config file, and not in `services.php`.

(Thanks Taylor, for pointing me in the right direction)