I configured laravel's mail service with mandrill driver. No problems here!
Now, at certain point of my application, I need to send a mail via gmail.
I did something like:
// backup current mail configs $backup = Config::get('mail'); // rewrite mail configs to gmail stmp $new_configs = array( 'driver' => 'smtp', // ... other configs here ); Config::set('mail', $new_configs); // send the email Mail::send(... // restore configs Config::set('mail', $backup);
This doens't work, laravel always uses the mandrill configurations. Looks like he initiates mail service at script startup and ignores whatever you do during execution.
How do you change mail service configs/behaviour during execution?
The answer to both these questions is YES!... And the answer is easy. All you have to do is hold SHIFT when selecting an email you want open or when you click Compose.
Therefore, for every user, we recommend having at least four different email addresses for all of the resources they access on the internet.
You can create a new Swift_Mailer
instance and use that:
// Backup your default mailer $backup = Mail::getSwiftMailer(); // Setup your gmail mailer $transport = Swift_SmtpTransport::newInstance('smtp.gmail.com', 465, 'ssl'); $transport->setUsername('your_gmail_username'); $transport->setPassword('your_gmail_password'); // Any other mailer configuration stuff needed... $gmail = new Swift_Mailer($transport); // Set the mailer as gmail Mail::setSwiftMailer($gmail); // Send your message Mail::send(); // Restore your original mailer Mail::setSwiftMailer($backup);
A bit late to the party but just wanted to extend the accepted answer and throw in my 2 cents, in case it saves someone time. In my scenario each logged in user had their own SMTP settings BUT I was sending mails using a queue, which caused the settings to go back to default after setting them. It also created some concurrent emails issues. In short, the problem was
$transport = Swift_SmtpTransport::newInstance($user->getMailHost(), $user->getMailPort(), $user->getMailEncryption()); $transport->setUsername($user->getMailUser()); $transport->setPassword($user->getMailPassword()); $mailer = new Swift_Mailer($transport); Mail::setSwiftMailer($mailer); //until this line all good, here is where it gets tricky Mail::send(new CustomMailable());//this works Mail::queue(new CustomMailable());//this DOES NOT WORK
After few moments of keyboard bashing I realized that the queue is running on a separate process and therefore Mail::setSwiftMailer does not affect it at all. It simply picks up the default settings. Therefore the configuration change had to happen at the actual moment of sending the email and not when queuing it.
My solution was to extend the Mailable Class as following.
app\Mail\ConfigurableMailable.php <?php namespace App\Mail; use Illuminate\Container\Container; use Illuminate\Contracts\Mail\Mailer; use Illuminate\Mail\Mailable; use Swift_Mailer; use Swift_SmtpTransport; class ConfigurableMailable extends Mailable { /** * Override Mailable functionality to support per-user mail settings * * @param \Illuminate\Contracts\Mail\Mailer $mailer * @return void */ public function send(Mailer $mailer) { $host = $this->user->getMailHost();//new method I added on User Model $port = $this->user->getMailPort();//new method I added on User Model $security = $this->user->getMailEncryption();//new method I added on User Model $transport = Swift_SmtpTransport::newInstance( $host, $port, $security); $transport->setUsername($this->user->getMailUser());//new method I added on User Model $transport->setPassword($this->user->getMailPassword());//new method I added on User Model $mailer->setSwiftMailer(new Swift_Mailer($transport)); Container::getInstance()->call([$this, 'build']); $mailer->send($this->buildView(), $this->buildViewData(), function ($message) { $this->buildFrom($message) ->buildRecipients($message) ->buildSubject($message) ->buildAttachments($message) ->runCallbacks($message); }); } }
And then changed CustomMail
to extend ConfigurableMailable
instead of Mailable
:
class CustomMail extends ConfigurableMailable {}
This makes sure that even calling Mail::queue(new CustomMail())
will set the per-user mail settings right before sending. Of course you will have to inject the current user to the CustomMail at some point i.e Mail::queue(new CustomMail(Auth::user()))
While this may not be the ideal solution (i.e if trying to send bulk email it is better to config the mailer once and not on every email sent), I like its simplicity and the fact that we do not need to change the global Mail
or Config
settings at all, only the $mailer
instance is being affected.
Hope you find it useful!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With