发送电子邮件时使用Gmail SMTP的PHPMailer速度较慢

我发现有几个旧线程有类似的问题,但其中大多数没有答案,如果他们有,这些build议与我的情况不相关。

我有一个完整的设置与PHP邮件function一点,它的工作很好。 我必须格式化我的硬盘驱动器,并从头开始设置服务器。 之后,PHP邮件function变慢了。 在研究解决scheme时,我发现大多数人都推荐PHPMailer。 我切换到,但问题仍然存在。

大多数时候,我每个页面发送至less两封不同的邮件,但使用同一个对象。 大约有3-4秒的延迟。 请在下面find相关代码($ email1和$ email2是包含有效电子邮件地址的数组):

function sendEmail ($email1, $subject1, $message1, $email2, $subject2, $message2) { require_once('../PHPMailer/class.phpmailer.php'); $mail = new PHPMailer(); $mail->IsSMTP(); $mail->SMTPDebug = 0; $mail->SMTPAuth = true; $mail->SMTPSecure = 'ssl'; $mail->Host = "smtp.gmail.com"; $mail->Port = 465; $mail->IsHTML(true); $mail->Username = $gmail_username; $mail->Password = $gmail_password; $mail->SetFrom($gmail_address,$email_title); $mail->Subject = $subject1; $mail->Body = $message1; foreach($email1 as $k => $v) { $mail->AddAddress($v); } if(!$mail->Send()) { $emailreturn['cust'] = 0; } else { $emailreturn['cust'] = 1; } $mail->ClearAddresses(); $mail->Subject = $subject2; $mail->Body = $message2; foreach($email2 as $k => $v) { $mail->AddAddress($v); } if(!$mail->Send()) { $emailreturn['partner'] = 0; } else { $emailreturn['partner'] = 1; } $mail->ClearAddresses(); } 

我没有看到任何错误,通过debugging和消息,它只是比平时发送电子邮件。

我试过了:

  • 我关掉防火墙只是为了testing它,它是一样的。
  • 切换到“tls”,这使得它更慢
  • 使用对象发送每封电子邮件,每个电子邮件延迟3-4秒
  • 用可选的configuration玩,注释掉或设置为false,所有的结果都一样

在邮件程序设置中是否还有其他缺失,或者是否有一些我应该检查的幕后configuration? 谢谢

缓慢(或由于超时而失败)是因为Google支持IPv6寻址,但是您的网络不支持。 (例如,Digital Ocean目前还不支持SMTP流量的IPv6)。 所以,使用这个:

 $mail->Host = gethostbyname("smtp.gmail.com"); 

gethostbyname()将返回IPv4地址。

对我来说,我的PHPMailer脚本从2分钟的执行时间变成<4秒

如果发送电子邮件之间的延迟真的是一个关键问题,你有没有考虑实施一种多线程的形式? 每个消息的延迟可能是相同的,但是如果您一次发送两个enails,它本质上会被减半。

一个简单的方法就是实现一个队列,并通过非阻塞的HTTP / SQL调用发送消息。 通过这种方式,您可以尽可能多地发送尽可能多的延迟。

我还建议,如果可能的话,找到具有最低延迟的Gmail服务器,并将其添加到您的主机文件,以消除DNS查找。

还有一些性能提示:你只需要require_once()作为包含文件,但是你需要在每次调用时(include_once()更快)。 为什么不创建一个$邮件对象只有一次,并重复使用它,只要你需要调用sendemail()?

为什么不把message1,subject1等作为一个数组传递给message2,subject2等作为第二个数组? 在一般的程序调用中(至少在经典的编程中)传递少量的参数往往会加快速度。

顺便说一句 – 不知道这是否可能 – 也许有一种方法可以保持与smtp.gmail.com的连接。 这也会消除很多开销。

另外,通过你自己的小型服务器来传递你的消息一个选项? 这会消除延误。

