Postfix邮件转发详解(1)


到目前为止,我们主要的讨论焦点,都是postfix于邮递路径末端所扮演的角色。也就

是说,抵达postfix服务器的邮件,主要是被投递到本机系统。但是,postfix也常扮演

另一种角色--位于邮递路径中的中继器。

备用交换器

在DNS的术语中,MX代表mail exchanger。一个MX记录代表一个网域承接外来邮件的主

机,以及该主机的优先度。同一个网域可以同时有好几个MX记录,优先度最高的主机称

为主交换器,其余主机称为备用交换器。备用交换器的任务,是在主交换器离线时,承

接该网域的外来邮件;当优先度高于自己的其他备用交换器或主交换器恢复上线时,已

收下的邮件必须传给主交换器来处理,备用交换器不能自己擅作主张,将收到的邮件直

接投递到最终目的地。假设备用交换器时,不必特别设定如何传信给主交换器,因为

postfix自己能从DNS查出如何转信给主交换器。不过,前提是你必须让postfix知道自

己是哪一个网域的备用交换器。你的 postfix系统是哪些网域的备用交换器,那些网域

的名称就必须被列在relay_domains参数中。当寄信方的MTA发觉收信网域的主交换器离

线了,它会试着联系优先度次高的交换器,直到有一个备用交换器能够收下邮件地址为

止。如果你的postfix系统是某个网域的备用交换器,而且该网域被列在

relay_domains参数中,则postfix会收下该网域的邮件,并将其排入队列。每隔一段时

间,postfix会扫描它的队列,并检查是否有优先度更高的邮件交换器恢复连接,如果有

,则交出先前代收的邮件。

如果不能交出邮件,postfix会持续尝试,直到邮件在队列里等待的时间超过

maximal_queue_lifetime所指定的时限为止。此参数的默认值为五天,如果邮件在等待

队列里待的时间超过此上限,postfix会发出退信通知函给寄件人。如果你事先知道主交

换器停机的时间会超过五天,可以适度提高时限。

转发列表

postfix可从relay_domains参数与DNS系统知道自己的备用交换器角色,但是它如何知

道转发的网域中有哪些有效收件人?如果备用交换器无法事先知道主交换器有哪些合法

邮箱,它势必被迫盲目收下所有邮件,等到主交换器恢复连接时,才会发现有哪些邮件

无法投递并退信给原寄件人。因此,我们郑重建议你在备用交换器设置一份列表,记录

受理网域有哪些合法用户,并定期与主交换器同步更新。

当备用交换器上的postfix server收到寄给relay_domains所列网域的邮件时,它会检

查relay_recipient_maps参数所指定的查询表,借此判断是否应该收下邮件,如不应收

下则直接拒收。relay_recipient_maps参数的设定方式如下:

relay_recipient_maps = hash:/etc/postfix/relay_recipients

relay_recipients查询表应该记录所有合法收件人的邮件地址。postfix只需要此表的

索引键,所以对应值可以任意填写(但不可不填)

对于人事变动频繁的网域,我们建议你应该研制一个同步程序,利用rsync、ssh、

crond等工具,自动从主交换器下载最新列表。

如果备用交换器的postfix不过滤转发网域的收件地址,会有什么后果?答案是备用交换

器会收到一大堆无法投递的垃圾邮件,并产生一大堆寄不出去的退信通知函。因为捏造

收件人是垃圾邮件发送者常用的手段之一,他们事先不知道你的邮件交换器有哪些用户

,于是以常用的人名来捏造收件地址,试图蒙混过关。此外,垃圾邮件也不可能会提供

有效的回信地址。

假如备用交换器与主交换器位于同一个局域网,除了使用rsync、scp、ssh、crond等传

统工具之外,还有更好的方法来进行列表的同步更新工作。比方说,将用户账号储存在

某种数据库中,像mysql、ldap等,让postfix能够进行实时查询。

在你设定了relay_recipient_maps之后,还必须面对一个潜在的问题;你必须将所有转

发网域的所有合法邮件地址都列入查询表,因为 postfix将拒收任何收件地址没出现在

查询表的邮件。如果你不知道某些网域的合法邮件地址,你可以为该网域设置一个无限

别名地址;

快速清空

为许多网域承接邮件的网络,时常会面临无法立刻送出邮件的困境,因为他们的顾客的

服务器不见得永远保持连接。在客户离线的情况下,ISP只能将收到的邮件暂时存放在队

列里,等到客户的服务器恢复连接时,再使用SMTP的ETRN命令,一次清空队列里的所有

邮件;

当一个网域的主交换器恢复连接并完成收信准备时,我们的队列里已囤积了大量要传给

该网域的邮件,让postfix逐一检查每一个队列文件的收信网域为何,将会损耗许多时间

。为此,postfix提供了一种称为“快速清空”(fast flush)的功能,可用来在队列

