Я использую SwiftMailer для отправки писем с рабочего процесса редуктора. Я использую класс Swift_SmtpTransport
для отправки писем.
Проблема заключается в том, что если этот рабочий процесс временно остается бездействующим, соединение SMTP SwiftMailer истекает. Теперь, когда приходит следующая работа, SwiftMailer не может отправлять электронные письма по истечении времени соединения.
В идеале я хотел бы закрыть соединение smtp после каждой работы. Я не могу найти api в классе, который делает это специально. Также не работает объект unset()
поскольку это статический класс.
Существует грубый вариант: остановите транспорт явно. При последующих вызовах метода 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); } } }