In my application each user can use his own SMTP server. Therefor the config must be provided. I'm using Laravel Notifications to send the emails. If I'm using no queue (that means sync), there is no problem.
I made a CustomNotifiable Trait:
config([
'mail.host' => $setting->smtp_host,
'mail.port' => $setting->smtp_port,
'mail.username' => $setting->smtp_username,
'mail.password' => $setting->smtp_password,
'mail.encryption' => $setting->smtp_encryption,
'mail.from.address' => $setting->smtp_from_address,
'mail.from.name' => $setting->smtp_from_name,
]);
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
After that, I restore the original config:
config([
'mail' => $originalMailConfig
]);
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
No problem until now. But if it's queued, just the first config after starting the queue worker will be taken for all further emails, even if any other SMTP config is provided. The default config from config/mail.php will be overridden. But this only works the first time.
I've made in the AppServiceProvider::boot method (the SMTP config is stored at the notification):
Queue::before(function (JobProcessing $event) {
// Handle queued notifications before they get executed
if (isset($event->job->payload()['data']['command']))
{
$payload = $event->job->payload();
$command = unserialize($payload['data']['command']);
// setting dynamic SMTP data if required
if (isset($command->notification->setting))
{
config([
'mail.host' => $command->notification->setting->smtp_host,
'mail.port' => $command->notification->setting->smtp_port,
'mail.username' => $command->notification->setting->smtp_username,
'mail.password' => $command->notification->setting->smtp_password,
'mail.encryption' => $command->notification->setting->smtp_encryption,
'mail.from.address' => $command->notification->setting->smtp_from_address,
'mail.from.name' => $command->notification->setting->smtp_from_name,
]);
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
}
}
});
Of course, the original config get restored:
Queue::after(function (JobProcessed $event) use ($originalMailConfig) {
$payload = $event->job->payload();
$command = unserialize($payload['data']['command']);
// restore global mail settings
if (isset($command->notification->setting))
{
config([
'mail' => $originalMailConfig
]);
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
}
});
It seems, as the Swift Mailer has a cache or something like that. I registered a new MailServiceProvider, which should simply replace the old one. So if I set the config with the new SMTP data, the new registered provider should take them. Logging the config shows even in the TransportManager, that the correct SMTP data were set, right before sending the mail, but the mail was sent with the first set config.
I found this thread and tried the linked solution, but with the same result: How to set dynamic SMTP details laravel
So I need a way to override the Services / ServiceProvider / SMTP config. Even if the Supervisor restarts the queue, there is a chance that multiple emails with different configs should be send at the same time.