我每小时需要处理至少三千封在 postfix 邮箱中收到的传入电子邮件。处理涉及提取电子邮件附件并将电子邮件附件的内容发送到外部电子邮件地址。对于每个电子邮件附件,我发送一封电子邮件。我想我可以通过编写一个脚本让 cronjob 每秒休眠来实现这一点,但我不确定这是一个好的做法(这样做很容易让我每小时处理大约 3600 封邮件)。请建议解决此问题的最佳方法。我已经有一个提取电子邮件和发送电子邮件的脚本,该脚本的唯一问题是它一次只能处理一封电子邮件。如果我使用每分钟 cronjob,我每小时只能处理 60 封邮件,而目标实际上是每小时至少 3000 封邮件。
答案1
只要您的服务器有 CPU 和带宽来维持流量,Procmail 就可以轻松解决这个问题。如果您已经有一个脚本可以处理此问题,只需将每个传入消息通过管道传输到您的脚本即可。将以下内容放入您的$HOME/.procmailrc
:
:0
| /path/to/your/script
该脚本接收消息作为其标准输入,并负责从此处传递或以其他方式处理该消息。 (换句话说,Procmail 根本不会将此邮件发送到您的收件箱。请参阅下文了解如何修改此行为。)
(Procmail 对此并不是绝对必要的,但它添加了一个很好的安全网,以便您的脚本不需要应对所有可能的错误情况。.forward
如果您的脚本足够健壮,您可以简单地将管道塞进您的脚本中。这是基本上 @number5 的评论也告诉了你什么,除了它在 Postfix 的配置文件中执行此操作,而不是使用该.forward
工具。)
如果脚本的两个实例无法同时运行(例如,因为它需要对后端数据库的独占访问),请添加一个锁定文件:
:0:yourscript.lock
| /path/to/your/script
这将导致 Procmail 查找该文件yourscript.lock
,如果存在,则等待它消失;然后创建文件,运行配方,并删除锁定文件。
使用锁文件强制传送被序列化。但这会降低性能。如果可能的话,最好使脚本在并行执行下更加健壮。
另一方面,如果您的脚本给服务器带来了沉重的负载,您可能不想运行多个并发实例;在这种情况下,如果强制序列化交付,性能实际上可能会提高。
如果您还想在收件箱中保留一份副本,请在传送到脚本时克隆一份副本:
:0c # or :0c:yourscript.lock
| /path/to/your/script
您还可以添加一个条件,以便仅将具有特定主题行的消息通过管道传输到您的脚本。条件以星号作为第一个字符指定,后跟需要匹配消息标头的正则表达式。
:0
* ^Subject: xyzzy$
| /path/to/your/script
如果上述方法不合适,以下配方会将所有附件提取到目录中,并为每条传入消息发送一封电子邮件。循环附件可能最好通过像上面这样的外部脚本来完成,但这至少应该让您了解在 Procmail 本身中做一些更多的事情会是什么样子。
METAMAIL_TMPDIR=`mktemp -d /tmp/extracted.XXXXXXXXX`
# Crude attachment extraction ... how are you currently doing this?
:0c
| metamail -w -d
COUNT=`find "$METAMAIL_TMPDIR" -printf "%i\n" | wc -l`
:0
| ( echo Subject: $COUNT attachments extracted into $METAMAIL_TMPDIR; echo; echo ) \
| sendmail -oi [email protected]