到目前为止,我们主要的讨论焦点,都是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是一种特殊的传输服务,它唯一的作用是当场拒收邮件。冒号之后的字符
串是回复给传送方的错误信息。
传输表不一定用来将邮件传递到外界,也可以用于将特定邮件交给本地系统,以便进行
特殊处理。比方说,过滤邮件内容、暂时扣留某个网域的所有邮件等。
#p#
延迟投递时间
在某些情况下,你可能会希望postfix先收下邮件,但不立刻投递出去。等到你下达
posqueue -f domain命令之后,或是postfix从支持快速清空功能的网域收到ETRN
SMTP命令之后,postfix才递送出被暂扣留的邮件。
最常见的一种情况是ISP为客户的网域代收邮件,但是客户的网络并不总是保持连接。
ISP必须先储存邮件,直到客户的网络恢复连接,并且能收下邮件为止。类似的情况还有
客户网络上的用户,应该要能够通过本地的邮件网关来寄信,该网关必须能先暂存外寄
邮件,直到网络恢复连接时才投递出去。
暂缓转发邮件
在以下的程序中,我们要先创建一种新型的传输法,称为“ondemand”,然后设定传输
表,要求所有寄到example.com网域的邮件,一律先暂时扣留在队列里。
1。 在master.cf设置一种新的传输法,并命名为ondemand。它的配置应该与smtp传
输法一样
ondemand unix - - n - - smtp
2、要求postfix自动延缓任何通过ondemand递送的邮件。只要将新设的ondemand传输法
列在main.cf的defer_transports参数中,就可以达到自动延缓的效果:
defer_transports = ondemand
3、 确定transport_maps参数指向我们的传输表:
transport_maps = hash:/etc/postfix/transport
4、编辑修改传输表,使得example.com网域的所有邮件都通过ondemand传输法来投递:
example.com ondemand
5、运行postmap将传输表转换成数据库格式:
postmap /etc/postfix/transport
6、要求postfix重新读取配置文件,使我们所做的改变开始生效:
postfix reload
现在,所有要寄到example.com网域的邮件都会被扣留在队列里,直到你下达以下命令为
止:
postqueue -f example.com
暂缓投递外地邮件
假设有一个小型办公室网络,他们与Internet之间没有连接,而是由网管人员架设呢一
台邮件服务器来接收内部员工寄到外界的邮件。网管人员希望能够控制外地邮件的投递
时间,让postfix只有在有连接时才送出外地邮件。
1、 将smtp服务名称列在main.cf的defer_transports参数中:
defer_transports = smtp
2、要求postfix重新加载配置文件,使我们的改变生效:
postfix reload
以后,每当办公室网络与Internet接通时,网管人员就可以使用postqueue -f命令来送
出所有外地邮件。
入站邮件网关
邮件网关是一种能收下邮件然后将其转交给其他系统的邮件服务器系统。在在网络术语
中,“网关"一词的意义有两个:一是物理上的含义,代表某个网络到达另一个网络的必
经通路;另一层含义是协议的转换,将一种协议所传达的信息以另一个协议传到目标系
统。
邮件网关通常被设置在企业网络与Internet之间,甚至与防火墙系统搭配在一起,以尽
可能减少需要直接访问Internet的服务器数量。
假设有一个企业网络,这家企业有多个部门,各部门都有自己的子网域,也有自己的内
部邮件服务器。网关系统gw.example.com负责收下企业网络的所有邮件。假设人力资源
部门的邮件系统位于mail.example.com,此部门员工的邮件地址是
user@hr.example.com;业务部门的邮件系统位于mail2.example.com,他们的邮件地
址格式是user@sales.example.com。每个字网络上的主机,应该分别从他们各自的内部
邮件服务器取信。邮件网关gw.example.com必须设置传输表,才能将收下的邮件交付给
正确的内部邮件服务器。
下列程序示范要如何设定gw.example.com,才能使它将邮件交给正确的内部服务器。
1、确定hr.example.com与sales.example.com的DNS mx记录都指向gw.example.com网
关
2、编辑网关系统的main.cf配置文件,将两个子网域列入relay_domains参数:
relay_domains = hr.example.com, sales.example.com
3、确定transport_maps参数指向正确的传输表“
transport_maps = hash:/etc/postfix/transport
4、编辑修改传输表内容,将各网域指向正确的内部服务器:
transport maps
hr.example.com relay:[mail.example.com]
sales.example.com relay:[mail2.example.com]
注意,内部邮件服务器的主机名是放在一对方括号内,这使得网关系统可跳过mx查询,
而直接将邮件递送到主机名称所对应的ip地址。
5、重新加载配置文件,使改变生效:
postfix reload
郑重建议你将mail与mail2的所有合法邮箱列表汇整成一个查询表,放在gw系统上,并将
网关系统的relay_recipient_maps参数指向查询表;否则,gw.example.com将会收下
许多垃圾邮件。
出站邮件网关
若邮件系统没有足够的信息或能力将邮件直接送达目的地,它可将邮件交给位于更有利
位置的其他系统,间接送到目的地。假设那两个内部邮件系统不能直接访问 Internet,
它们不能将字网络上的用户寄到外地的邮件直接递送到目的地,但它们可以将所有外地
邮件都托付给网关系统,由网关代为递送。下列步骤示范如何设定mail.example.com上
的postfix server,使它将收下的所有外地邮件都交给gw.example.com。
在开始设定内部邮件系统之前,请确定邮件网关已被设定成能接收内部邮件系统的转发
要求。网关系统的mynetworks参数应该涵盖内部邮件系统的所有 ip地址;此外,如果
网关系统使用了smtp ube过滤规则,请确定permit_mynetworks被列在过滤规则里。
1、在各部门的办公室贴公告,告诉你的同事,要求他们设定MUA使用的内部邮件系统(mail1 mail2。。。)为smtp server
2、设定内部邮件系统(mail1与mail2)的mynetworks(或mynetworks_style)参数,确定子网络上的全部客户端系统都涵盖在内。
3、编辑内部邮件系统的main.cf,将relayhost参数指向网关系统:
relayhost = 〔gw.example.com〕
4、重新加载postfix配置文件,使改变生效:
postfix reload
现在,所有送到mail.example.com的外地邮件,都会通过gw.example.com送到目的地。
UUCP、传真以及其他投递机制
postfix的在线文件描述了如何设定postfix使其将邮件交给传真机系统以及如何使用postfix来架设UUCP网关。当你的postfix需要与任何特殊设备接轨时,这些例子提供了很好的参考。原则上,如果你需要在不同类型的系统或网络之间架设网关,传输表提供了引导邮件到其他系统或设备的机制。
通过上面文章,我们可以清楚的知道Postfix邮件转发的一些附属知识,能更容易的掌握Postfix邮件转发的功能。
【编辑推荐】