[英]How to set dynamic SMTP data in Laravel 5.4 for queued emails?
在我的应用程序中,每个用户都可以使用自己的SMTP服务器。 因此必须提供配置。 我正在使用Laravel Notifications发送电子邮件。 如果我不使用队列(这意味着同步),那就没有问题。
我做了一个CustomNotifiable特性:
config([
'mail.host' => $setting->smtp_host,
'mail.port' => $setting->smtp_port,
'mail.username' => $setting->smtp_username,
'mail.password' => $setting->smtp_password,
'mail.encryption' => $setting->smtp_encryption,
'mail.from.address' => $setting->smtp_from_address,
'mail.from.name' => $setting->smtp_from_name,
]);
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
之后,我恢复了原始配置:
config([
'mail' => $originalMailConfig
]);
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
到现在为止没有问题。 但是,如果已排队,则即使再提供其他SMTP配置,也将仅使用启动队列工作器之后的第一个配置来接收所有其他电子邮件。 config / mail.php中的默认配置将被覆盖。 但这仅是第一次。
我在AppServiceProvider :: boot方法中进行了设置(SMTP配置存储在通知中):
Queue::before(function (JobProcessing $event) {
// Handle queued notifications before they get executed
if (isset($event->job->payload()['data']['command']))
{
$payload = $event->job->payload();
$command = unserialize($payload['data']['command']);
// setting dynamic SMTP data if required
if (isset($command->notification->setting))
{
config([
'mail.host' => $command->notification->setting->smtp_host,
'mail.port' => $command->notification->setting->smtp_port,
'mail.username' => $command->notification->setting->smtp_username,
'mail.password' => $command->notification->setting->smtp_password,
'mail.encryption' => $command->notification->setting->smtp_encryption,
'mail.from.address' => $command->notification->setting->smtp_from_address,
'mail.from.name' => $command->notification->setting->smtp_from_name,
]);
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
}
}
});
当然,可以还原原始配置:
Queue::after(function (JobProcessed $event) use ($originalMailConfig) {
$payload = $event->job->payload();
$command = unserialize($payload['data']['command']);
// restore global mail settings
if (isset($command->notification->setting))
{
config([
'mail' => $originalMailConfig
]);
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
}
});
看起来,因为Swift Mailer具有缓存或类似的东西。 我注册了一个新的MailServiceProvider,它应该只替换旧的MailServiceProvider。 因此,如果我使用新的SMTP数据设置配置,则新的注册提供程序应使用它们。 记录配置,即使在TransportManager中,也正好在发送邮件之前设置了正确的SMTP数据,但是邮件是使用第一个设置的配置发送的。
我找到了该线程并尝试了链接的解决方案,但结果相同: 如何设置动态SMTP详细信息
因此,我需要一种方法来覆盖服务/ ServiceProvider / SMTP配置。 即使主管重新启动队列,也有可能同时发送多封配置不同的电子邮件。
在Laravel 5.4+中,我看到Mailer类是一个拥有MailTransport类的单例,后者负责SMTP邮件的配置,并且也是一个单例。 我只需要使用以下方法覆盖配置:
首先,我设置一个特征,以便可以在某些邮件上启用此功能:
trait MailSenderChangeable
{
/**
* @param array $settings
*/
public function changeMailSender($settings)
{
$mailTransport = app()->make('mailer')->getSwiftMailer()->getTransport();
if ($mailTransport instanceof \Swift_SmtpTransport) {
/** @var \Swift_SmtpTransport $mailTransport */
$mailTransport->setUsername($settings['email']);
$mailTransport->setPassword($settings['password']);
}
}
}
然后,在邮件类的build()方法中,您可以利用上述特征并调用:
$this->changeMailSender([
'email'=>$this->company->email,
'password'=>$this->company->email_password,
]);
景气,让Laravel休息吧。
经过大量研究,我偶然发现了不同的队列命令。 我尝试了queue:listen(在Laravel 5.4文档中没有描述)而不是queue:work,问题解决了。
当然,这并不能真正解释所描述的行为,但是幸运的是,这并不重要,因为我可以接受这种解决方案/解决方法。
另一个奇怪的行为是,由于数据库被锁定,队列工作人员有时会引发异常。 不知道,什么时候或为什么发生这种情况。
这篇文章稍微解释了为什么事情会发生: queue:work --daemon和queue:listen之间有什么区别?
简而言之,queue:listen解决了我的问题,也解决了另一个非常奇怪的数据库锁问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.