【问题标题】:Sendmail Exception reached when thousands emails sent in bulk mail script. Has sendmail a email-sent limit for a given process?当以批量邮件脚本发送数千封电子邮件时,Sendmail 出现异常。 sendmail 是否对给定进程设置了电子邮件发送限制?
【发布时间】:2013-02-19 20:17:18
【问题描述】:

我对我们的网络服务器中的问题感到有些绝望。我们的网络是一个拥有大量用户和活动的社区。我们向用户发送他们感兴趣的活动的个性化邮件。我们处理这些邮件的脚本有问题。

我们的批量电子邮件脚本在有数千封电子邮件要发送时失败。它通常可以正常工作,但是当它必须发送比平常更多的电子邮件(大约 25.000 封电子邮件)时,它会反复抛出异常:

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

奇怪的是sendmail在其他进程中正常工作比如web服务器,sendmail在PHP(Zend)中的调用方式是一样的。当大量电子邮件已经发送且没有错误时,Sendmail 只会在 PHP 批量邮件脚本中失败。 当第一个异常被抛出时,下一次对 sendmail 的调用也会失败。似乎已经达到了一些队列限制,但仅限于此进程!


PHP脚本代码

PHP 批量邮件 scipt 主循环执行了数千次。在每个循环中,使用不同的 $email$user 调用 sendMail:

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

$this->sendmail($mail, $user) 调用 Zend 内部方法发送邮件。它调用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);
    }
}

进程sendmail正在运行

当批量邮件 scipt 工作正常时查看ps -aux | grep sendmail 输出

$ 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 的新手,所以我感谢任何形式的帮助。如果您需要更多信息,请告诉我。

  • 简单来说,sendmail 是如何发送邮件的?
  • sendmail 是否有发送邮件的限制(我们的服务器是专用的,没有托管服务提供商设置的具体限制)?
  • sendmail 是否有任何进程队列来限制给定进程可以发送的邮件数量?
  • 百万美元问题:为什么会抛出异常以及如何解决? :-)

提前感谢您的帮助!

【问题讨论】:

  • 请不要交叉发布到多个 Stack Exchange 站点。相反,选择一个最合适的网站并在那里发布。

标签: zend-framework exception sendmail transactional-email bulk-mail


【解决方案1】:

每发送一封电子邮件,您就创建一个 sendmail 进程。 25_000 封电子邮件可能会为您的计算机创建太多进程来处理。

附: 您可以尝试在 news:comp.mail.sendmail 中提出您的问题 - 添加一些内容以表明它不是“有问题的垃圾邮件发送者”问题。

【讨论】:

  • 谢谢!我已经重写了这个问题。如您所见,我们不是垃圾邮件发送者,或者尽量不要成为:-)。请澄清我如何在 news:comp.mail.sendmail 提问
【解决方案2】:

sendmail 如何发送邮件?

这不是一个短篇小说。 无论如何,为了减少 sendmail 进程的数量,您可以将您的 php 配置为通过 smtp 协议发送到 127.0.0.1 上的端口 25(环回接口)。 它将创建“由 root 拥有”的 sendmail 进程。

您还应该定义 confDELAY_LA、confQUEUE_LA(延迟

confDELAY_LA 会在系统平均负载高于配置限制时减慢接受新邮件的速度。它可能/将使您的脚本运行时间更长。

confQUEUE_LA 跳过“一次”传递尝试 - 您很可能应该增加队列运行器进程的数量。

简而言之:您将您的 sendmail 服务器推送到超出限制的标准简单 配置被认为可以轻松处理。

【讨论】:

  • 在我们的 sendmail.mc 中:FEATURE(`conncontrol', `nodelay', `terminate')dnlFEATURE(`ratecontrol', `nodelay', `terminate')dnl
  • 您对我们的方案有何建议?谢谢!
  • conncontrol & ratecontrol - 如果您在访问表 (/etc/mail/access) 中有条目将其关闭以用于环回地址,这并不重要。例如“clientrate:127 0”和“clientcon:127 0”。
  • 我建议 1) 将 php 转换为 smtp 127.0.0.1:25 2) 在 sendail 配置中增加(经过一些测试)confQUEUE_LA - 我认为许多现代服务器可以处理更高的负载,尤其是在 Linux 中计算 LA另一种给出更高值的方法 3) IF "mailq" 将报告队列中的许多消息 THEN 增加队列目录的数量 - sendmail.org/~gshapiro/8.10.Training/mqueue.html - 使用 /var/spool/mqueue* 与名为 /var/spool/mqueue1 /var/spool 的额外目录/mqueue2 .... ;第一次尝试不要创建超过 3 个额外的目录
猜你喜欢
  • 1970-01-01
  • 2013-12-22
  • 2017-01-20
  • 2018-07-22
  • 1970-01-01
  • 1970-01-01
  • 2011-03-03
  • 2018-10-17
相关资源
最近更新 更多