Как закрыть соединение Smtp в SwiftMailer

Я использую SwiftMailer для отправки писем с рабочего процесса редуктора. Я использую класс Swift_SmtpTransport для отправки писем.

Проблема заключается в том, что если этот рабочий процесс временно остается бездействующим, соединение SMTP SwiftMailer истекает. Теперь, когда приходит следующая работа, SwiftMailer не может отправлять электронные письма по истечении времени соединения.

В идеале я хотел бы закрыть соединение smtp после каждой работы. Я не могу найти api в классе, который делает это специально. Также не работает объект unset() поскольку это статический класс.

Solutions Collecting From Web of "Как закрыть соединение Smtp в SwiftMailer"

Существует грубый вариант: остановите транспорт явно. При последующих вызовах метода sendMail SwiftMailer проверяет, вверх ли транспорт (он не сейчас), и запустите его снова. IMNSHO, SwiftMailer должен перехватить тайм-аут SMTP и автоматически подключиться. Но на данный момент это обходное решение:

 function sendMail($your_args) { try{ $mailer = Swift_Mailer::newInstance($transport); $message = Swift_Message::newInstance('Wonderful Subject') ->setFrom(array('john@doe.com' => 'John Doe')) ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name')) ->setBody('Here is the message itself'); $result = $mailer->send($message); $mailer->getTransport()->stop(); } catch (Swift_TransportException $e) { //this should be caught to understand if the issue is on transport } catch (Exception $e) { //something else happened } } 

Я отправляю письма в цикле, и я улавливал Swift_TransportException и создавал новый экземпляр Swift_Mailer но это было неправильное исправление: проблема Swift_Mailer с транспортом , а не с почтовой программой . Решение состоит в том, чтобы выдать явный вызов Swift_SmtpTransport::stop() :

 foreach($recipients as $to => $body){ try{ $message->setTo($to); $message->setBody(body); $mailer->send($message); }catch(Swift_TransportException $e){ $mailer->getTransport()->stop(); sleep(10); // Just in case ;-) } } 

Таким образом, Swift обнаруживает, что почтовая программа остановлена ​​и автоматически запускается, поэтому она правильно восстанавливается из-за ошибок связи.

Я запускаю работника в бесконечном цикле, используя Swiftmailer и AWS SES. Я получал ошибку:

 Expected response code 250 but got code "421", with message "421 Timeout waiting for data from client. 

Решение для моего скрипта:

 $love = true; while($love) { $message = Message::to($record->to) ->from(array('no-reply@clouddueling.com' => $user->name())) ->reply(array($user->email => $user->name())) ->subject($record->subject) ->body($body->value) ->html(true) ->send(); if (! $message->was_sent()) throw new Swift_TransportException($errstr . ': ' . $errno); } 

Я получил то же исключение с командной строкой symfony2 при отправке большого количества писем с помощью SwiftMailer и AWS SES.

Я мог бы исправить свою проблему, каждый раз запуская и останавливая транспортный уровень. Посмотрите мое сообщение в блоге для получения дополнительной информации: http://www.prowebdev.us/2013/06/swiftmailersymfony2-expected-response.html

Когда труба сломана, $ mailer-> getTransport () -> stop () также не удастся. И из-за этой ошибки транспорт не может быть остановлен. Обходной путь

 // Let's try to send an email. $tries = 3; while ($tries--) { try { $sent = $this->mailer->send($message); break; } catch (\Exception $e) { // Connection problems // @see https://github.com/swiftmailer/swiftmailer/issues/490 try { // Try to stop $this->mailer->getTransport()->stop(); } catch (\Exception $e) { // Got Exception while stopping transport. // We have to set _started to 'false' manually, because due to an exception it is 'true' now. $t = $this->mailer->getTransport(); $reflection = new \ReflectionClass($t); $prop = $reflection->getProperty('_started'); $prop->setAccessible(true); $prop->setValue($t, false); $prop->setAccessible(false); } } }