最后,我遇到了Google的这个回应:[ Gmail发送限制 `

 Thank you for your message. I understand you have a query regarding the Google Apps for Business sending limits. As mentioned in our Help Center article at http://support.google.com/a/bin/answer.py?hl=en& answer=166852, the daily limitation is 2000 messages in a 24-hour period not day. In general, our servers can tolerate one message per second until sending limits are hit. We really don't have an hourly or minute limitation for sending. If you send messages too quickly you may get rate-limited but the account should not lock out. By rate-limt, since in general one message per second, if you try to send too many messages per second you may get a message telling you that the message cannot be send or you must wait before sending a message. ` 

如果你需要的话,我会很乐意写一个符合这些限制的课程。 请让我知道,不要花太长的时间。

建议:使用另一个电子邮件主机/中继

发送电子邮件通常是一个缓慢的活动。 无论出于什么原因(网络流量,流量优先级,邮件服务器守护进程等),都需要很长时间。 处理电子邮件流量的一种方法是不要将其与您生成的响应一致发送。 更好的解决方案是异步执行。 上面的一个建议(使用工作队列并使用cron作业来清空工作队列)是很好的。 唯一的警告(取决于流量)是发送工作队列中的所有电子邮件的时间可能大于cron任务之间的时间间隔。

另一个选择(这是我的首选)是使用像Rabbit MQ(可能更好的书/主题上的帖子)或Zero MQ(如果你是一个更坚实的程序员)的消息层。 在这种情况下,您将创建一个事件“send-email”并将其推送到队列中。 有多个队列监听器。 一旦你的PHP脚本推送电子邮件发送到队列,它已经完成并继续前进。 其中一个队列监听器接收消息并发送电子邮件。

这可以使您在构建解决方案时拥有极大的灵活性。 由于大多数时间发送电子邮件似乎是等待时间,你可以运行10个消费者程序发送电子邮件,知道大部分时间单个发件人将闲置。 (这是我的发送电子邮件的经验是等待时间长,但CPU负载不高)。 通过运行固定数量的消费者(您的PHP脚本是生产者),您可以限制发送邮件/投入系统资源发送邮件的速度。

我已经实现了这种方法的变体,最重要的是可以使用相同的模式处理需要发生的其他事情,比如调整图像大小。 随着您的成长,您只需通过启动这些机器上的使用者就可以将部分工作转移到其他机器上。

从您拥有PHPMailer托管的服务器,请尝试:

 telnet smtp.gmail.com 465 

您会看到在服务器和smtp.gmail.com之间建立连接需要多长时间

删除客户端到服务器等待的解决方案之一是将发送电子邮件移动到crontab。 所以当客户端点击发送时,PHP将电子邮件和消息添加到队列中,然后每分钟通过cron发送排队的消息。

另外,您可以通过$start = microtime(true);来将调试信息添加到您的脚本中$start = microtime(true); 在脚本的顶部并回显echo "Line ".__LINE__.":"round(microtime(true) - $start, 3)."sec<br>"; 在每一行。

从你的描述,我猜想它看起来像DNS缓存问题也许。 您可能需要更详细地调查解决DNS记录的时间

  • 使用curl_getinfo详细信息的时间被花费在SMTP谷歌的连接,例如名称查找时间,解析等…见http://www.php.net/manual/en/function.curl-getinfo.php 。 这将帮助您隔离查找的哪一部分是有问题的。
  • 要排除DNS问题,您可能需要将您的DNS IP服务器设置为Google的公共DNS服务器8.8.8.8或8.8.4.4 – 请参阅https://developers.google.com/speed/public-dns/ 。 如果问题仍然存在,则可能是网络配置错误 – 然后尝试从另一台计算机或托管连接到SMTP gmail以检查延迟时间。

从应用程序的角度来看,您可能会建议您异步发送电子邮件,而不是同步发送 ,也就是说通过后台(例如CRON工作) 发送电子邮件 。 如果您发送超过10个电子邮件每小时,这是适合的解决方案。 确保完全控制电子邮件堆栈队列,跟踪错误,无延迟或前端用户页面崩溃。