Laravel:可以延迟发送通知,但是可以动态更改smtp设置吗?

时间:2019-02-17 15:17:59

标签: laravel laravel-mail laravel-notification

我正在使用Laravel v5.7开发多租户(多个数据库),并且成功发送了队列电子邮件。

在某些特定情况下,我想发送带有“延迟”的按需通知,类似于指南On-Demand Notifications,但通知发送前应使用的SMTP设置。

我已经开发了一个可更改config()值的类。

app / Tenant / SmtpConfig.php

class SmtpConfig
{
    public static function setConnection(SmtpConta $conta = null)
    {
        // get connection default settings
        $config = config()->get("mail");

        // populate connection default settings
        foreach ($config as $key => $value) {
            if ( $key == 'host' )      { $config[$key] = $conta->mail_host ?? $config[$key]; }
            if ( $key == 'from' )      { $config[$key] = [
                'address' => ( $conta->mail_host === 'smtp.mailtrap.io' ) ? $config[$key]['address'] : $conta->mail_username,
                'name' => $conta->conta ?? $config[$key]['name']
            ]; }
            if ( $key == 'username' )  { $config[$key] = $conta->mail_username ?? $config[$key]; }
            if ( $key == 'password' )  { $config[$key] = !empty($conta->mail_password) ? $conta->mail_password : $config[$key]; }
        }

        $config['encryption'] = ( $conta->mail_host === 'smtp.mailtrap.io' ) ? null : 'ssl';

        // set connection default settings
        config()->set("mail", $config);
    }

}

...,我在通知中将此SmtpConfig类称为:

/**
  * Create a new notification instance.
  *
  * @param $conta
  * @param $subject
  * @return void
  */
  public function __construct(SmtpConta $conta = null, $subject = null)
  {
        $this->conta = $conta;
        $this->subject = $subject;

        $when = \Carbon\Carbon::now()->addSecond(100);

        $this->delay($when);

        app(\App\Tenant\SmtpConfig::class)::setConnection($this->conta);
  }

我可以成功发送“延迟”通知,但是显然,它始终使用.env文件的默认值。

现在,我不确定在什么地方调用该类是否有意义,甚至不确定如何通知该通知应使用哪种SMTP配置。

2 个答案:

答案 0 :(得分:1)

在使用Notification backport库的Laravel 5.2代码库上,我目前正面临类似的挑战。

这是我解决方案的一个示例,类似于Kit Loong的建议。我们只扩展Illuminate\Notifications\Channels\MailChannel类并覆盖send()方法。

您将需要能够从收件人或通知对象中确定SMTP配置,因此您需要根据需要编辑我的示例。

这也假设您的应用使用默认的Swift_Mailer,因此YMMV ...

<?php

declare (strict_types = 1);

namespace App\Notifications\Channels;

use Illuminate\Notifications\Channels\MailChannel;
use Illuminate\Notifications\Notification;

class DynamicSmtpMailChannel extends MailChannel
{
    /**
     * Send the given notification.
     *
     * @param  mixed  $notifiable
     * @param  \Illuminate\Notifications\Notification  $notification
     * @return void
     */
    public function send($notifiable, Notification $notification)
    {
        //define this method on your model (note $notifiable could be an array or collection of notifiables!)
        $customSmtp = $notifiable->getSmtpConfig(); 

        if ($customSmtp) {
            $previousSwiftMailer = $this->mailer->getSwiftMailer();

            $swiftTransport = new \Swift_SmtpTransport(
                $customSmtp->smtp_server, 
                $customSmtp->smtp_port,
                $customSmtp->smtp_encryption
            );
            $swiftTransport->setUsername($customSmtp->smtp_user);
            $swiftTransport->setPassword($customSmtp->smtp_password);

            $this->mailer->setSwiftMailer(new \Swift_Mailer($swiftTransport));
        }

        $result = parent::send($notifiable, $notification);

        if (isset($previousSwiftMailer)) {
            //restore the previous mailer
            $this->mailer->setSwiftMailer($previousSwiftMailer);
        }

        return $result;
    }
}

保留短暂的自定义swift邮件的临时存储也可能是有益的,这样您就可以在相同的调用/请求(考虑长期运行的工人)中重复使用它们-就像一个集合类,其中smtp配置的哈希值用作项目键。

祝你好运。

编辑: 我可能应该提到您可能需要将此绑定到服务容器中。这样的东西就足够了:

// in a service provider
public function register()
{
    $this->app->bind(
        \Illuminate\Notifications\Channels\MailChannel::class
        \App\Notifications\Channels\DynamicSmtpMailChannel::class
    );
}

或者,将其注册为单独的通知渠道。

答案 1 :(得分:0)

我想您也可以参考此实现。

https://stackoverflow.com/a/46135925/6011908

您可以通过传递自定义的smtp配置来执行。

$transport = new Swift_SmtpTransport(
    $customSmtp->host, 
    $customSmtp->port, 
    $customSmtp->encryption
);