多个邮件配置

时间:2014-10-24 11:15:14

标签: laravel laravel-4

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

现在,在我申请的某个时刻,我需要通过Gmail发送邮件。

我做了类似的事情:

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

这样做很有效,laravel总是使用mandrill配置。看起来他在脚本启动时启动了邮件服务,并忽略了执行过程中的任何操作。

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

7 个答案:

答案 0 :(得分:33)

您可以创建一个新的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);

答案 1 :(得分:8)

派对有点晚了,但只是想延长接受的答案并投入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

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

我的解决方案是将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);
        });
    }
}

然后将CustomMail更改为ConfigurableMailable而不是Mailable

class CustomMail extends ConfigurableMailable {}

这可确保即使在调用Mail::queue(new CustomMail())之前,也会在发送前设置每用户邮件设置。当然,您必须在某个时刻将当前用户注入CustomMail,Mail::queue(new CustomMail(Auth::user()))

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

希望你觉得它很有用!

答案 2 :(得分:3)

您可以设置动态邮件设置:

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']);

也许你可以在config / customMail.php中存储设置值,然后用Config :: get('customMail')

来检索它们

答案 3 :(得分:2)

对于 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);

答案 4 :(得分:1)

对于Laravel version 7.x,您现在可以指定要在发送电子邮件时使用的邮件驱动程序。您只需在config/mail.php中正确配置所有连接和凭据即可。配置完成后,您可以通过mailer()函数指定驱动程序的名称,如下所示:

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

我希望它能对某人有所帮助。

答案 5 :(得分:0)

在发送电子邮件之前,之后,之后执行以下代码更加容易 您已经使用config覆盖了邮件配置:

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

答案 6 :(得分:0)

按照Bogdan的解释,仅使用setSwiftMailer对我不起作用,因为这样fromadress选项仍然取自config/mail.php。因此,看起来好像是从旧地址发送过来的。更糟糕的是,这可能导致电子邮件将被标记为垃圾邮件,因为电子邮件客户端会注意到from地址可能与实际发送地址不匹配,因为spf记录不匹配等。

相反,我还必须创建一个新的Mailer对象,在其中指定from,然后从该Mailer对象发送它:

// Setup your gmail mailer
$transport = new Swift_SmtpTransport('**.mailout.server.de', 465, 'ssl');
$transport->setUsername('***');
$transport->setPassword('***');
// Any other mailer configuration stuff needed...

$swift_mailer = new Swift_Mailer($transport);

// create new mailer object to not use name/address from config/mail.php
$view = app()->get('view');
$events = app()->get('events');
$mailer = new \Illuminate\Mail\Mailer($view, $swift_mailer, $events);
$mailer->alwaysFrom('***', '**');
$mailer->alwaysReplyTo('**', '***');

$mail = new \App\Mail\Test;

$mailer->to('mail@mail.com')->send($mail);

这不适用于queue邮件。 以下行:

$mailer->to('mail@mail.com')->queue($mail);

将使用旧地址发送邮件,而不发送$mailer对象指定的邮件。如果您要发送延迟的邮件,则最好使用jobs而不是queue,如本article所述。