How to configure and use multiple SES accounts in a Laravel app
When working on Mailcoach, 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.
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.
// 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 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
.
// 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.
// 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.
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.
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:
// 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.
// 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. 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)
What are your thoughts on "How to configure and use multiple SES accounts in a Laravel app"?