2017-07-26 1 views
0

In meiner Anwendung kann jeder Benutzer seinen eigenen SMTP-Server verwenden. Dazu muss die Config bereitgestellt werden. Ich benutze Laravel Benachrichtigungen, um die E-Mails zu senden. Wenn ich keine Warteschlange benutze (das bedeutet Synchronisierung), gibt es kein Problem.Wie werden dynamische SMTP-Daten in Laravel 5.4 für E-Mails in der Warteschlange festgelegt?

machte ich einen CustomNotifiable Trait:

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

Danach habe ich die ursprüngliche Konfiguration wiederherzustellen:

 config([ 
      'mail' => $originalMailConfig 
     ]); 

     (new \Illuminate\Mail\MailServiceProvider(app()))->register(); 

Kein Problem bis jetzt. Aber wenn es in die Warteschlange gestellt wird, wird nur die erste Konfiguration nach dem Start des Warteschlangen-Workers für alle weiteren E-Mails übernommen, selbst wenn eine andere SMTP-Konfiguration bereitgestellt wird. Die Standardkonfiguration von config/mail.php wird außer Kraft gesetzt. Aber das funktioniert nur das erste Mal.

Ich habe in der AppServiceProvider :: Boot-Methode vorgenommen (die SMTP-Konfiguration an der Meldung gespeichert ist):

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

    }); 

It:

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

    }); 

Natürlich erhalten die ursprüngliche Konfiguration wiederhergestellt scheint, als der Swift Mailer einen Cache oder etwas ähnliches hat. Ich habe einen neuen MailServiceProvider registriert, der einfach den alten ersetzen sollte. Wenn ich also die Konfiguration mit den neuen SMTP-Daten einstelle, sollte der neue registrierte Provider sie übernehmen. Das Protokollieren der Konfiguration zeigt selbst im TransportManager, dass die korrekten SMTP-Daten eingestellt wurden, direkt bevor die Mail gesendet wurde, aber die Mail wurde mit der ersten Set-Konfiguration gesendet.

fand ich diesen Thread und versuchte, die verknüpfte Lösung, aber mit dem gleichen Ergebnis: How to set dynamic SMTP details laravel

Also muß ich einen Weg, um das Service/Serviceprovider/SMTP Konfiguration außer Kraft zu setzen. Selbst wenn der Supervisor die Warteschlange neu startet, besteht die Möglichkeit, dass mehrere E-Mails mit unterschiedlichen Konfigurationen gleichzeitig gesendet werden.

Antwort

0

Nach vielen Recherchen stolperte ich über die verschiedenen Warteschlangenbefehle. Ich habe versucht, Warteschlange: zu hören (was nicht in der Laravel 5.4 Docs beschrieben wird) statt Warteschlange: Arbeit und die Probleme sind weg.

Natürlich erklärt das nicht wirklich das beschriebene Verhalten, aber zum Glück ist es egal, weil ich mit dieser Lösung/Workaround leben kann.

Ein anderes seltsames Verhalten ist, dass der Warteschlangen Worker von Zeit zu Zeit eine Ausnahme auslöst, weil die Datenbank gesperrt war. Keine Ahnung, wann oder warum das passiert ist.

Dieser Beitrag erklärt ein wenig, warum Dinge passieren kann: What is the difference between queue:work --daemon and queue:listen

Auf den Punkt gebracht, Warteschlange: mein Problem und eine andere sehr seltsam db Sperre Problem auch gelöst mitzuhören.

0

In Laravel 5.4+, wie ich sehe, dass die Mailer-Klasse ein Singleton ist, der eine MailTransport-Klasse enthält, die für die Konfiguration von SMTP-Mail verantwortlich ist und auch ein Singleton ist; Ich muss nur noch die Config außer Kraft setzen mit dem folgenden Ansatz:

Zuerst habe ich Setup eine Eigenschaft, so kann ich nur diese Funktion aktivieren einigen Mails:

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

Dann wird in dem Build() -Methode Ihrer Mail-Klasse, können Sie das oben genannte Merkmal verwenden und rufen Sie:

$this->changeMailSender([ 
     'email'=>$this->company->email, 
     'password'=>$this->company->email_password, 
    ]); 

Boom, lass den Laravel den Rest tun.

+0

Auf diese Weise, können Sie den Port und den Host, genau wie die E-Mail und das Passwort einstellen? – iglesiasedd

+1

natürlich Mann, bitte lesen Sie die Implementierung der Klasse, bitte. <.project> /vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php Diese Methoden sind $ mailTransport-> setHost ('Host'), $ mailTransport-> setPort ('1234') –

Verwandte Themen