как я могу исправить/избежать этой ошибки smtp с помощью swift_mailer?

Извините, возможно, это просто вопрос новичка, но вот, у меня есть скрипт, который перебирает группу (иногда тысячи) участников, отправляющих электронную почту, используя такой код:

    $transport = Swift_SmtpTransport::newInstance('...', 25)
                                ->setUsername('...')
                                ->setPassword('...');

                $mailer = Swift_Mailer::newInstance($transport);
                $mailer->send($message);

и обычно это работает хорошо, но иногда я получаю эту ошибку: Ожидаемый код ответа 354, но получен код "250" с сообщением "250 2.1.5... Получатель в порядке"

Я плохо знаю smtp, поэтому я могу только догадываться, что происходит: код 354 ожидается в начале процесса отправки почты, но код 250 получен из последнего отправленного электронного письма, поэтому почтовая программа перегружается. используется слишком быстро, я думаю, я должен ждать, пока каждое электронное письмо будет действительно завершено (т.е. дождаться кода 250), прежде чем отправлять следующее. Я бы не хотел просто вставлять команду сна после каждого письма, так есть ли лучший способ защититься от этой ошибки? Или причина в другом?

Спасибо


person lost baby    schedule 08.06.2012    source источник
comment
Я иногда добавлял $mailer-›disconnect() — sleep — reconnect, но это выдает ошибку: PHP Неустранимая ошибка: вызов неопределенного метода Swift_Mailer::disconnect(), я думаю, что disconnect() не является частью API в быстрая почтовая программа 4.0.5. Есть ли другой метод?   -  person lost baby    schedule 08.06.2012


Ответы (1)


Подводя итог:

  1. Основное изменение: повторное использование вашего почтового соединения и, желательно, создание сообщения, поэтому это делается только по мере необходимости, обычно только один раз.
  2. Проверьте, как вы создаете экземпляр SwiftMailer, и подтвердите, что это наиболее оптимальный способ.
  3. Ваша версия класса SwiftMailer кажется немного устаревшей (4.0.5), вы можете проверить более новую версию

Подробнее:

Повторное использование экземпляров объектов. Вы каждый раз заново создаете свой почтовый транспорт, что приводит к накладным расходам. Вы не должны этого делать. Вы можете использовать batchSend() для больших пакетов писем, если он поддерживается. См. пример использования в этом вопросе. Прикладной пример:

$message = Swift_Message::newInstance(...)
  ->setSubject('A subject')
  ->setFrom(array('[email protected]' => 'From Me'))
  ->setBody('Your message')
;

while(list($targetadd, $targetname) = each($targetlist))
{
   $message->addTo($targetadd, $targetname);
}

$message->batchSend();

Обратите внимание, что функция batchSend() была удалена в версии 4.1.0 RC1 SwiftMailer. . Насколько мне известно, он внутренне вызывает send() в цикле, поэтому вы должны иметь возможность иметь те же эффекты, вызывая send() несколько раз, но повторно используя, по крайней мере, ваш почтовый транспорт, чтобы вы не создавали его каждый раз (и, если применимо, также создавали сообщение).

Из примера пакетной отправки в официальной документации вы можете отправлять электронные письма в пакете, используя send() с

// Create the Transport
$transport = Swift_SmtpTransport::newInstance('localhost', 25);

// Create the Mailer using your created Transport
$mailer = Swift_Mailer::newInstance($transport);

// Create a message
$message = Swift_Message::newInstance('Wonderful Subject')
  ->setFrom(array('[email protected]' => 'John Doe'))
  ->setBody('Here is the message itself')
  ;

// Send the message
$failedRecipients = array();
$numSent = 0;
$to = array('[email protected]', '[email protected]' => 'A name');

foreach ($to as $address => $name)
{
  if (is_int($address)) {
    $message->setTo($name);
  } else {
    $message->setTo(array($address => $name));
  }

  $numSent += $mailer->send($message, $failedRecipients);
}

Транспортные протоколы. Следует также отметить, что SwiftMailer является классом-оболочкой. Что он на самом деле использует под капотом, это то, что вы определяете. В вашем случае вы используете SMTP-транспорт, который лучше, чем почтовый транспорт (функция mail()), но, возможно, не самый оптимальный.

Вы не говорите, хотите ли вы явно использовать это и какая среда у вас есть, но в среде Linux вы можете напрямую вызывать sendmail с помощью чего-то вроде

$transport = Swift_SendmailTransport::newInstance('/usr/sbin/sendmail -bs');

Что может дать лучшую производительность. Дополнительную информацию о различных транспортных средствах можно найти в документации по использованию SwiftMailer.

Версия класса. Судя по вашему комментарию, вы используете версию 4.0.5. Текущая версия — 4.1.8., и есть некоторые изменения. так как с пакетной отправкой, так что вы можете проверить это тоже.

РЕДАКТИРОВАТЬ: обновлена ​​информация о batchSend(), текущей версии и ручных ссылках.

person eis    schedule 18.06.2012
comment
спасибо за ответ, я использую smtp, так как это стандартный способ, которым его используют другие наши скрипты, и, похоже, это рекомендуется в документации по быстрой рассылке. Я только время от времени воссоздаю объекты транспорта и почтовой программы и только начал это делать, пытаясь решить эту проблему, но я знаю, что это выглядит так, как будто я делаю это каждый раз в своем фрагменте кода. Таким образом, мой код в основном соответствует тому, что вы предлагаете, за исключением того, что я воссоздаю большую часть сообщения каждый раз, поскольку оно зависит от получателя. Я рассмотрю возможность обновления до последней версии, но мне нужно попросить системного администратора сделать это. - person lost baby; 19.06.2012
comment
ну, вы могли бы хотя бы попытаться увидеть, имеет ли значение использование другого транспорта - это поможет сузить проблему. - person eis; 23.06.2012
comment
Я также воссоздаю объекты транспорта и почтовой программы при возникновении ошибки и запускаю вызов sleep(30) после каждой ошибки, чтобы дать smtp-серверу время наверстать упущенное. Пока это работает достаточно хорошо. Попробую другой метод транспортировки, когда у меня будет еще один шанс вернуться к этой проблеме. Спасибо айс. - person lost baby; 25.06.2012