Назад | Перейти на главную страницу

Исключение Sendmail возникло, когда тысячи писем были отправлены в скрипте массовой рассылки. Есть ли у sendmail лимит отправки электронной почты для данного процесса?

Я немного отчаялся из-за проблемы на нашем веб-сервере. Наша сеть - это сообщество с множеством пользователей и активности. Мы отправляем пользователям персонализированные письма о деятельности, которая их интересует. У нас есть проблема в скрипте, который обрабатывает эти рассылки.

Наши Сценарий массовой рассылки не работает, когда нужно отправить тысячи писем. Обычно он работает нормально, но когда ему нужно отправить больше обычных писем (около 25000 писем), он неоднократно выдает исключение:

Unable to send mail. mail():
Could not execute mail delivery program '/usr/sbin/sendmail -t -i '

Странно то, что sendmail правильно работает в других процессах такой веб-сервер, и sendmail вызывается точно так же в PHP (Zend). Sendmail не работает в сценарии массовой рассылки PHP только в том случае, если много писем уже отправлено без ошибок. Когда выбрасывается первое исключение, следующие вызовы sendmail также терпят неудачу.. Кажется, что достигнут какой-то предел очереди, но только для этого процесса!


Код PHP скрипта

Основной цикл 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.