Я немного отчаялся из-за проблемы на нашем веб-сервере. Наша сеть - это сообщество с множеством пользователей и активности. Мы отправляем пользователям персонализированные письма о деятельности, которая их интересует. У нас есть проблема в скрипте, который обрабатывает эти рассылки.
Наши Сценарий массовой рассылки не работает, когда нужно отправить тысячи писем. Обычно он работает нормально, но когда ему нужно отправить больше обычных писем (около 25000 писем), он неоднократно выдает исключение:
Unable to send mail. mail():
Could not execute mail delivery program '/usr/sbin/sendmail -t -i '
Странно то, что sendmail правильно работает в других процессах такой веб-сервер, и sendmail вызывается точно так же в PHP (Zend). Sendmail не работает в сценарии массовой рассылки PHP только в том случае, если много писем уже отправлено без ошибок. Когда выбрасывается первое исключение, следующие вызовы sendmail также терпят неудачу.. Кажется, что достигнут какой-то предел очереди, но только для этого процесса!
Основной цикл scipt рассылки PHP-сообщений выполняется тысячи раз. В каждом проходе цикла вызывает sendMail с разными $email
и $user
:
// Sometimes, hundred thousands iterations
foreach($notifications as $j => $notification){
...
$mail->setNotification($notification);
$this->sendMail($mail, $user);
...
}
$this->sendmail($mail, $user)
вызывает внутренний метод Zend для отправки почты. Он вызывает собственный метод PHP почта.
/**
* Send mail using PHP native mail()
*
* @access public
* @return void
* @throws Zend_Mail_Transport_Exception if parameters is set
* but not a string
* @throws Zend_Mail_Transport_Exception on mail() failure
*/
public function _sendMail()
{
...
set_error_handler(array($this, '_handleMailErrors'));
// CALL TO MAIL PHP NATIVE METHOD
$result = mail(
$this->recipients,
$this->_mail->getSubject(),
$this->body,
$this->header,
$this->parameters);
restore_error_handler();
}
if ($this->_errstr !== null || !$result) {
/**
* @see Zend_Mail_Transport_Exception
*/
require_once 'Zend/Mail/Transport/Exception.php';
// HERE THE EXCEPTION IS THROWN
throw new Zend_Mail_Transport_Exception('Unable to send mail. ' . $this->_errstr);
}
}
sendmail
БегУвидеть ps -aux | grep sendmail
вывод, когда scipt рассылки почты работает нормально
$ ps -aux | grep sendmail
root 6756 0.0 0.0 62240 2468 ? Ss 18:19 0:08 sendmail: MTA: accepting connections
root 25766 0.0 0.0 62668 3536 ? Ss 22:43 0:00 sendmail: MTA: ./r17Lh1fX025764 eml4.in.gr.: client DATA status
root 30978 0.0 0.0 62460 2876 ? Ss 22:46 0:00 sendmail: MTA: ./r17Lk8li030976 s1.m1r3.onet.pl.: user open
root 31462 0.0 0.0 62672 3536 ? Ss 22:46 0:00 sendmail: MTA: ./r17LkSIg031460 mx2.hotmail.com.: client DATA status
root 31474 0.0 0.0 62672 3540 ? Ss 22:46 0:00 sendmail: MTA: ./r17LkT54031472 mx2.hotmail.com.: client DATA status
root 31494 0.0 0.0 62668 4404 ? Ss 22:46 0:00 sendmail: MTA: ./r17LkUXC031492 gmail-smtp-in.l.google.com.: client RCPT
root 31498 0.0 0.0 62668 3536 ? Ss 22:46 0:00 sendmail: MTA: ./r17LkUn1031496 mx4.hotmail.com.: client DATA status
root 31502 0.0 0.0 62672 3536 ? Ss 22:46 0:00 sendmail: MTA: ./r17LkUti031500 mx3.hotmail.com.: client DATA status
root 31506 0.0 0.0 62672 3500 ? Ss 22:46 0:00 sendmail: MTA: ./r17LkUHw031504 mx4.hotmail.com.: client RCPT
root 31510 0.0 0.0 62672 3496 ? Ss 22:46 0:00 sendmail: MTA: ./r17LkUth031508 mx3.hotmail.com.: client MAIL
root 31514 0.0 0.0 62668 4436 ? Ss 22:46 0:00 sendmail: MTA: ./r17LkVPb031512 gmail-smtp-in.l.google.com.: client DATA status
root 31518 0.0 0.0 62460 2888 ? Ss 22:46 0:00 sendmail: MTA: ./r17LkV9o031516 mx1.hotmail.com.: client EHLO
root 31522 0.0 0.0 62668 4404 ? Ss 22:46 0:00 sendmail: MTA: ./r17LkVD4031520 gmail-smtp-in.l.google.com.: client RCPT
root 31526 0.0 0.0 62460 2852 ? Ss 22:46 0:00 sendmail: MTA: ./r17LkVcF031524 mx3.hotmail.com.: user open
Когда сценарий начинает генерировать исключения, ps -aux | grep sendmail
выводит почти пустой, как и ожидалось
$ ps -aux | grep sendmail
root 6756 0.0 0.0 62240 2468 ? Ss Feb07 0:49 sendmail: MTA: accepting connections
Я новичок в sendmail, поэтому ценю любую помощь. Если вам нужна дополнительная информация, сообщите мне.
Заранее спасибо за вашу помощь!
Когда ты звонишь mail()
в PHP в системе на основе Unix он разветвляет sendmail
command и передает каждого получателя в качестве аргумента в командной строке. тем не мение есть ограничение на длину аргументов, которые вы можете передать в командной строке! Это очень большой ограничение, 128 КБ по умолчанию в системах Linux, но 25 000 адресов электронной почты значительно превышают его.
Чтобы обойти эту проблему, отправляйте почту меньшими партиями, например 1000 получателей одновременно. Разделить массив получателей на группы по 1000 и просмотреть их в цикле покажется тривиальным, но если нет, посетите наш родственный сайт. Переполнение стека за помощь в программировании.
Однако ваш сообщение об ошибке похоже, указывает на то, что вы не прошли любой получатели сообщения. Так что вам, возможно, стоит поискать программную ошибку, в которой вы вызвали mail()
без recipients
или с недействительным recipients
.
Любая почтовая система перегружена моим слишком большим количеством писем за короткие промежутки времени. Возможно, вам следует остановиться на некоторое время после отправки пакета сообщений (скажем, каждые 100 или около того).
В любом случае вам следует внимательно посмотреть, что вы здесь делаете. Я очень сомневаюсь, что у вас есть тысячи важных сообщений к получателю отправить в то же время. Такое поведение приведет вас только в самые глубокие тайники всех черных списков электронной почты, известных человечеству.
Когда вы запускаете этот сценарий, запускаете ли вы его от имени другого пользователя, чем тот, от имени которого запускаются почтовые сценарии веб-сервера? Для пользователя, запускающего сценарий, это может быть что-то простое, например ulimit.