3

I'm trying to use different SMTP configuration for each user of my application. So, using Swift_SmtpTransport set a new transport instance, assign it to Swift_Mailer and then assign it to Laravel Mailer.

Below the full snippet:

$transport = Swift_SmtpTransport::newInstance($mailConfig['smtp_host'], $mailConfig['smtp_port'], 'ssl');
$transport->setUsername($mailConfig['smtp_user']);
$transport->setPassword($mailConfig['smtp_pass']);
$smtp = new Swift_Mailer($transport);
Mail::setSwiftMailer($smtp);
Mail::queue(....);

Messages are added to the queue but never dispatched. I guess that since the "real" send is asyncronous it uses default SMTP configuration, and not the transport set before Mail::queue().

So, the question is: how to change mail transport when using Mail::queue()?

Luciano
  • 1,455
  • 8
  • 22
  • 52

3 Answers3

6

Instead of using Mail::queue, try creating a queue job class that handles sending the email. That way the transport switching code will be executed when the job is processed.

The Job Class Structure Documentation actually uses a mailing scenario as an example, which receives a Mailer instance that you can manipulate. Just use your code in the class's handle method:

public function handle(Mailer $mailer)
{
    $transport = Swift_SmtpTransport::newInstance($mailConfig['smtp_host'], $mailConfig['smtp_port'], 'ssl');
    $transport->setUsername($mailConfig['smtp_user']);
    $transport->setPassword($mailConfig['smtp_pass']);
    $smtp = new Swift_Mailer($transport);

    $mailer->setSwiftMailer($smtp);

    $mailer->send('viewname', ['data'], function ($m) {
        //
    });
}
Bogdan
  • 43,166
  • 12
  • 128
  • 129
  • thanks for help. This seems to be the right solution, anyway I'm getting strange error "exception 'Swift_TransportException' with message 'Connection could not be established with host mailtrap.io". $mailConfig holds the right credentials, the same that works with native mail-queue. – Luciano Jan 15 '16 at 21:53
  • nevermind, it was a configuration error. It seems that mailtrap.io does not support ssl, so in newInstance method i just removed the option. – Luciano Jan 15 '16 at 22:29
  • Another question for completness: does $this->dispatch(new JobName($data)) accept only one argument, or I can supply any args declared in job class constructor? – Luciano Jan 15 '16 at 22:38
  • 1
    Since you are passing an instance created using the `new` keyword, you're invoking the `JobName` constructor, so you need to pass all parameters required for the class to be instantiated. – Bogdan Jan 15 '16 at 22:42
  • @Bogdan It works for me in a multi tenant app. Thanks a lot! – jartaud Sep 26 '18 at 03:59
0

Best way from notifications since Laravel 7 : https://laravel.com/docs/9.x/notifications#customizing-the-mailer

public function toMail($notifiable)
{
    return (new MailMessage)
                ->mailer('postmark')
                ->line('...');
}
Franck
  • 560
  • 7
  • 20
0

I am working on a test where I need 300 different mailers (to fill Mailtrap Enterprise) so having 300 different configs was not good for me. I am posting the simple solution I found looking at Illuminate\Mail\Mailer class

$transport = Transport::fromDsn('smtp://user:pass@host:port');
Mail::setSymfonyTransport($transport);
Mail::to('to@email.com')
  ->send((new LaravelMail())
  ->subject('Subject')
);

Having this you can do some string manipulation to switch between transport configurations