Laravel: Можно ли отправлять уведомления с задержкой, но динамически менять настройки smtp? - PullRequest
0 голосов
/ 17 февраля 2019

Я разрабатываю Multi Tenant (несколько баз данных) с Laravel v5.7, и я успешно отправляю электронные письма в очереди.

В некоторых конкретных ситуациях я хотел бы отправлять уведомления по требованиюс 'delay', аналогично руководству Уведомления по требованию , но с указанием настроек SMTP, которые следует использовать перед отправкой.

Я разработал класс, который изменяет значения конфигурации().

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 голосов
/ 01 марта 2019

В настоящее время я сталкиваюсь с аналогичной проблемой на базе кода Laravel 5.2 с использованием библиотеки бэкпорта уведомлений.

Это пример моего решения, аналогичного предложению Кит Луна.Мы просто расширяем класс 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;
    }
}

Также может быть полезно сохранить кратковременный запаснастраиваемые быстрые почтовые программы, так что вы можете повторно использовать их в одном и том же вызове / запросе (подумайте о долго работающих работниках) - как в классе коллекции, где в качестве ключа элемента используется хэш конфигурации smtp.

Наилучшийудачи с ним.

Редактировать: Я, вероятно, должен упомянуть, что вам может понадобиться связать это в контейнере службы.Что-то вроде этого должно быть достаточно:

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

Или, в качестве альтернативы, зарегистрируйте его как отдельный канал уведомлений.

0 голосов
/ 17 февраля 2019

Я думаю, вы также можете обратиться к этой реализации.

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

Вы можете выполнить, передавая пользовательские конфигурации smtp.

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