当本地投递失败时,Postfix 应该将邮件暂时退回到队列

当本地投递失败时,Postfix 应该将邮件暂时退回到队列

我在 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这里的标志应该足够了。

相关内容