![当本地投递失败时,Postfix 应该将邮件暂时退回到队列](https://linux22.com/image/785951/%E5%BD%93%E6%9C%AC%E5%9C%B0%E6%8A%95%E9%80%92%E5%A4%B1%E8%B4%A5%E6%97%B6%EF%BC%8CPostfix%20%E5%BA%94%E8%AF%A5%E5%B0%86%E9%82%AE%E4%BB%B6%E6%9A%82%E6%97%B6%E9%80%80%E5%9B%9E%E5%88%B0%E9%98%9F%E5%88%97.png)
我在 Debian 11 上运行 postfix,同时进程邮件作为 lda。有些用户有〜/ .procmailrc它调用外部程序,解析邮件并执行相应的操作。只要没有出错,它就会按预期工作。
目标定义
我发现,如果在 procmail 配方中运行的程序因错误而退出,则邮件将被放入用户的本地邮箱中,并且不会执行进一步的操作。这不是我想要的结果。我希望邮件留在 postfix 队列中,以便下一次队列运行可以再次尝试投递。这类似于由于远程主机端出现临时错误而无法通过 SMTP 将邮件投递到另一台主机时的临时故障。
Postfix + procmail
我在/etc/postfix/main.cf:
mailbox_command = procmail -t -a "$EXTENSION"
根据 procmail 手册页,-t
应该强制软失败 — 如预期的那样 — 但这显然不适用于 postfix?不幸的是,我没有找到关于 postfix 如何处理rc!=0
外部邮箱命令秒。
我找到一个资料来解释如何编写〜/ procmailrc-recipe 强制 procmail 因被调用程序的错误而退出。这是我用于测试目的的代码片段:
:0
* ^Subject: failme$
{
:0wc
|/usr/bin/false
:0
{ EXITCODE=$? }
}
其基本工作原理是:Postfix 识别到 lda 因错误退出,并立即退回邮件。
因此,我猜想 Postfix 中可能存在我遗漏的设置,尽管我已经在 postconf(5) 中查找了以下关键字:错误和推迟,并读取本地(8)。
概括
如何配置 Postfix 以便当 lda 失败时邮件保留在队列中?
答案1
关键在于 Procmail没有如果您没有明确使其失败,则失败。如您所指出的,其默认行为是使当前配方失败,然后$DEFAULT
如果未成功执行任何交付配方,则最终交付为后备。
我不认为这显然是可以修复的,但我可以想出一个变通的办法;配置它,使其$DEFAULT
指向一个无法投递邮件的位置;然后当它从用户的末端掉下来时,你应该会收到一个错误.procmailrc
实际上,如果你
$DEFAULT
用不可写的位置覆盖,Procmail 将反复尝试传递、失败并重试。最终,在我的快速而粗糙的实验中,它似乎会回到$ORGMAIL
(“默认”)。$DEFAULT
我想你也可以考虑以某种方式包装它,也许明确地includerc=$HOME/.procmailrc
包装它/etc/procmailrc
,如果它在没有交付的情况下返回,则会失败。
下面的内容/etc/procmailrc
确实很 hacky。
它实际上最终会运行两次用户.procmailrc
;它假设如果第一次调用没有提供任何内容,第二次调用也不会提供任何内容。我找不到阻止它.procmailrc
再次执行用户的方法;但也许有办法。
# ... your regular /etc/procmailrc contents here
# Drop root privileges
DROPPRIVS=yes
# Run user's recipes
INCLUDERC=$HOME/.procmailrc
# Don't deliver to DEFAULT any longer
DEFAULT=/dev/null
# Set exit code to an error code (check your local manual for what makes sense for your MTA)
EXITCODE=77
# Force quit
HOST=
Sendmail(我认为还有 Postfix)使用退出代码系统退出;Qmail(如果有人仍在使用它)据称有其自己的约定。
顺便说一句,c
测试配方上的标志似乎被误导了(:0wc
);c
标志表示要克隆消息,并有效地生成两个消息。由于您的配方总是会失败,我猜您会立即丢弃刚刚创建的配方;但无论如何,w
这里的标志应该足够了。