Sendmail Exceção alcançada quando milhares de e-mails são enviados em script de e-mail em massa. O sendmail tem um limite enviado por email para um determinado processo?

1

Estou um pouco desesperado com um problema no nosso servidor web. Nossa web é uma comunidade com muitos usuários e atividades. Enviamos aos usuários e-mails personalizados da atividade de seu interesse. Temos um problema no script que lida com essas correspondências.

Nosso script de e-mail em massa falha quando tem milhares de e-mails para enviar . Geralmente funciona bem, mas quando tem que enviar mais do que os e-mails usuais (aprox. 25.000 e-mails), ele lança uma Exceção repetidamente:

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

O mais estranho é que o sendmail funciona corretamente em outros processos como o servidor web, e o sendmail é chamado da mesma forma no PHP (Zend). O Sendmail só falha no script de e-mail em massa do PHP quando muitos e-mails já foram enviados sem erros. Quando a primeira exceção é lançada, as próximas chamadas para o sendmail também falham . Parece que algum limite de fila foi atingido, mas apenas para este processo!

Código do script PHP

O loop principal do scipt de e-mail em massa do PHP é executado milhares de vezes. Em cada passagem de loop chama o sendMail com um diferente $email e $user :

// Sometimes, hundred thousands iterations
foreach($notifications as $j => $notification){
    ...
    $mail->setNotification($notification);
    $this->sendMail($mail, $user);
    ...          
}

$this->sendmail($mail, $user) chama o método interno do Zend para enviar email. Ele chama o método nativo do PHP mail .

/**
 * 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);
    }
}

Processa sendmail executando

Veja a saída ps -aux | grep sendmail quando a mensagem de correio em massa está funcionando bem

$ 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

Quando o script começa a gerar exceções, ps -aux | grep sendmail produz quase vazio, como esperado

$ ps -aux | grep sendmail
root      6756  0.0  0.0  62240  2468 ?        Ss   Feb07   0:49 sendmail: MTA: accepting connections     

Algumas perguntas

Sou novato no sendmail, por isso agradeço qualquer tipo de ajuda. Se você precisar de mais informações, por favor me diga.

  • Resumidamente, como o sendmail funciona para enviar e-mails?
  • O sendmail tem um limite de emails para enviar (nosso servidor é dedicado e não tem restrições específicas definidas pelo provedor de hospedagem)?
  • O sendmail tem alguma fila de processos que limite o número de e-mails que podem ser enviados por um determinado processo?
  • Pergunta de um milhão de dólares: por que a exceção está sendo lançada e como resolvê-la? : -)

Agradecemos antecipadamente por sua ajuda!

    
por Emilio Nicolás 05.03.2013 / 13:42

3 respostas

3

Quando você chama mail() em PHP em um sistema baseado em Unix, ele bifurca o comando sendmail e passa cada destinatário como um argumento na linha de comando. No entanto, existe um limite para o tamanho dos argumentos que você pode realmente passar na linha de comando ! É um limite muito grande , 128 KiB por padrão nos sistemas Linux, mas 25.000 endereços de e-mail excedem muito.

Para contornar esse problema, envie seu e-mail em lotes menores, por exemplo, 1.000 destinatários por vez. Você deve achar trivial dividir sua matriz de destinatários em grupos de 1.000 e passá-los por eles, mas se não, visite nosso estouro de pilha . ajuda de programação.

No entanto, sua mensagem de erro parece indicar que você não transmitiu nenhum destinatário para a mensagem. Talvez você deva procurar um erro de programação no qual chamou mail() sem recipients ou com recipients inválido.

    
por 05.03.2013 / 13:49
0

Quando você está executando esse script, você o está executando como um usuário diferente daquele em que os scripts de correio do servidor da Web são executados? Pode ser algo tão simples quanto o ulimit para o usuário que está executando o script.

    
por 05.03.2013 / 14:16
0

Qualquer sistema de e-mail está sobrecarregado com minhas muitas mensagens de e-mail em uma curta sucessão. Talvez você deva parar um pouco depois de enviar um lote de mensagens (digamos a cada 100 ou mais).

Em qualquer caso, você deve revisar com atenção o que está fazendo aqui com cuidado. Duvido muito que você tenha milhares de mensagens importantes para o destinatário para enviar ao mesmo tempo. Tal comportamento só vai levá-lo para os recessos mais profundos de todas as listas negras de e-mail conhecidas pela humanidade.

    
por 05.03.2013 / 14:52