【问题标题】:How to build an email queue with PHPmailer?如何使用 PHPmailer 建立电子邮件队列?
【发布时间】:2017-08-01 23:52:54
【问题描述】:

在插入表格后,我使用 PHPmailer 构建了一个电子邮件脚本,但是,由于脚本超时,我得到了一个错误的网关 502。并且发送 300 多封电子邮件以响应网络请求对我来说听起来不是一个好主意。所以我的问题是如何建立一个在后台发送电子邮件的队列?

据我了解,我将需要新表让我们说 email_queue_table 插入电子邮件地址、内容,然后发送一个名为 status 的字段或排队创建一个类似于 if($status == "queued"){ //then send the email here} else{ // nothing to be sent.} 的 while 循环

如果您知道一种更有效/更好的方法,我会全力以赴。谢谢你的帮助。

【问题讨论】:

  • 您已经有了一个听起来不错的计划。试试看它是否有效。
  • 你所拥有的逻辑是正确的。有一个选择少量数量的脚本(例如,一次 50 个 - SQL 中的 LIMIT 0, 50)。将状态标记为已发送/发送失败。重复直到到达列表的末尾。可能有一些东西可以尝试并重新发送任何失败的东西,但将其限制为一定数量的尝试(您可以有一个用于重新发送尝试的字段,每次尝试都会增加)。您不能通过浏览器运行此脚本,因为它会超时。您必须从 PHP CLI 运行它或使用 ajax 请求触发它。可以使用 cron 作业定期运行它。
  • 将电子邮件与状态一起存储在数据库中是个好主意。您还可以考虑在队列运行时生成电子邮件的内容以减少数据库中的数据。另一个会增加复杂性但可能效果很好的选择是使用 Redis 队列和工作人员,一次从队列中接收和发送电子邮件。它有点复杂,但想补充一点,以防其他人觉得它有用。
  • @bob 我已经发布了一个答案。如果有帮助,我们将不胜感激。

标签: php email queue phpmailer


【解决方案1】:

它的工作逻辑——用一些代码来帮助你——是这样的:

将以下字段添加到您的 email_queue_table 表中:

  • email_address,电子邮件地址(收件人:)
  • content,留言内容。如果要发送给每个用户的相同消息,您最好将其存储一次。如果只是内容中需要更改的一些内容,例如用户名,则使用 PHP 的 str_replace() 执行 str_replace('%name%', 'Andy') 之类的操作,其中 %name% 在您的模板中,并将在每个循环中适当替换。 理想情况下,您不会有此列或在此处重复相同的数据 - 如果您的消息为 50 Kb 并且您有 3000 个用户,例如,您将在一个表中存储 150 Mb 的数据- 必须的。
  • sent_status,已发送状态(默认 = “未发送”,或 0
  • retry_attempts 重试尝试(默认 = 0

创建执行以下操作的 PHP 脚本:

  • SELECT email_address, content FROM email_queue_table LIMIT 0, 50。这让你每个循环有 50 人。重复直到列表末尾 - 为此,您需要知道表中的记录总数,您可以使用 COUNT()
  • 在每个循环中(您要发送邮件的每个人):
    • 使用 PHPMailer 尝试将content 发送到email_address
    • 从 PHPMailer 读取 return 状态。如果发送成功,则将sent_status 标记为“已发送”(1)。如果没有,请将其标记为“未发送”(0)。
  • 延迟,例如sleep(60) 在每批 50 个之间。这会使脚本的执行暂停 1 分钟(60 秒),并可能有助于减轻您的服务器被标记为一次尝试发送大量电子邮件的情况。

发送完所有消息后,您可以选择返回表格,尝试重新发送任何未发送的消息。仍然保留LIMIT 逻辑,因为可能有很多它没有发送,例如

SELECT email_address, content FROM email_queue_table WHERE sent_status = 0 AND retry_attempts < 5 LIMIT 0, 50

增加retry_attempts 字段。如果超过 5 次尝试就停止。

您不能通过浏览器执行上述脚本,因为它会超时。

相反,您可以从命令行手动触发它,例如

php send_email.php

或者在 Cron 上设置以上内容,每天晚上运行,或者以任何需要的频率运行。

或者您可以从 ajax 调用触发它并在浏览器中更新进度。见:creating background processes in php for long running process

【讨论】:

  • 好答案。关于“将内容发送到电子邮件地址”部分,请参阅the mailing list example provided with PHPMailer。它提供了此处描述的有效实现。
  • @Andy 感谢您的出色回答,但对如何实现提到的一些步骤有点不知所措。因此,这将为每个电子邮件地址创建一行,然后更新该行的状态(如果已发送)?
  • 您需要在while 循环(第 21 - 24 行)中包含发送电子邮件的代码。这也是您需要更新是否发送状态的地方(使用sent_status 字段上的UPDATE 查询)。这个循环处理表中的每个人,一次一个。我无法验证您的代码,因为我需要数据库等。我不确定您为什么要在第 8 行绑定 id 参数
  • 是的,我将它排除在 while 循环之外,因为我不确定如何组合它。并且绑定ID不应该在那里。当然我需要将它们插入到另一个表中的email_queue_table 中。我在这里有点困惑。大声笑
  • 我不确定你的意思。 email_queue_table 必须(在脚本运行之前)填充所有电子邮件地址等。如果不是,您需要先执行此操作。然后,当它充满了这些细节时,您循环遍历它(while 循环一次获取 1 人(行))。所以你所有的代码都发送电子邮件,然后更新(SQLUPDATE查询)它是否被发送的状态进入同一个循环。这就像用英语说“给 Bob 发送一封电子邮件。电子邮件是否已发送?根据 Bob 的记录在表中写下状态(已发送/未发送)。为下一个人重复......等等......”
猜你喜欢
  • 2020-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多