0

我正在创建一个网站,在他们可以指定的时间向大约 800 名用户发送每日新闻电子邮件。我的问题是我的脚本需要很长时间才能运行并且超时,所以我正在寻找一些关于如何更好地解决这个问题的建议。

目前的做法:

用户被放置在一个“邮件队列”数据库表中,其中包含他们的 ID、接收时间和发送标志。

然后我每分钟运行一个 CRON 脚本,它执行以下操作:

  1. 从邮件队列中获取所有“接收时间”小于或等于现在、尚未发送的邮件
  2. 遍历用户,加入偏好表以获取他们选择的类别(每个用户最多约 30 个)。
  3. 对于每个类别,找到最新的 3 篇文章
  4. 使用 PHPMailer 准备包含此内容的 HTML 电子邮件
  5. PHPMailer 使用 Mailgun SMTP 来避免我的 SMTP 服务器超载
  6. 向用户发送邮件,在数据库中标记为已发送

到目前为止,我的观察是:

  1. 通过在浏览器中运行来测试脚本时,它运行非常缓慢,几分钟然后超时(不发送任何电子邮件)。
  2. 通过 CRON 每分钟运行一次时,它会在 40 分钟内发送超过电子邮件数量(大约 1400 封)的电子邮件,我猜是因为脚本自身重叠并且发送的标志没有可靠地更新。

大多数用户设置为同时接收他们的电子邮件,所以我在此基础上进行“最坏情况”测试

问题

  1. 通过查询数据库并为每个用户即时生成 HTML 电子邮件内容,我的脚本是否过于繁重?我想知道提前生成内容并将用户存储在邮件队列中是否会更好。
  2. 像 Beanstalkd 这样的队列管理器会有所帮助吗?我已经对其进行了研究,但正在努力了解如何实施到我的日常工作中。

最终,我需要将电子邮件在他们期望的时间可靠地发送给每个用户。

非常感谢任何建议!

4

1 回答 1

0

可以在 PHP 中执行此操作,但您可能不应该这样做。当有更好的方法时,您正在尝试构建邮件服务器,这主要涉及使用邮件服务器。

在页面加载期间发送大量电子邮件是不可行的——即使是单个消息也可能很麻烦,但许多人仍在尝试。像这样接近它:

  • 将您的列表存储在数据库中。
  • 当您要发送时,生成代表要发送的每条消息的记录(本质上是列表的副本)。
  • 有一个以块的形式发送消息的守护进程(一个长时间运行的任务)或 cron 作业。
  • 一次创建一条消息并将它们提交到本地邮件服务器。
  • 使用 DKIM 签名。
  • 在发送每条消息时,将它们标记为在数据库中已发送,但您需要非常了解数据库事务和锁是如何工作的,以使其安全工作并避免重复 - 正确执行此操作,重叠进程就可以正常工作。
  • 您可以随心所欲地生成消息,并且您的邮件服务器将处理排队、转发、重试和退回。
  • 使用VERP 寻址,并将退回邮件输入退回处理程序(请注意,写这些并不好玩!),并防止将来发送到退回地址。

这种方法效果很好——这正是我自己的系统([Smartmessages.net](https://info.smartmessages.net/,内置于 PHP)的工作方式,我可以使用多条消息每秒维持超过 200 条消息并行运行的生成器(数据库事务 FTW!)。

如果你觉得这一切有点太多(这很困难),你可能最好使用商业发送服务(比如我自己的)或托管一个 DIY 解决方案,比如我在Spatie的好朋友的 Mailcoach。其中任何一个都可以很好地工作,而且您的列表非常小——我经常处理超过 100,000 个的列表。

于 2020-11-17T09:11:45.197 回答