multiple mail configurations

后端 未结 7 513
遇见更好的自我
遇见更好的自我 2020-11-28 07:13

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

相关标签:
7条回答
  • 2020-11-28 07:39

    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);
    
    0 讨论(0)
  • 2020-11-28 07:43

    Using only setSwiftMailer as explained by Bogdan didn't work for me, because then the from and adress options where still taken from config/mail.php. Also it wasn't working with queues.

    I created a package called multiMail to solve this.

    One can setup the mail adress and host/provider/username/passwort etc in /config/multimail.php and then one can send the mails using

    \MultiMail::from('office@example.com')->send(new MailableDummy()));
    \MultiMail::from('contact@otherdomain.de')->send(new MailableDummy()));
    

    or queue it

    \MultiMail::from('office@example.com')->queue(new MailableDummy()));
    
    0 讨论(0)
  • 2020-11-28 07:47

    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!

    0 讨论(0)
  • 2020-11-28 07:47

    You can set on the fly mail settings:

    Config::set('mail.encryption','ssl');
    Config::set('mail.host','smtps.example.com');
    Config::set('mail.port','465');
    Config::set('mail.username','youraddress@example.com');
    Config::set('mail.password','password');
    Config::set('mail.from',  ['address' => 'youraddress@example.com' , 'name' => 'Your Name here']);
    

    Maybe you can store settings values in config/customMail.php and retrive them whith Config::get('customMail')

    0 讨论(0)
  • 2020-11-28 07:55

    For Laravel version 7.x you can now state the mail driver to use while sending an email. All you need to configure all your connections & credentials properly in config/mail.php. Once configured, you can specify the name of the driver via mailer() function as below:

    Mail::mailer('postmark')
        ->to($request->user())
        ->send(new OrderShipped($order));
    

    I hope it helps someone.

    0 讨论(0)
  • 2020-11-28 07:56

    Even easier it is to execute following code, just before sending an email, after you have written over the mail-configuration with config :

    app()->forgetInstance('swift.transport');
    app()->forgetInstance('swift.mailer');
    app()->forgetInstance('mailer');
    
    0 讨论(0)
提交回复
热议问题