以下步骤介绍 MTA 如何将重写规则应用到给定地址:
一个地址可以指定多个主机或域名,如下例所示:
jdoe%hostname@siroe.com.
找到匹配的重写规则后,MTA 将根据该规则的模板部分重写地址。
最后,MTA 会将通道标记和与每个通道相关联的主机名进行比较。
如果找到匹配,MTA 会将邮件加入关联的通道队列中;否则该重写过程失败。如果匹配的通道为本地通道,则会通过查找别名数据库和别名文件来进行地址的某个附加的重写。
在下个小节中将更加详细地介绍这些步骤。
使用不属于任何现有通道的通道标记将导致其地址与此规则匹配的邮件被退回。也就是使匹配的邮件无法路由。
重写地址的过程通过从地址中提取第一个主机或域说明开始。(建议不熟悉 RFC 822 地址约定的读者阅读该标准以便理解以下讨论内容。)扫描地址中的主机/域说明的顺序如下所示:
源路由中的主机(从左向右读取)
主机显示在 "at" 符号 (@) 的右侧
主机显示在最后单个百分比符号 (%) 的右侧
主机显示在第一个感叹号 (!) 的)
如果 bangoverpercent 关键字在正进行地址重写的通道上有效(即,如果尝试将邮件加入队列的通道自身被标上 bangoverpercent 通道关键字),则最后两个项目的顺序将被切换。
表 11–3 中显示了可以首先提取的一些地址和主机名的示例。
表 11–3 提取的地址和主机名
地址 |
第一个主机域说明 |
注释 |
---|---|---|
user@a |
a |
“简短格式”域名。 |
user@a.b.c |
a.b.c | |
user@[0.1.2.3] |
[0.1.2.3] |
“域文字”。 |
@a:user@b.c.d |
a | |
@a.b.c:user@d.e.f |
a.b.c |
源路由的地址;路由部分被完全限定。 |
@[0.1.2.3]:user@d.e.f |
[0.1.2.3] |
源路由的地址;路由部分是域文字。 |
@a,@b,@c:user@d.e.f |
a |
带有 a 到 b 到 c 路由的源路由的地址。 |
@a,@[0.1.2.3]:user@b |
a |
在路由部分中带有域文字的源路由的地址。 |
user%A@B |
B | |
user%A |
A | |
user%A%B |
B | |
user%%A%B |
B | |
A!user |
A |
“Bang 式样”寻址;通常用于 UUCP。 |
A!user@B |
B | |
A!user%B@C |
C | |
A!user%B |
B | |
A!user%B |
A |
RFC 822 不在地址中对感叹号 (!) 和百分比符号 (%) 进行解释。如果 at 符号不存在,百分比符号通常与 at 符号 (@) 的解释方法相同,因此 Messaging Server MTA 采用了该约定。
重复的百分比符号的特殊解释用于允许将百分比符号作为本地用户名的一部分;这在处理某些外部邮件系统地址时可能会十分有用。感叹号的解释符合 RFC 976 的“bang 式样”地址约定,因此可以在 Messaging Server MTA 中使用 UUCP 地址。
RFC 822 或 RFC 976 都没有指定这些解释的顺序,因此可以使用 bangoverpercent 和 nobangoverpercent 关键字来控制执行重写的通道应用这些解释的顺序。尽管在某些情况下其他设置可能会很有用,但默认值更“标准”一些。
不建议在地址中使用感叹号 (!) 或百分比符号 (%)。
从地址中提取出第一个主机或域说明后,MTA 将咨询重写规则以找出要执行的操作。将主机/域说明与每个规则的模式部分(即每个规则的左侧)进行比较。该比较不区分大小写。RFC 822 规定不区分大小写。MTA 不区分大小写,但在可能的情况下将保留大小写。
如果主机或域说明与任何模式均不匹配,即所谓的“与任何规则均不匹配”的情况,则主机或域说明的第一个部分(第一个句点前的部分,通常为主机名)将被删除并用星号 (*) 替换,然后将再次尝试查找生成的主机或域说明,但只在配置文件重写规则中查找(不查询域数据库)。
如果此操作失败,则会删除第一个部分并重复该过程。如果此操作也失败了,则会删除下一个部分(通常为子域),重写程序会再次尝试,首先带星号然后不带星号。包含星号的所有探测只在配置文件重写规则表中进行;不检查域数据库。此过程将继续,直到找到匹配或用尽整个主机或域说明。此过程的作用是尝试首先与最为特别的域匹配,然后逐渐与不太特别和比较一般的域匹配。
使用主机/域说明作为比较字符串 spec_1 和 spec_2 的初始值。(例如,spec_1 = spec_2 = a.b.c)。
将比较字符串 spec_1 与配置文件中每个重写规则的模式部分进行比较,然后与域数据库比较直到找到匹配。如果找到了匹配则将退出匹配过程。
如果未找到匹配,则 spec_2 最左侧的非星号部分将被转换为星号。例如,如果 spec_2 为 a.b.c,则将被更改为 *.b.c; 如果 spec_2 为 *.b.c,则将被更改为 *.*.c.。如果找到了匹配则会退出匹配过程。
如果未找到匹配,则比较字符串 spec_1 的第一部分(包括任何前导句点)将被删除。如果 spec_1 只有一个部分(例如 .c 或 c),则该字符串将被单个句点 "." 替换,如果结果字符串 spec_1 的长度为非零值,则您将返回步骤 1。 如果结果字符串长度为零(例如,为先前的 "."),则查找过程已失败并且您将退出匹配过程。
例如,假设地址 dan@sc.cs.siroe.edu 将被重写。这将导致 MTA 按照给定的顺序查找以下模式:
sc.cs.siroe.edu *.cs.siroe.edu .cs.siroe.edu *.*.siroe.edu .siroe.edu *.*.*.edu .edu *.*.*.* . |
主机/域说明与某个重写规则匹配后,将使用该规则的模板部分进行重写。模板指定了三个内容:
地址的新用户名。
地址的新的主机/域说明。
用于识别现有 MTA 通道(到达该地址的邮件应该发送到此通道)的通道标记。
主机/域说明重写后可能会出现下面两种情况之一。
如果通道标记既不与本地通道关联也不与标有 routelocal 通道关键字的通道关联,或者地址中没有附加的主机/域说明,则重写的说明将被替换为替换原始说明(为进行重写而提取)的地址,并且重写过程将终止。
如果通道标记与本地通道或标有 routelocal 的通道关联,并且在地址中显示了附加的主机/域说明,则重写的地址将被放弃,原始(初始)主机/域说明将从地址中被删除,并从地址中提取新的主机/域说明,然后重复整个过程。重写将继续直到用尽所有主机/域说明或找到一个通过非本地、非 routelocal 通道的路由。此重复机制就是 MTA 为源路由提供支持的方式。实际上,通过本地系统和 routelocal 系统的多余的路由都通过此进程从地址中删除了。
如果主机/域说明无法与任何重写规则匹配,并且不存在默认规则时,MTA 将使用“原样”说明;例如原始说明将成为新的说明和路由系统。如果地址中包含无意义的主机/域说明,则当路由系统不匹配与任何通道相关联的任何系统名时,将检测出该说明并将邮件退回。
重写规则应用到地址后不进行任何附加的语法检查。这是有意的—这样可以使用重写规则将地址转换成不符合 RFC 822 的格式。但是,这也意味着配置文件中的错误可能会导致邮件为 MTA 留下不正确或非法的地址。
在重写过程中将对域文字进行特殊处理。如果地址的域部分中显示的域文字与某个重写规则模式不匹配,则该文字将被解释为由句点分隔并由方括号括起来的一组字符串。最右侧的字符串将被删除并会重复进行搜索。如果此操作不起作用则将删除下一个字符串,以此类推直到只剩下空括号。如果搜索空括号失败,则会删除整个域的文字并会对域地址的下一个部分(如果该部分存在)继续进行重写。域文字的内部处理中不使用星号;由星号替换整个域文字时,星号的数量与域文字中的元素的数量相对应。
与常规的域或主机说明类似,域文字也是按最特定到最不特定的顺序进行尝试。其模式匹配的第一个规则将是用于重写主机或域说明的规则。如果规则列表中有两个相同的模式,则会使用首先显示的模式。
例如,假设地址 dan@[128.6.3.40] 将被重写。重写程序将依次查找 [128.6.3.40]、[128.6.3.]、[128.6.]、[128.]、[] 以及 [*.*.*.*],最后是全匹配规则 "."。