laravel 多个邮件配置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26546824/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 10:19:23  来源:igfitidea点击:

multiple mail configurations

laravellaravel-4

提问by cmancre

I configured laravel's mail service with mandrill driver. No problems here!

我用 mandrill 驱动程序配置了 laravel 的邮件服务。这里没有问题!

Now, at certain point of my application, I need to send a mail via gmail.

现在,在我的应用程序的某个时刻,我需要通过 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.

这不起作用,laravel 总是使用 mandrill 配置。看起来他在脚本启动时启动邮件服务并忽略您在执行期间所做的任何事情。

How do you change mail service configs/behaviour during execution?

您如何在执行期间更改邮件服务配置/行为?

回答by Bogdan

You can create a new Swift_Mailerinstance and use that:

您可以创建一个新Swift_Mailer实例并使用它:

// 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);

回答by dev7

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

聚会有点晚了,但只是想延长已接受的答案并投入我的 2 美分,以防它节省某人的时间。在我的场景中,每个登录用户都有自己的 SMTP 设置,但我使用队列发送邮件,这导致设置在设置后恢复为默认值。它还创建了一些并发电子邮件问题。简而言之,问题是

$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.

在敲了几下键盘之后,我意识到队列正在一个单独的进程上运行,因此 Mail::setSwiftMailer 根本不会影响它。它只是选择默认设置。因此,配置更改必须在发送电子邮件的实际时刻发生,而不是在排队时发生。

My solution was to extend the Mailable Class as following.

我的解决方案是按如下方式扩展 Mailable 类。

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 CustomMailto extend ConfigurableMailableinstead of Mailable:

然后改为CustomMail扩展ConfigurableMailable而不是Mailable

class CustomMail extends ConfigurableMailable {}

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()))

这确保即使呼叫Mail::queue(new CustomMail())也会在发送之前设置每个用户的邮件设置。当然,您必须在某个时候将当前用户注入到 CustomMail 中,即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 Mailor Configsettings at all, only the $mailerinstance is being affected.

虽然这可能不是理想的解决方案(即,如果尝试发送批量电子邮件,最好配置一次邮件程序而不是每次发送的电子邮件),但我喜欢它的简单性以及我们不需要更改全局MailConfig设置的事实总之,只有$mailer实例受到影响。

Hope you find it useful!

希望你觉得它有用!

回答by Giacomo

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','[email protected]');
Config::set('mail.password','password');
Config::set('mail.from',  ['address' => '[email protected]' , 'name' => 'Your Name here']);

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

也许您可以将设置值存储在 config/customMail.php 中并使用 Config::get('customMail') 检索它们

回答by Adam

Using only setSwiftMaileras explained by Bogdan didn't work for me, because then the fromand adressoptions where still taken from config/mail.php. Also it wasn't working with queues.

setSwiftMailer按照 Bogdan 的解释使用对我不起作用,因为fromadress选项仍然取自config/mail.php. 它也不适用于队列。

I created a package called multiMailto solve this.

我创建了一个名为multiMail的包来解决这个问题。

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

可以设置邮件地址和主机/提供商/用户名/密码等/config/multimail.php,然后可以使用发送邮件

\MultiMail::from('[email protected]')->send(new MailableDummy()));
\MultiMail::from('[email protected]')->send(new MailableDummy()));

or queue it

或排队

\MultiMail::from('[email protected]')->queue(new MailableDummy()));

回答by Jakub Adamec

For Laravel 6you should use it like this:

对于Laravel 6,您应该像这样使用它:

// Backup your default mailer
$backup = Mail::getSwiftMailer();

// Setup your gmail mailer
$gmail = new \Swift_SmtpTransport('smtp.gmail.com', 465, 'ssl');

// Set the mailer as gmail
Mail::setSwiftMailer(new \Swift_Mailer($gmail));

// Send your message
Mail::send();

// Restore your original mailer
Mail::setSwiftMailer($backup);

回答by Choxx

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

对于Laravel 7.x 版,您现在可以说明在发送电子邮件时要使用的邮件驱动程序。您只需要在app/config/mail.php. 配置完成后,您可以通过mailer()如下函数指定驱动程序的名称:

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

I hope it helps someone.

我希望它可以帮助某人。

回答by Tanju ?zsoy

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

更容易的是,在发送电子邮件之前,使用 config 完成邮件配置之后,执行以下代码:

app()->forgetInstance('swift.transport');
app()->forgetInstance('swift.mailer');
app()->forgetInstance('mailer');