Postfix 剖析

作者:Ralf Hildebrandt

请注意,本书基于 Postfix 2.1,更高版本的 Postfix 具有本书未讨论的新守护进程。

本章描述了 Postfix 的工作原理,系统中每个部分的作用以及这些组件之间的关系。 阅读完本材料后,您应该对 Postfix 有一个整体的了解,以便您可以专注于单个目标。

Postfix 由少量与用户进程交互的程序(sendmail, postqueue, postsuper等等)和大量在后台运行的程序组成。 只有在后台运行的程序由master守护进程控制。master守护进程的工作是确定要做什么工作,并派遣适当的程序来完成工作。 这种模块化设计允许更高的安全性,因为每个程序都以完成其任务所需的最低权限集运行。

您可以将整个 Postfix 系统视为路由器。 乍一看这可能听起来很奇怪,但请记住,路由器的工作是查看 IP 数据包,确定目标 IP 地址(也可能是源 IP 地址),然后选择正确的接口来将数据包路由到其目的地。 Postfix 对邮件执行相同的操作(参见图 5-1),查看消息的目标(信封收件人)和源(信封发件人),以确定将消息移近其最终目的地的应用程序。

Anatomy of Postfix

Postfix 的工作方式类似于路由器

现在让我们更仔细地看看这个系统。 真正的路由器通常接受来自多个接口的 IP 数据包,并通过接口将它们路由出去。 Postfix 也是如此; 它接受来自多个来源的消息,然后将邮件传递到多个目的地。 消息的来源可能是本地sendmail二进制文件或 SMTP 或 QMQP 连接。 目标可以是本地邮箱、传出 SMTP 或 LMTP、管道连接到程序等等。 图 5-2 显示了 Postfix 的这种视图。

Anatomy of Postfix

Postfix“路由器”接受并建立各种连接

消息的来源和目的地似乎足够明确,但 Postfix 如何根据目的地选择传递方法? 路由器使用将 IP 地址与网络匹配的路由表来确定路径。 Postfix 对电子邮件地址执行相同的操作。

在 Postfix 中,查找表称为映射。 Postfix 使用 映射 不仅可以找出邮件的发送位置,还可以限制客户端、发件人和收件人,以及检查电子邮件内容中的某些模式。 图 5-3 显示了映射的位置——仅举几例,aliases, virtualtransport显示出来——适合在什么位置。

Anatomy of Postfix

映射是 Postfix“路由器”的查找表

Postfix 守护进程

图 5-4 显示了 Postfix 守护进程的概述以及它们如何组合在一起。

Anatomy of Postfix

图 5-4:Postfix 守护进程之间的关系

注意

Postfix 正在不断开发中。 以下守护进程列表基于 Postfix 2.1。

master

master守护进程是 Postfix 的主管,它监督所有其他 Postfix 守护进程。master等待传入的任务被委派给下属守护进程。 如果有很多工作要做,master可以调用守护进程的多个实例。 您可以配置并发守护进程实例的数量、Postfix 可以重用它们的频率以及在停止实例之前应该经过的非活动时间。

如果您曾经使用过 Unix 机器上的inetd服务器,您会发现它与master守护进程之间有很多相似之处。

bouncedefer

邮件传输代理必须通知发件人有关无法送达的邮件。 在 Postfix 中,bouncedefer守护进程处理此任务,该任务由队列管理器触发(qmgr)。 具体来说,导致发件人通知的两种事件类型是无法恢复的错误以及长时间无法访问的目标。 后一种情况会导致延迟警告。

error

error守护进程是一个邮件传递代理,如localsmtp。 它是一个总是导致邮件被退回的传递代理。 通常,除非您通过将邮件定向到error传递代理来将域配置为不可传递,否则您不会使用它。 如果邮件发送到error守护进程,它将通知bounce守护进程记录收件人无法送达。

trivial-rewrite

trivial-rewrite守护进程在cleanup守护进程的请求下运行,以便将非标准地址重写为标准user@fqdn形式。