中找出寄给特定网域的所有邮件。快速清空功能是由flush daemon控制管理的,对于

postfix所代理的每一个收信网域,flush各准备了一份列表,记录该网域邮件在队列里

的编号。如此,在发出ETRN 命令之后,postfix可以迅速找出所有要投递到该网域的邮

件。

默认情况下,flush只管理relay_domains所列的网域。如果还有其他网域也需要快速清

空服务,你可以将它们的网域名称在fast_flush_domains参数中,像这样:

fast_flush_domains = $relay_domains, example.com

此例中,example.com是一个没列在relay_domains的网域。

你可以使用postqueue -s命令来通知postfix,某各快速清空网域已经准备好接收先前

累积的邮件了:

postqueue -s example.com

传输表

当你想改变默认的邮递流程时,可利用传输表(transport map)来达成愿望。也就是

说,如果你希望postfix以你指定的方式来处理特定网域的邮件,而不管DNS MX记录是

怎么设定的,你可将相关网域与传送方式写在一二传输表中,然后将transport_maps参

数指向此传输表。

本节讨论transport_maps参数的基本用法,后面几章会陆续谈到此参数在其他方面的应

用。transport_maps参数可指向一个或多个传输表,例如:

transport_maps = hash:/etc/postfix/transport

传输表的索引键可以是完整的邮件地址、网域名称或子网域名称。当收件地址或网域名

称符合传输表某个记录的索引键时,则以该记录的对应值所指定的传输法来投递该邮件

传输表内容

example.com smtp:[192.168.23.56]:20025

oreilly.com relay:[gateway.oreilly.com]

oreillynet.com smtp

ora.com maildrop

kdent@ora.com error:no mail accepted for kdent

传输表对应值的格式,随传输方法而异,但大体上符合transport:nexthop这样的格式

。某些传输方法的nexthop可表示成host:port形式,表示递送路径下一站的主机名与

通信端口。以下分别说明可组成对应值的三种元素:

transport

传输方法的名称。此名称必须是master.cf所定义的传输类型之一。如果你增加

了新的传输方法,则必须先在master.cf定义其名称与传输类型。

host

收信主机或网域。host只能搭配inet传输类型(smtp或lmtp)。postfix按照一

般收信网域的处理流程host:先查询mx记录来决定邮件的去处,如果没有mx记录,则传

到a记录所指的ip地址。如果将主机名称放在一对方括号内,则postfix会直接传信到

host的a记录所指的ip地址。但如果你直接使用ip地址,则一定要加方括号,例如

〔192.168.23.56〕

port

收信主机的通信端口。通常只有inet类型的传输服务才会指定通信端口。port

的格式可以是十进制数,也可以是/etc/services文件定义的服务名称。

上例列出的传输表内容,暂时了transport:host:port的多种可能组合,分别解释如

下:

example.com smtp:〔192.168.23.56〕:20025

收下所有写给example.com的邮件,然后使用smtp MDA传送到位于

192.168.23.56的主机,而且smtp MDA必须连接到该主机的port 20025,而非默认的

smtp port25。请注意,由于我们直接使用了ip地址,所以必须加上方括号。

oreilly.com relay:〔gateway.oreilly.com〕

收下所有要寄到oreilly.com的邮件,然后使用relay MDA转寄给

gateway.oreilly.com主机。由于没指定通信端口,所以relay使用默认的port25。由于

主机名称被放在方括号内,所以邮件是直接传到gateway.oreilly.com的A记录所指的ip

地址,而非mx记录所指的ip地址。

relay MDA是postfix2.0版以后才引进的,它修正了队列调度算法可能引起的潜在效能

瓶颈。当你要将入站邮件送到内部系统时,应该直接通过relay MDA,以避免这类邮件与

出站邮件竞争资源。

oreillynet.com smtp

收下所有目的地为oreillynet.com网域的邮件,然后交给smtp MDA执行投递操

作。由于没指定host:port,所以smtp依照oreillynet.com网域的DNS MX或A记录来决

定目的地,并使用port 25来联系收信服务器。实际上这个例子实属多余,因为只要将

oreillynet.com列在relay_hosts或relay_domains参数,就可以达到相同效果。

ora.com maildrop

收下所有写给ora.com网域的邮件,然后交给maildrop处理。maildrop的运作方

式必须被明确定义在master.cf中。由于maildrop不需要inet socket,所以不必指定

host:port。

kdent@ora.com error:No mail accepted for kdent

error是一种特殊的传输服务,它唯一的作用是当场拒收邮件。冒号之后的字符

串是回复给传送方的错误信息。

传输表不一定用来将邮件传递到外界,也可以用于将特定邮件交给本地系统,以便进行

特殊处理。比方说,过滤邮件内容、暂时扣留某个网域的所有邮件等。


相关内容