Как закрыть соединение Smtp в SwiftMailer
Я использую SwiftMailer для отправки писем от рабочего процесса редуктора. Я использую класс Swift_SmtpTransport
для отправки писем.
Проблема заключается в том, что если этот рабочий процесс временно остается бездействующим, соединение SMTP SwiftMailer истекает. Теперь, когда приходит следующая работа, SwiftMailer не может отправлять электронные письма по истечении времени ожидания подключения.
В идеале я хотел бы закрыть соединение smtp после каждой работы. Я не могу найти api в классе, который делает это специально. Также не работает объект unset()
, так как это статический класс.
Ответы
Ответ 1
Существует грубая опция: запретить перенос явно. При последующих вызовах метода sendMail SwiftMailer проверяет, вверх ли транспорт (он не сейчас), и запустите его снова.
IMNSHO, SwiftMailer должен перехватить тайм-аут SMTP и автоматически подключиться. Но на данный момент это обходной путь:
function sendMail($your_args) {
try{
$mailer = Swift_Mailer::newInstance($transport);
$message = Swift_Message::newInstance('Wonderful Subject')
->setFrom(array('[email protected]' => 'John Doe'))
->setTo(array('[email protected]', '[email protected]' => '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
}
}
Ответ 2
Я отправляю письма в цикле, и я ловил Swift_TransportException
и создавал новый экземпляр 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 обнаруживает, что почтовая программа остановлена и запускает ее автоматически, поэтому она правильно восстанавливается из-за ошибок связи.
Ответ 3
Я получил то же самое исключение с командной строкой symfony2 при отправке большого количества писем с помощью SwiftMailer и AWS SES.
Я мог бы исправить свою проблему, каждый раз запуская и останавливая транспортный уровень. Посмотрите на мое сообщение в блоге для более подробной информации: http://www.prowebdev.us/2013/06/swiftmailersymfony2-expected-response.html
Ответ 4
Когда труба сломана, $mailer- > getTransport() → stop() также не удастся. И из-за этой ошибки транспорт не может быть остановлен. Обходной путь
// Let 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);
}
}
}
Ответ 5
Я запускаю рабочего в бесконечном цикле, используя Swiftmailer и AWS SES. Я получал ошибку:
Expected response code 250 but got code "421", with message "421 Timeout waiting for data from client.
Решение для моего script:
$love = true;
while($love) {
$message = Message::to($record->to)
->from(array('[email protected]' => $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);
}