此守护进程还在队列管理器 (qmgrqmgrtrivial-rewrite。 默认情况下,

showq

showq守护进程列出 Postfix 邮件队列,它是mailq (sendmail -bp)命令背后的程序。 此守护进程是必需的,因为 Postfix 队列不是世界可读的; 非 setuid 用户程序无法列出队列(并且 Postfix 二进制文件不是 setuid)。

flush

flush守护进程尝试清除邮件队列中挂起和延迟的消息。 通过使用每个目的地的排队邮件列表,它可以提高 SMTP Extended Turn (ETRN) 请求及其命令行等效项的性能,sendmail -qR destination。 您可以使用fast_flush_domains参数在main.cf文件中维护目标列表。

qmgr

qmgr守护进程管理 Postfix 队列; 它是 Postfix 邮件系统的核心。 它将传递任务分配给local, smtp, lmtppipe守护进程。 在委派任务后,它会将队列文件路径名信息、消息发件人地址、目标主机(如果目标是远程的)以及一个或多个消息收件人地址提交给它委派传递任务的守护进程。

qmgr的设计很好地说明了 Postfix 如何处理作业以避免资源匮乏并保持稳定性。 有两件事很突出

  • qmgr维护一个小的active队列,只有少量消息等待传递。 此队列有效地充当了可能更大的incomingdeferred队列的有限窗口,并且可以防止qmgr在大量负载下耗尽内存。

  • 如果 Postfix 无法立即传递消息,qmgr会将消息移动到deferred队列。 将临时无法送达的消息保存在单独的队列中可确保大量邮件积压不会减慢正常的队列访问速度。

qmgr使用bounceerror守护进程来退回邮件给已迁移表中的收件人,该表包含不再存在于系统上的用户或域的联系信息。

proxymap

Postfix 客户端进程可以通过proxymap守护进程获得对映射的只读访问权限。 通过在许多 Postfix 守护进程之间共享单个打开的映射,proxymap规避了 chroot 限制并减少了打开查找表的数量。

spawn

spawn进程根据请求创建非 Postfix 进程。 它侦听连接到标准输入、输出和错误流的 TCP 端口、Unix 域套接字或 FIFO。spawn本书中讨论的唯一用途是第 13 章中的 Postfix 外部内容过滤系统。

local

顾名思义,local守护进程负责本地邮箱传递。 Postfixlocal守护进程可以写入 mbox 和 Maildir 格式的邮箱。 此外,local可以访问 Sendmail 风格的别名数据库和用户.forward文件。

注意: 这些功能使local成为 Sendmail 邮件发布代理的对应物,并且它们都维护相同的用户界面。

作为替代方案,local可以将邮箱传递委派给提供更高级功能(如过滤)的本地传递代理 (LDA)。 两个非常受欢迎的 LDA 是 procmail (www.procmail.org) 和 maildrop (www.flounder.net/~mrsam/maildrop)。

Postfix 可以运行多个local.

virtual

virtual守护进程,有时称为 虚拟传递代理,是local的精简版本,专门传递到邮箱。 它是最安全的 Postfix 传递代理; 它不执行别名和.forward文件扩展。

此传递代理可以为多个域传递邮件,使其特别适合在单台机器(所谓的 POP toaster)上托管多个小域,而无需真正的系统或 shell 帐户。

smtp

smtp客户端是将出站消息传输到远程目的地的 Postfix 客户端程序。 它查找目标邮件交换器,按优先级对列表进行排序,并尝试每个地址,直到找到响应的服务器。 繁忙的 Postfix 系统通常会同时运行多个smtp守护进程。

lmtp

lmtp客户端使用 RFC 2033(ftp.rfc-editor.org/in-notes/rfc2033.txt)中定义的本地邮件传递协议 (LMTP) 与local和远程邮箱服务器进行通信。 它通常与 Cyrus IMAP 服务器 (asg.web.cmu.edu/cyrus/imapd) 一起使用。

使用 Postfix 的lmtp客户端的优势在于 Postfix 处理所有队列管理,并且一台 Postfix 机器可以通过 LMTP 向多个邮箱服务器(需要具有 LMTP 守护进程)馈送数据。 相反的情况也是如此:多个 Postfix 机器可以通过lmtp向一台邮箱服务器馈送数据。 例如,这些邮箱服务器可以运行 Cyrus IMAP。

pipe

pipemailer 客户端是与其他邮件传输机制的出站接口。 它使用参数调用程序,并将消息正文管道传输到其标准输入中。

pickup

pickup守护进程拾取本地maildrop用户客户端程序放入sendmail队列中的消息。 在执行一些完整性检查后,pickup将消息传递给cleanup守护进程之间有很多相似之处。

smtpd

smtpd守护进程处理与通过 SMTP 向 Postfix 传递消息的网络邮件客户端的通信。smtpd执行许多检查以保护 Postfix 系统的其余部分,并且可以配置为实施未经请求的商业电子邮件 (UCE) 控制(本地或基于网络的黑名单、DNS 查找、其他客户端请求等等)。

在接受消息后,smtpd将消息传递给cleanup

cleanup

cleanupdaemon 是新邮件的最终处理阶段。它会添加任何必需的缺失头部,安排地址重写,并(可选地)从邮件头部提取收件人地址。cleanupdaemon 将结果插入到incoming队列中,然后通知队列管理器有新邮件到达。

sendmail

sendmail是一个 Postfix 命令,它替换并模拟 Eric Allman 的 MTA Sendmail。 它的目的是为仅调用/usr/sbin/sendmail的应用程序提供与 Sendmail 兼容的接口。它与postdrop二进制文件交互,将邮件放入maildrop队列中以便提取。

注意 sendmail是将邮件注入 Postfix 队列系统的最慢方式。如果您需要一次发送大量邮件,请改用 SMTP。

qmqpd

Postfix QMQP 服务器实现了快速邮件队列协议 (QMQP; 参见 http://cr.yp.to/proto/qmqp.html),以使 Postfix 与 qmail 和ezmlm列表管理器兼容。

anvil

Postfixanvil是一种初步的防御机制,用于防御 SMTP 客户端和拒绝服务攻击,这些攻击会用过多的并发或连续连接尝试来淹没 SMTP 服务器。它带有白名单功能,用于禁用对授权客户端的限制。anvil未包含在 Postfix 2.1 中,但在 Postfix 2.2 实验版本中可用。anvil在 Postfix 速率限制方面积累足够的经验之前,将保持实验性。

Postfix 队列

Postfix 轮询在您的queue_directory文件中由参数指定的目录中的所有队列。main.cf队列目录通常是/var/spool/postfix。每个队列都有自己的子目录,其名称标识该队列。 Postfix 处理的所有邮件都保留在这些目录中,直到 Postfix 传递它们。 您可以通过其队列状态确定邮件的状态incoming, maildrop, deferred, active, hold, 或者corrupt.

incoming

所有进入 Postfix 队列系统的新邮件都会通过incoming队列发送到cleanup服务。新的队列文件以postfix用户作为所有者创建,访问模式为 0600。一旦队列文件准备好进行进一步处理,cleanup 服务会将队列文件模式更改为 0700,并通知队列管理器有新邮件到达。 队列管理器会忽略模式为 0600 的不完整队列文件。

队列管理器在将新邮件移动到incoming队列时扫描active队列,并确保未超过active队列资源限制。 默认情况下,active队列最多有 20,000 条消息。

注意:一旦达到active队列消息限制,队列管理器将停止扫描incomingdeferred队列。

maildrop

使用sendmail命令提交的尚未由 pickup 服务发送到主 Postfix 队列的邮件将在maildrop队列中等待处理。即使 Postfix 未运行,您也可以将邮件添加到maildrop队列中; Postfix 会在启动后查看它们。

单线程 pickup 服务会定期扫描并清空maildrop队列,以及在收到来自postdrop程序的通知时。该postdrop程序是一个 setgid 辅助程序,允许非特权sendmail程序将邮件注入到maildrop队列中,并通知 pickup 服务邮件已到达。(所有进入主 Postfix 队列的邮件都通过 cleanup 服务进行。)

deferred

如果邮件仍然有由于某些暂时性原因而导致传递失败的收件人,并且邮件已传递给所有可能的收件人,则 Postfix 会将邮件放入deferred队列中。

队列管理器在将新邮件移动到deferred队列会定期扫描,将延迟的邮件放回active队列中。 扫描间隔由queue_run_delay配置参数指定。如果deferredincoming队列扫描恰好在同一时间进行,则队列管理器会在两个队列之间按每条消息交替进行。

active

active队列有点类似于操作系统的进程运行队列。active队列中的邮件已准备好发送,但不一定正在发送过程中。

队列管理器是一个传递代理调度程序,其作用是确保在指定的资源限制内,快速且公平地将邮件传递到所有目标。

注意:尽管大多数 Postfix 管理员将active队列视为磁盘上的目录,但真正的active队列是队列管理器进程内存中的一组数据结构。

hold

管理员可以定义 smtpd access(5) 策略和 cleanup 头部和正文检查(请参阅第 10 章),这些策略和检查会导致邮件自动从正常处理中转移,并无限期地放置在hold队列中。放置在hold队列中的邮件会一直保留在那里,直到管理员干预。不会对hold队列中的邮件进行定期传递尝试。您可以运行postsuper命令来手动将邮件置于保留状态,或将hold队列中的邮件释放到deferred队列中。

队列中。hold邮件可能会在队列中停留一段时间,超过由参数设置的队列文件生存期(超过此期限,未传递的邮件将被退回给发件人)。如果需要从hold队列中释放较旧的邮件,可以使用postsuper -r将它们移动到maildrop队列中,以便该邮件获得新的时间戳,并获得多次传递的机会。

注意:hold队列在 Postfix 性能中没有太大作用;监控hold队列通常是出于跟踪垃圾邮件和恶意软件的目的,而不是出于性能问题的考虑。

corrupt

corrupt目录包含损坏的队列文件。 Postfix 不会丢弃这些文件,而是将它们存储在此处,以便(人工)邮件管理员可以使用postcat.

检查它们。 Postfix 在启动时会记录有关任何损坏文件的警告。

映射

映射是 Postfix 用于查找信息的文件和数据库。映射有许多不同的用途,但它们都有一个共同点 - 左侧 (LHS,或) 和右侧 (RHS,或)。

以下是一些键和值的示例

postmasterjohn
postmaster@example.comjohn
192.168.254.12REJECT
spammer@example.comREJECT
/^Subject: your account {25}[a-z]{8}/REJECT Mimail 病毒检测到

要使用映射,您需要指定一个键,并获得关联的值作为结果。

注意:这里的键和值来自各种文件,在一个文件中没有意义。 前面的列表只是一个说明,表明所有映射条目都采用相同的基本形式。

映射类型

Postfix 可以使用许多不同类型的映射。 可用的格式取决于 Postfix 在您的特定系统上的编译方式。 要了解您的 Postfix 支持哪些格式,请在命令行上运行postconf -m。 您应该获得映射类型的列表

# postconf -m
btree
cdb
cidr
environ
hash
ldap
mysql
nis
pcre
proxy
regexp
sdbm
static
tcp
unix

索引映射(hash、btree、dbm 等)

索引映射是使用诸如newaliases, postaliaspostmap之类的命令从常规文本文件构建的二进制数据库。二进制映射具有索引格式,因此 Postfix 可以快速检索与键关联的值。为了进一步提高性能,Postfix 守护程序在启动时打开这些映射,并且除非它们注意到文件系统中映射文件发生更改,否则它们不会重新读取它们。要重新加载映射,守护程序会退出,然后由master守护进程之间有很多相似之处。

注意

启动一个新的守护程序。如果您有经常更改的索引映射,则使用这些映射的守护程序也会频繁重新启动。在高负载下,这可能会导致性能问题。

最常见的索引映射是从aliases, virtual, transport, relocatedsasl_passwd文本文件构建的。您可以识别映射文件,因为它的名称是原始文件,带有后缀,该后缀也告诉您索引格式。例如,使用aliases命令构建的postalias映射文件命名为aliases.db.

注意

当您创建文件以便从中构建索引映射时,您不必按特定顺序放置键。转换工具和使用索引映射的程序不需要特定的输入顺序。 事实上,转换过程会删除排序。

Postfix 以手册页中指定的预定义顺序查询表中的条目(access(5)、transport(5)、virtual(5)、aliases(5) 和 canonical(5))。换句话说,每个映射查找实际上都包含一系列对索引映射中单个键的单次查询(源自原始查询)。

线性映射(PCRE、regexp、CIDR 和平面文件)

线性映射是常规文本文件。 Postfix 从上到下读取这些文件,这使它们与索引映射不同。 这种差异非常重要,因为文件中第一次匹配决定了 Postfix 将采取的操作。 Postfix 会忽略任何后续条目,无论它们是否匹配查询。

考虑以下 regexp 映射,其中john.doe@example.com查找返回 OK,因为第一行匹配。

/john\.doe@example\.com/ OK
/example\.com/ REJECT

但是,如果您交换 regexp 映射中的行,则另一个条目首先匹配,因此相同的john.doe@example.com查找返回REJECT:

/example\.com/ REJECT
/john\.doe@example\.com/ OK

不需要将线性映射转换为二进制形式(事实上,您无法这样做)。 Postfix 守护程序在启动时读取它们,并且在重新启动之前不会注意到映射的任何更改。 典型的 Postfix 线性映射包括header_checks, body_checksmime_header_checks(请参阅第 9 章)。

注意

随着线性映射的增长,Postfix 守护程序处理它们需要更长的时间。 这对于正文或头部检查尤其如此,因为cleanup守护程序需要检查正文的每一行(最多body_checks_size_limit)和头部与映射的每一行进行比较。

这可能会导致明显的性能下降,尤其是在您有大量*_checks参数使用 regexp 或 PCRE(Perl 兼容正则表达式)类型的映射来防止垃圾邮件进入系统时。发生这种情况时,通常需要将复杂的垃圾邮件过滤交给外部应用程序处理。

要使 Postfix 守护进程注意到线性映射中的更改,请运行 postfix reload。如果时间不紧迫,您可以设置max_use参数来定义守护进程的生存时间。一旦守护进程处理了该参数中指定的任务数量,它就会退出并由master重新启动。重新启动后,它会重新读取所有需要的映射。

数据库(MySQL、PostgreSQL、LDAP)

Postfix 将数据库视为索引映射。数据库查询的结果是匹配(以及查询返回的值)或不匹配。数据库映射和索引映射的主要区别在于,当数据库发生更改时,您无需重新启动守护进程。Postfix 不会假定只有邮局管理员才能更改数据库。

这种方法的缺点是数据库可能无法优雅地处理大量的查询,因为 Postfix 至少需要为每个映射中的查找执行三个查询(请参阅下面的“Postfix 如何查询映射”部分)。在高负载下,数据库后端可能会停止工作,并且您的邮件服务可能会受到自我引起的崩溃或拒绝服务攻击的影响。这种可能性不应阻止您使用数据库后端,但您应该意识到风险。

对于负载重的系统,数据库查找可能会成为一个问题,但这并不是唯一需要考虑的问题——延迟可能是另一个问题。数据库查询比索引映射具有更高的延迟,因为 Postfix 必须连接到数据库后端,发送查询,然后等待结果。使用索引映射,Postfix 只需查询已加载到内存中的数据。

如果您的数据库成为瓶颈,并且您没有过大的映射,则可以在数据库和 Postfix 之间插入一个映射。也就是说,您可以从完整的数据库查询创建一个索引映射,然后使用该映射运行 Postfix。您需要记住根据需要经常更新映射,但是proxymap守护进程可以显著减少并发连接数。

确定到数据库的并发连接数

Postfix 守护进程(smtpd, smtp等等)运行的进程限制(由default_process_limit设置)为 100 个并发进程。在峰值负载下运行,将有 100 个并发smtpd守护进程,每个守护进程都查询数据库后端以进行一次 access(5) 查找(例如,因为我们使用映射来检查客户端是否在我们的个人黑名单中,如果是,则应拒绝其向我们发送邮件)。

请记住,一次查找至少会导致三次查询,因此到数据库的同时查询数量至少为default_process_limit * 3(在默认配置中,这将是 300 个查询),而同时连接的数量是default_process_limit。这只是smtpd守护进程的查询和连接数量;其他守护进程,例如localqmgr,可能正在处理其他作业,从而增加了打开的连接数和同时查询数。

Postfix 如何查询映射

映射可以用于各种任务。Postfix 具有使用映射的表驱动机制(请参阅 access(5)、aliases(5)、canonical(5) 和 transport(5))。这些映射可以使用不同的查找机制(LDAP、NIS、SQL、btree、hash、regexp、cdb、cidr、pcre 等)。请注意,下面描述的查找顺序仅适用于 access(5) 类型的映射。

  1. <localpart@domainpart>完全匹配指定的邮件地址。

  2. <domainpart>匹配domainpart作为电子邮件地址的域部分。模式domainpart也匹配子域,但仅当字符串smtpd_access_maps在 Postfix 的parent_domain_matches_subdomains配置设置中列出时。否则,指定.domainpart(注意初始点)以匹配子域。

  3. <localpart@>匹配具有指定用户部分 (localpart) 的所有邮件地址,无论它们属于哪个域。

  4. 失败。如果查找不匹配,Postfix 将返回未找到匹配项,并且查询以错误结束。

注意

在某些查找表类型中,无法查找空发件人地址。默认情况下,Postfix 使用 <> 作为空发件人地址的查找键。该值由smtpd_null_access_lookup_key参数在main.cf文件中维护目标列表。

指定。这种查找顺序意味着 Postfix 为每个查询执行多次查找,这实际上不是问题,除非您使用高延迟映射(如 SQL 或 LDAP 映射)(当然,您应该预料到很多查找都需要多个查询)。这只是在您将所有映射放入 LDAP,然后在postfix-users邮件列表中抱怨“Postfix 很慢……”之前要记住的一件事。

外部来源

Postfix 支持并非基于 Postfix 构建,甚至不在您直接控制之下的信息源,例如黑名单(DNSBL 和 RHSBL 列表)、基于 DNS 的列表和其他外部来源。黑名单几乎专门用于smtpd_*_restrictions参数中,以拒绝来自 DNSBL 或 RHSBL 样式列表中列出的客户端或发件人的邮件(请参阅第 7 章)。

与任何外部查询一样,由于连接问题、针对黑名单服务器的拒绝服务攻击和其他问题,这些查找可能会失败。如果发生超时或其他故障,Postfix 仍然可能接受邮件(绕过可能的限制),但它会将相应的警告记录到邮件日志中。

命令行实用程序

Postfix 附带了许多命令行实用程序,可帮助您完成管理任务。尽管它们执行不同的功能(例如查询映射、检查队列文件、对消息进行排队和重新排队以及更改配置),但它们都有一个共同点——它们的名称以“post”开头。

注意

这些命令的功能远不止此处描述的功能。我们专注于您在日常操作中将体验到的选项。如果您在此处找不到所需内容,则首先要查找的地方是在线手册。

postfix

postfix命令使用stop, startreload选项停止、启动和重新加载配置。

postalias

postalias命令从别名文件创建索引别名映射。它的工作方式与postmap命令(稍后介绍)类似,但它特别注意别名文件中的表示法(其中冒号分隔键和值)。postalias必须在别名文件上使用。

postcat

postcat命令显示邮件队列中消息的内容。

要读取邮件队列中的消息,您需要其队列 ID。运行mailq以获取队列 ID 列表。例如,以下消息的队列 ID 为 F2B9715C0B3

# mailq
F2B9715C0B3 2464 Mon Oct 13 15:29:39 markus.herrmann@example.com
            (connect to mail.example.com[217.6.113.151]: Connection timed out)
            torsten.hecke@example.net
-- 2 Kbytes in 1 Requests.

获取队列 ID 后,将其用作postcat的选项以查看队列文件的内容

# postcat -q F2B9715C0B3

postmap

postmap命令的主要目的是从平面文件构建索引映射。例如,要构建/etc/postfix/virtual.db来自/etc/postfix/virtual,运行以下命令。

# postmap hash:/etc/postfix/virtual

postmap命令可以做更多的事情。其中最有用的功能是能够测试 Postfix 安装支持的任何类型的映射。这在调试映射查找似乎失败的配置时非常有用,并且您不确定 Postfix 是否实际可见键和值。

调试查找表中的条目

要确定 Postfix 是否可以在映射中找到条目,请使用 postmap -q。例如,以下命令返回分配给键<sender@example.com>在映射/etc/postfix/sender_access(类型 hash

# postmap -q sender@example.com hash:/etc/postfix/sender_access
OK

中的值。postmap<sender@>, <example.com><com>,即使这些术语在 access(5) 手册页中也是如此。您需要手动执行这些查找

# postmap -q sender@ hash:/etc/postfix/sender_access
# postmap -q example.com hash:/etc/postfix/sender_access
# postmap -q com hash:/etc/postfix/sender_access

postdrop

postdrop命令从标准输入读取邮件,并将结果放入maildrop目录中。该程序与sendmail实用程序结合使用。

postkick

postkick命令通过本地传输通道向 Postfix 守护进程发送请求,从而使 Postfix 进程间通信可供 shell 脚本和其他程序访问。

注意

postkick命令将消息发送到 Postfix 守护进程进程。这需要 Postfix 正在运行。

重新排队消息

以下高级postkick示例演示如何重新排队消息以立即重新发送

# cat queueidlist | postsuper -r -
postkick public pickup W

此命令序列将queueidlist中列出的所有选定消息移动到maildrop队列,使用postsuper -r- 命令,其中pickup守护进程将像处理任何其他邮件一样处理它们。通过这样做,您可以将内容过滤器重置为适合本地提交的设置,并添加额外的Received: 标头。

postkick命令请求立即进行maildrop队列扫描。否则,消息将在maildrop队列中停留最多 60 秒。pickup守护进程将消息提交到cleanup守护进程,它会在那里获得一个新的 queueid 并被存放到incoming队列中。整个目的是尽快将消息移动到active队列。

postlock

postlock命令允许您独占访问 Postfix 写入的 mbox 文件,然后在保持锁定的情况下运行命令。您从postlock获得的锁定与 Postfixlocal传送代理兼容。当您的命令执行时,Postfix 不会接触该文件。这是一个例子

# postlock /var/mail/user from

注意

尽量避免任何可能需要 ctrl-C 才能终止的命令。中断postlock并不能保证锁定会消失;您可能需要删除锁定文件才能再次传送到邮箱。要查看是否存在残留的锁定文件,请运行postlock而不使用命令。如果这挂起并最终超时,您可能有一个剩余的锁定。

postlog

postlog命令允许外部程序(如 shell 脚本)将消息写入邮件日志。这是一个与 Postfix 兼容的日志记录接口;默认情况下,它会将命令行中的文本记录为单个记录。这是一个非常简单的例子

# postlog This is a test
postlog: This is a test
# grep "This is a test" /var/log/mail.log
Feb 20 11:50:16 mail postlog: This is a test

postqueue

postqueue命令是 Postfix 队列的用户界面,为您提供传统上可与sendmail命令一起使用的功能。

  1. -f参数使postqueue请求队列管理器传送所有排队的邮件(刷新),无论目的地如何。这相当于postfix flushsendmail -q:

    # postqueue -f
  2. -p参数使postqueue打印队列的内容。它相当于mailq:

    # postqueue -p
  3. -sdomain 参数使postqueue尝试传送所有绑定到域的排队邮件。这相当于sendmail -q domain:

    # postqueue -s example.com

注意

postqueue命令将消息发送到 Postfix 守护进程进程。这需要 Postfix 正在运行。

postsuper

postsuper命令维护 Postfix 队列中的作业。与postqueue不同,此命令仅限于超级用户,并且可以在 Postfix 关闭时运行。一些postsuper功能需要在启动守护进程进程之前检查队列。表 5-1 显示了postsuper命令可以执行的操作。

表 5-1: 的功能postsuper命令

选项操作
-d从指定的邮件队列中删除具有指定队列 ID 的邮件
-h将邮件置于保持状态,使其不被尝试投递
-H释放当前处于保持状态的邮件
-p清除崩溃后遗留的临时文件
-r从指定的邮件队列中,重新排队具有指定队列 ID 的邮件
-s检查并修复队列结构

最常见的用途之一是postsuper使用以下命令从邮件队列中删除邮件postsuper -d queueid。手动执行此操作很繁琐,尤其是在删除许多文件时。以下 Perl 脚本 (delete_from_mailq) 使其更容易

#!/usr/bin/perl
$REGEXP = shift || die "no email-address given (regexp-style, e.g. bl.*\@yahoo.com)!";
@data = qx</usr/sbin/postqueue -p>;
for (@data) {
	if (/^(\w+)(\*|\!)?\s/) {
		$queue_id = $1;
	}
	if($queue_id) {
		if (/$REGEXP/i) {
			$Q{$queue_id} = 1;
			$queue_id = "";
		}
	}
}
#open(POSTSUPER,"|cat") || die "couldn't open postsuper" ;
open(POSTSUPER,"|postsuper -d -") || die "couldn't open postsuper" ;
foreach (keys %Q) {
	print POSTSUPER "$_\n";
};
close(POSTSUPER);

以下是如何使用它

# mailq
C73A015C095     7509 Mon Oct 13 14:56:17 MAILER-DAEMON
	(connect to mx5.ancientaward.com[64.156.166.211]: Connection refused)
 
National_Nosepicking_Month@mx5.ancientaward.com

请注意,发件人被标识为<MAILER-DAEMON>。要删除这些退信,请以 root 身份运行 delete-from-mailq

# delete-from-mailq MAILER-DAEMON
postsuper: C73A015C095: removed
postsuper: Deleted: 1 message

关于作者

Ralf Hildebrandt 和 Patrick Koetter 是 Postfix 社区中活跃且知名的人物。 Hildebrandt 是德国电信公司 T-NetPro 的系统工程师,Koetter 经营自己的公司,为欧洲和非洲的客户提供企业通信咨询和开发。 两人都曾在行业会议上发表过关于 Postfix 的演讲,并定期向许多开源邮件列表投稿。

No Starch Press 在这里有更多关于这本书的信息:www.nostarch.com/postfix.htm 作者维护着该书的勘误和下载页面,您可能想在这里查看:www.postfix-book.com/errata.html

Anatomy of Postfix


         Postfix 之书:最先进的消息传输
         作者:Ralf Hildebrandt & Patrick Koetter
         版权所有 2005 年,464 页
         ISBN 1-59327-001-1
         No Starch Press (http://www.nostarch.com)
      

加载 Disqus 评论