队列管理单元的服务器程序--qmgr,是整个postfix系统的中心枢纽。所有邮件,包括等待送出与从外界收进来的,都必须通过队列。了解队列的运行原理以及postfix如何处理队列,有助于你解决问题。
队列管理器总共设置了五个做不同用途的队列,包括:输入、活动、等待、故障、保留。每个队列在queue_directory参数指定的路径下各有一个专属的子目录。默认的队列目录是/var/spool/postfix/。
于后台运作的qmgr daemon能自动处理大部分的队列管理工作,必要时,管理员可使用postsuper和postqueue自己动手管理。本章介绍qmgr于相关命令行工具的运行原理,以及能影响队列的postfix参数。
qmgr的运行原理
邮件进入postfix系统的第一站是“输入队列”。postfix以queue_minfree参数来保护队列文件系统,此参数的默认值为0,表示qmgr可以无限制地使用队列磁盘空间。如果你不想队列耗尽服务器地磁盘空间,建议你设定一个合理地上限值。
每当有新信进入收件队列,qmgr便会将邮件移到活动队列,并调用适当地MDA来处理。只要投递过程没遇到意外,这段流程通常是相当迅速地,快到你没机会 见到邮件停留在活动队列里,除非postfix正在将邮件送到一台非常慢地远程smtp server。如果无法在30秒内连接到远程系统,postfix便会认为该系统目前无法到达。
暂时无法送出去地邮件会被放在等待队列。可能发生了临时性意外包括:DNS系统暂时离线、远程服务器主机临时故障、网络不稳定、收件人地邮箱爆满等。如果遇到永久性地问题或是被远程拒收,则邮件会连同错误报告立刻被退回给原寄件人,不会留在队列里。
等待邮件
留在等待队列里地邮件,会待到它们被成功投递出去,或因为超时而被退回给原寄件人为止。退信通知函与遭退邮件地总和大小不得超过bounce_size_limit,如果超过此限制,则原寄件人只会收到退信通知函,而不会收到遭退邮件本身。
如果邮件一时无法投递,postfix会给邮件标上一个时间,这个时间代表下次尝试投递得时刻。对于一时无法联系得远程主机,postfix会将它们另外 记录在自己内部得一份有时效性得名单上,借此避免不必要的递送尝试。如果有任何等待邮件要被安排重新投递,而且活动队列里有足够空间,则qmgr会交替在 等待队列与收件队列之间取信。如此一来,新进邮件不至于因为postfix正在忙着处理大量等待邮件而等待太久。
队列调度
postfix会定期扫描队列,检查每一封等待邮件的时间,看看是否有任何等待邮件已经到了下一回合应该尝试投递的时间。每一次投递失败,都会导致延迟间 隔时间加长,所以,失败次数越多,就必须等待更长的时间才有再次被投递的机会。延迟时间上限由maximal_queue_lifetime参数决定。如 果邮件在等待队列里的时间超过此上线,postfix便会放弃投递,并退信给原寄件人。maximal_queue_lifetime的默认值为5天,你 可以将它改成任何时间长度;如果你希望postfix在第一次递送失败时就立刻退信,你可将此参数的值该为0。
postfix内部的队列扫描间隔决定于queue_run_delay参数,其默认值为1000秒。也就是说,大约每隔1000秒,postfix就会检查一次等待队列,看看是否有任何应该再次尝试投体的邮件。
postfix重新投体等待邮件的频繁程度的上下限,分别由minimal_backoff_time与maximal_backoff_time这两个 参数决定。每次邮件被延迟,qmgr便会加长下次投递机会的时间间隔,但是累增后的间隔时间不的超过上线,也不得低于下限。如果你发现经常有寄不出去的等 待邮件,或许你应该考虑适度加大上线,让postfix不要浪费太多资源于等待邮件。
投递操作
每当需要投递邮件时,qmgr便会调用适当的MDA来运行投递程序。postfix会很谨慎地避免干扰收信系统,并提供几个参数来控制外寄邮件地可用资 源。这些参数地默认值应该足以应付大部分地情况,但是如果你地操作环境特殊,需要调整资源分配或是想要改善投递操作,你应要实际的测试qmgr或MDA的 操作参数,并依据实测效果来嫁衣调整列在master.cf配置文件里的各个MDA,都有可能被用来投递外寄邮件。master.cf配置文件的maxproc字段限定了MDA的进程数上限。如果该字段没有明确的设定值,则postfix使用default_process_limit参数的值为默认值。
大部分的MDA都有能力同时投递多封邮件到同一个目的地,但是并非所有收信系统都时时刻刻有能力同时收下许多邮件。为了兼顾投递效率于接收系统的工作负 荷,postfix使用一种特殊的投递调度算法:如果有多封邮件要送到同一个目的地,MDA第一次最多只能同时送出 initial_destination_concurrency封邮件,如果能成功完成初次投递,则postfix会尝试同时送出更多邮件,知道发现目 的地系统不能承当当前的工作负荷,或是同时投递的邮件数即将超过default_destination_concurrency_limit。
里可以适度提升initial_destination_concurrency参数的值,但是不能超过该MDA在master.cf配置文件的 maxproc字段值。一般而言,你不应该提升default_destination_concurrency_limit,因为这有使收信系统瘫痪的 风险。
postfix随附的每一个MDA,都有一个对应的mad_destination_concurrency_limit参数,它们的效力高于 default_destination_concurrency_limit参数。因此,如果想提升本地邮件的同时投递量,而不想影响其他MDA,你可 以修改local_destination_concurrency_limit参数的值。同理,如果只想降低远程邮件的同时投递量,而不影响其他 MAD,也可借由修改smtp_destination_concurrency_limit参数来达成目的。
同理,postfix内置的所有MDA都有自己的mad_destination_concurrency_limit参数,它们限制postfix将邮 件交给MDA时,每次最多可以指定多少位收件人。如果同一封邮件的邮件人数超过MDA每次能够承受的人数,postfix会将收件人分成多个小组,分批投 递。
损毁邮件
故障队列纯粹用于存放受损或无法解读的邮件。如果邮件已经损坏到无法进行任何处理的程度,postfix便将它们放在此处,供你调查故障原因。管理员可使 用“队列管理工具”提到的工具来检查故障邮件。一般而言,故障邮件非常少见,如果不幸遇到,通常是操作系统或硬件故障的征兆。
错误通知函
postfix可发出“错误通知函”给管理员,让管理员知道发生了什么类型的错误。postfix将错误通知分成七大类,管理员可设定main.cf里的 notify_classes参数来决定要收哪些类型的错误通知。在默认情况下,管理员只会收到resource与software两种错误类型的通知 函。
对于每一种类型的错误通知函,都有一个对应的class_notice_recipient参数,这些参数代表该类通知函的收件人地址,它们的默认值都是postmaster。
bounce 遭退邮件本身的标头
2bounce 无法投递的退信通知函
delay 被延迟邮件的标头
policy smtp对话过程(因违反垃圾邮件过滤条件而予以拒收的邮件)
protocol smtp对话过程(曾经在smtp对话过程出现错误者)
resource 因为系统资源问题而投递失败的通知
software 因为软件问题而投递失败的通知
如果想收到所有问题的通知函,请照下面这样设定notify_classes参数
notify_classes = bounce, 2bounce, delay, policy, protocol, resource, software
如果你的站点有专人研究垃圾邮件,你可以这样设定:
policy_notice_recipient = antispamexpert@example.com
队列管理工具
postfix提供了一组命令行工具来检查、控制、管理队列里的邮件,其中以postsuper和postqucuc这两个工具最为重要。你可以对队列中的邮件进行下列操作:
显示邮件列表
删除邮件
重新排队
保留邮件
显示邮件内容
清空邮件
每一种操作都有对应的命令。
显示邮件列表
邮件列表的显示项目,包括邮件在队列里的标识符、大小、到达时间、寄件人地址、收件人地址。对于等待邮件,还会另外显示等待原因。如果邮件是在活动队列 里,其标识符栏会加注一个星号(除非你的服务器很慢或是负荷沉重,否则应该没有机会见到星号)。在保留队列里的邮件的邮件,其标识符栏会加注一个感叹号。 等待邮件不加注任何符号。
使用postqueue -p 命令可列出队列里的所有邮件,其效果如果sendmail包的mailq。当安装postfix时,安装脚步会以postfix版的mailq程序(它其 实只是postqueue -p的符号链接而已)取代sendmail包原有的同名程序,借此维持与sendmail包的兼容性。
删除邮件
使用postsuper命令的-d选项,可移除队列里的邮件。邮件是以它们在队列里的标识符表示。
如果要删除所有邮件,请把标识符换成ALL
请注意,由于删除所有邮件是相当危险的操作,所以ALL关键字必须全以大写字母表示才有效,其目的是希望你三思而后行。
保留邮件
当你想将邮件无限期留在队列系统里,保留队列就成为容纳这些邮件的场所。不管邮件目前已经传到哪一个队列,你都可以将它们移除原来的队列,转移到保留队列。
假设你已经知道要保留的邮件的标识符,使用postsuper工具的-h选项,就可将指定的邮件搬到保留队列:
postsuper -h DRA3P1A9
在这之后,如果观察邮件列表,会发现该邮件的标识符多了一个感叹号。
要将邮件移回原来的队列,继续其未竟之进程,可使用同一个postsuper工具,只要将原来的-h改成-H。
在邮件被移回原来的队列之后,qmgr依照平常的调度原则来决定其下次投递时间。或者,你也可以执行清空(flush)命令,立刻将邮件递送出去。
重新排队
如果因为配置问题而耽误了任何邮件,在问题解决之后,你可能希望被耽搁的邮件重新走一遍队列处理流程,以便能够成功完成递送。因为配置问题可能使得 postfix在邮件里存储了错误的投递处理信息,或是使用了错误的地址改写法则。重新排队会使得postfix依据里的新配置来修正错误信息。使用 postsuper工具的-r选项,可以重新排队某一特定邮件,或是要求所有邮件全部都重新排队。
显示邮件内容
使用postcat工具的-q选项,可以查看一个队列文件的内容
早期版本的postcat并未提供-q选项,而是要求你提供队列文件的完整路径。然而,由于邮件可能在各个队列目录之间游移不定,而且这些队列目录还有自己的子目录,所以管理员很难一眼看出队列文件的完整路径。
清空邮件
要求postfix立刻投递滞留在队列里的邮件的操作称为清空(flush),执行清空动作的命令是postqueue -f。不过,除了你有理由确定邮件一定能成功投递出去,否则,最好还是让qmgr自己决定重新投递的时机。不断的反复要求清空,会严重影响邮件服务器的效 率。
使用-s选项可清空寄到特定站点的邮件,而且收件站点必须要有接收快速清空的“资格”才有效。要使得某站点具备此资格,你必须将该站点的主机名称或网域名 称列在fast_flush_domains参数中。此参数的默认值只包含relay_domains所列的所有网域,但是你可以视情况增加额外的站点:
fast_flush_domains = $relay_domains example.com
如果你有一个间歇性的邮件交换机,你可以在该交换器上线的时间内,使用postqueue -s清空先前无法送达到该交换器的所有邮件:
postqueue -s example.com
参数:queue_run_delay
说明:用于设定队列处理程序对拖延邮件的扫描周期。缺省为1000秒。
例 如:queue_run_delay = 1000
最长队列生命期
参数:maximal_queue_lifetime
说 明:用于设定队列处理程序对滞留邮件的最长保存期。缺省为5天。
例如:maximal_queue_lifetime = 5
最小投递失 败周期
参数:minimal_backoff_time
说明:用于设定队列处理程序对无法投递的邮件的最短巡回时间。缺省为1000秒。
例 如:minimal_backoff_time= 1000
最长投递失败周期
参数:maximal_backoff_time
说 明:用于设定队列处理程序对无法投递的邮件的最长巡回时间。缺省为4000秒。
例如:maximal_backoff_time= 4000
我的设置如下:
queue_run_delay = 1000s;每1000s会扫描一次delay的邮件 minimal_backoff_time= 1000s; 在1000s内不会重发delay的邮件
maximal_backoff_time= 1200s; 如果超过1200s则一定会重发邮件
maximal_queue_lifetime = 2400s;邮件超过2400s没有发出去则退信
预期效果为:
每1200s会重发一次,最多重发两次
以下自己理解:
queue_run_delay = 300s
minimal_backoff_time= 300s
maximal_backoff_time= 400s
bounce_queue_lifetime = 1h
maximal_queue_lifetime = 1h
bounce_queue_lifetime:退信(弹回)在队列中的保留时间。超过此时间,被认为是无法投递的。
maximal_queue_lifetime:普通邮件在队列中的最长保留时间。超过此时间,被认为是无法投递的。
最后修改成这样:
queue_run_delay = 200s
minimal_backoff_time = 200s
maximal_backoff_time = 300s
bounce_queue_lifetime = 1800s
maximal_queue_lifetime = 1800s