19.18.4 邮件别名
别名(alias)能够让系统管理员或单个用户重新发送邮件[21]。他们可以定义邮递列表、在机器之间转发邮件,或者允许用多个名字指定一个用户。别名处理是递归的,所以一个别名指向的其他目的地也可以是别名。
sendmail支持好几种别名机制:
用户和系统管理员很容易建立的各种纯文件的映射,诸如/etc/aliases;
厂商主推的老式文件发布系统,诸如Sun[22]的NIS和NIS+,以及苹果公司的NetInfo;
各种邮件路由数据库;
LDAP(Lightweight Directory Access Protocol,轻量级目录访问协议)。
、来自Sun公司的NIS和NIS+、来自NeXT/Apple的NetInfo、邮件路由数据库,以及用户和系统管理员可以设置的各种别名文件。
像/etc/aliases这样的纯文件(本节后面讨论)是迄今为止最简单和最容易在中小站点上建立的别名机制。如果您希望使用邮件之家的概念而且您有一个大型的复杂网点,我们建议您通过把别名保存在一台LDAP服务器上来实现它。
选择其他方法有几个缺点。纯别名文件通常必须由root用户维护;每次修改都必须重建它们的数据库表示,而且必须把它们复制到所有投递邮件的机器上。小型或者简单的网点只使用/etc/mail/aliases这个纯文件和newaliases命令比较好。有些拥有大量虚拟域的站点为各个域维护着单独的别名文件片段,并用一个脚本把它们合并为真正的别名文件。参考19.4.8了解有关LDAP的更多信息。
LDAP不能直接用于邮递列表的别名。不过,它可以用来返回指向程序(比如majordomo)或者:include:文件的别名。这些功能能够让LDAP在必须支持邮递列表的环境也可以工作得不错。
sendmail使用LDAP服务器就跟它使用DNS域名服务器一样。它调用DNS服务器把名字解析为IP地址以便发送消息。它调用LDAP服务器查找别名以便把消息重新发送到正确的地方。在上面两种情况下,查找操作都从纯文件(/etc/hosts和/etc/aliases)移到了数据库上,由服务器来管理查询。
我们已在第178章中提到过LDAP,还会在本章的3个地方更详细地讨论它。我们将在19.18.45.82节介绍和阐述LDAP,然后在18.9.10节描述LDAP与sendmail及其配置文件的交互及其配置文件的配合使用作用,不过,在深入讨论LDAP之前,我们先要介绍一下传统的纯文件别名机制。最后在19.9节举例使用LDAP来实现别名和虚拟主机。有关LDAP的更多信息请参见19.4.8节。
不过,在深入LDAP之前,我们先来描述一下传统的别名机制。传统上可以在下列3个地方定义别名(遗憾的是,要用3种不同的句法):
在用户代理的配置文件中(由发送方用户定义);。
在系统范围内起作用的/etc/mail/aliases文件中(由系统管理员定义);。
在用户的转发文件~/.forward中(由接收方用户定义)[23]。
用户代理在该用户的配置文件中查找别名,并在把消息注入到邮件系统之前扩展这些别名并在把消息送入到邮件系统之前扩展这些别名。传输代理sendmail在全局的aliases文件中寻找别名,然后再到收件人的转发文件中寻找。别名只会应用到sendmail认为是本地的那些消息上[24]。
下面是aliases文件格式中一些别名的例子:
nemeth: evi
evi: evi@mailhub
authors: evi,garth,trent
第一行说的是发送给“nemeth”的邮件应该投递给本地计算机上的用户evi。第二行说的是所有给evi的邮件都应该投递到机器mailhub,而第3行说地址是“authors”的邮件应该投递给用户evi、garth和trent。因为别名支持递归,所以发送给“nemeth”的邮件实际上最后去了“evi@mailhub”。
到全局aliases文件的路径是在sendmail的配置文件中指定的—在Red Hat和、SuSESUSE和Ubuntu上都是/etc/aliases。/etc/mail/aliases实际上才是“标准”位置。站点可以有多个aliases文件,且还可以使用别的方法,比如用NIS或数据库文件来保存别名映射关系。有关NIS的更多信息请参考第178章。
aliases文件中配置项的格式是:
local-name: recipient1,recipient2,...
其中local-name是与传入消息匹配的原来的地址匹配传入消息的源地址,而收件人名单则包含收件人地址或其他别名的名字。缩行被当作是前面行的续行。
从邮件的角度来看,aliases文件代替了/etc/passwd,所以:
david: david@somewhere-else.edu
将会阻止本地用户david得到任何邮件。因此,管理员和adduser工具在选择新用户的名字时应该把passwd文件和aliases文件都检查一下。
/etc/mail/aliases文件应该永远包含一个名为文件应该永远包含一个叫做“postmaster”的别名,它把邮件转发给负责维护邮件系统的人。类似地,要有一个别名“abuse”,适用于外单位的人需要联络您报告源自于您的网点的垃圾邮件或者可疑网络行为。还必须提供一个接收来自sendmail的自动消息的别名,通常把它称为Mailer-Daemon(邮寄程序守护进程),并且通常把它的别名起为并且经常让它的别名也是postmaster。
应该把root的邮件重定向给站点管理员或者每天都登录进入系统的人。bin、sys、daemon、nobody和hostmaster账号(以及设置的任何其他伪用户账号)也应该拥有把邮件转发给某个人的别名。对于理应包含的在系统范围内起作用的别名,软件发布中的文件sendmail/aliases是一个很好的模板。它还包含安全性建议和一个例子,说明一些常见的用户请求在伯克利Berkeley(译者注:sendmail的作者Eric Allman是UC Berkeley加州大学伯克利分校的毕业生,也在那里工作)里是怎样发送的那里是怎样发送的。
sendmail通过计算消息信头中Received行数来检测导致邮件没完没了来回转发的循环,并在计数值达到某个预设界限时(通常是25)[25]把邮件返回给发件人。在sendmail的专门术语中,每次访问到一台新的机器称作一“跳”(hop)”,把一则消息返回给发件人称为“弹回”(bouncing)”它。前面的表述如果用适当的术语讲,就是“邮件在25跳之后弹回”[26]。
除了用户列表,别名还可以指:
一个包含地址列表的文件;
一个应该把消息附加到其后的文件;
一条应该把消息作为其输入的命令。
因为一则消息的内容完全由它的发件人确定,所以这些投递目标常常受到黑客的攻击。sendmail对与这类文件和命令有关的所有权和权限已经变得非常挑剔。要让sendmail不那么偏执,必须设置DontBlameSendmail选项中的某一项,之所以叫这个名字是因为不鼓励您这样做。很遗憾,sendmail在遇到不安全的权限或所有权时产生的出错信息并不总是很清楚明了。
19.18.4.1
从文件中获取邮递列表
include:指令是让用户管理他们自己的邮递列表的一种好方法。它允许从外部文件获取一个成员的别名,而不是直接在aliases文件中列出。还可以在本地修改该文件而不需要负责全局aliases文件的系统管理员介入。
在设置列表时,系统管理员必须把别名输入全局aliases文件中、创建被包含文件,并用chown命令把被包含的文件的所有权赋予维护邮递列表的用户。例如,aliases文件可能包含:
sabook: :include:/usr/local/mail/lusah.readers
文件lusah.readers应该位于本地文件系统而不是在通过NFS安装的文件系统中[27],并且只应对其所有者是可写入的。为了做到真正完整,我们还应该包含邮递列表所有者的别名,以便将错误(弹回)发给列表的所有者而不是该地址列表的消息的发件人。
owner-sabook: evi
有关邮递列表以及它们和aliases文件交互作用的更多信息,可参考19.17.4.76节。
19.18.4.2
发邮件给文件
如果别名的目标是一个绝对路径名(如果它包含特殊字符则要用双引号引起来),消息将被附加到指定的文件之后。而该文件必须已经存在。例如:
complaints: /dev/null
能够把邮件发送给文件和程序是很有用的,但这一功能也引入了安全性问题,因而受到限制。这一句法只在aliases文件和用户的.forward文件(或是用:include:插入到这些文件中的某一个文件)中有效。文件名不会被理解成一个标准的地址,所以地址是/etc/passwd@host.domain的邮件将被弹回。
有些用户代理允许您把邮件发给一个本地文件(比如发件箱文件夹)。但只不过是这则消息的副本由用户代理保存起来了,永远不会真正通过邮件系统发送出去。
如果在aliases文件中引用了目的地文件,那么它必须对任何人可写(不建议这样)、有setuid位但不可执行、或者由sendmail的默认用户所有。默认用户的身份用DefaultUser选项设置。它通常为mailnull、sendmail、daemon,或者UID 1、GID 1。
如果在.forward文件中引用该文件,那么它必须由原来的消息收件人所有,且有对它的写权,而且此收件人必须是一个合法用户,在/etc/passwd文件中有他的一个项文件中有他的一条记录,并且在/etc/shells中列出了他用的合法shell。对于由 root用户拥有的文件,请使用模式4644或者模式4600来设置setuid位,但不可执行。
19.18.4.3
发邮件给程序
别名还可以把邮件发送到一个程序的标准输入。这一行为用下面这样的一行来指定这一做法用下面这样的一行来指定:
autoftp: "|/usr/local/bin/ftpserver"
用这项功能甚至比发邮件给文件更容易造成安全性漏洞,所以再强调一次,它只允许用在aliases、.forward或:include:文件中,sendmail的默认配置现在要求使用受限制的shell—smrsh。[28]。在aliases文件中,程序作为sendmail的默认用户运行;否则,程序作为.forward或:include:文件的所有者运行。这个用户必须已经在/etc/passwd文件中列出,并具有一个有效的shell(在/etc/shells中)。
程序的邮寄程序在运行接收邮件的命令之前先把它的工作目录变为用户的主目录(或者,如果那个目录不能访问,就变为root的目录)。默认原本是sendmail的邮件队列目录,但是有些基于csh的shell不接受。
给程序发送邮件是一个主要的潜在安全性漏洞。为了安全起见,不要使用/bin/sh作为程序的邮寄程序;改为使用sendmail的受限制的shell——smrsh。关于smrsh更详细的信息,请参见19.11节。
19.18.4.4
别名举例
下面是系统管理员可能使用的一些典型别名[29]。

在这个例子中,我们希望来自校园各处的用户能在发生问题时向一个别名“trouble”发送邮件。问题报告一定要传递给一个适当的本地系统管理员小组。特别地,我们愿意设置邮件别名是为了:
在这个例子中,我们希望来自校园各处的用户能在发生问题时向一个别名“trouble”发送邮件。问题报告一定要传递给一个适当的本地系统管理员小组。特别地,我们愿意设置邮件别名是为了:
让问题邮件总是去到一个适当的分组;
在所有主机上使用同一个简单版本的别名文件;
让单个管理小组控制他们自己的分发列表;
把所有问题邮件的副本发往各个小组所用的一个本地日志文件。
通过从每台机器上的一个文件中来获取trouble别名的定义,上述配置可以满足这些目标。发送给地址trouble@anchor和trouble@boulder的邮件最终会发到不同的地方,即使anchor和boulder使用同样的/etc/mail/aliases文件。
问题邮件通常在各个地点的某台特定机器上处理。例如,在一台从(slave)机器上的trouble.alias文件可以包含地址:
trouble@master
以便让将问题邮件送去往适当的主机器。
在分析一则trouble消息时,它被发送给别名“tmr”,此别名代表“trouble mail readers(问题邮件阅读器)”。tmr别名把这则消息归档到troubletrap别名,还把它发送给一个用户列表,这个列表是从主(master)机器上的一个文件中获得的。把管理员新手添加到tmr列表中是一种很棒的方法,这可以让他们看到出现的需要支持的问题、管理员的答复,还有对用户(也就是客户)应该适当使用的奉承语调。
这种机制只是名为queuemh的整个故障表单跟踪系统的冰山之一角,它基于mh用户代理。
别名sa-class有两个层次,这样一来,以便只需要在单台机器nag上维护包含学生列表的数据文件。前面19.18.4.1节里sabook别名的例子应该说真正具有了与这种类型相同的间接手段,因此不需要复制包含文件。
别名diary很方便,对于不耐烦记录下自己所做事情的乖僻的学生系统管理员来说,它很好地发挥了作为一种文档提取技术的作用。通过发送邮件给diary文件,系统管理员很容易就可以记录下机器生命周期中的重要事件(OS升级、硬件改动、崩溃等)。不要把这个文件放在包含日志文件的文件系统中,那样做会让黑客填满文件系统而使syslog无法写入日志条目(也就掩盖了他们的踪迹)。
19.18.4.5
邮件转发
aliases文件是一个系统范围的配置文件,它应该由管理员来维护。如果用户希望重新指定发送自己邮件的路径(而您的站点不使用POP或IMAP来访问邮件),可以在他们自己的主目录中创建.forward文件来实现这一点。以前,sendmail总是在用户的主目录中搜索一个.forward文件,但现在要启用这种做法,则必须设置ForwardPath变量,覆盖默认的设置。当用户希望在一台特定主机上接收邮件,或当某人离开您的网点而希望让邮件转发到一个新位置时,使用.forward文件会很方便。
一个.forward文件由单独一行上用逗号分隔的地址列表,或多行上的若干项组成。例如:
evi@ipn.caida.org
evi@atrust.comevi@xor.com
或者
\mcbryan, "/home/mcbryan/archive", mcbryan@f1supi1.gmd.de
在第一个例子中,evi的邮件不是投递到本地计算机上,而是转发给加州圣地亚哥的CAIDA的机器ipn和evi@atrust.comxor.com。第二个例子来自一个不信任邮件系统的用户,他希望把自己的邮件复制到3个地方:本地计算机上的常规邮件缓冲区、所有传入邮件的一个永久存档文件、他此刻游历的德国国内的一个临时地址。他的用户名之前的反斜线的意思是,无论别名或转发文件说什么,都要把邮件投递到本地。
对于邮件路由中的临时变化,使用.forward文件要比使用全局aliases文件更可取,因为修改系统范围的别名所需要的开销(计算机时间和人力时间)是相当高的。
用户的.forward文件必须由该用户所有,决不能让组成员或任何人都可写入。如果sendmail认为到.forward文件的目录路径是安全的(也就是说,从root用户以下的权限都没有问题),它就能是一个链接,否则,它就不能是一个链接。sendmail将忽略掉权限可疑的转发文件,上级目录的权限也必须是安全的(只能由拥有该文件的用户写入)。
自然,sendmail必须要能够访问邮件所投递到的机器上该用户的主目录,才能确定它是否包含一个.forward文件。地址的永久性修改应该放入/etc/mail/aliases文件,因为用户的主目录和文件最终将被删除。
sendmail有一项很棒的功能,FEATURE('redirect'backqucte
redirect
apostrophe),它有助于管理电子邮件的永久性变更它能帮助管理电子邮件的永久性变更。如果一个别名指向user@newsite.REDIRECT,邮件将被退回给发件人,并附上新地址的通知。消息不会转发到新地址,所以发件人必须更新他的地址簿并重新发送消息。
您可以配置sendmail以便支持用于.forward文件的中央目录,但用户不能寄期望于这项配置。.forward文件的位置由ForwardPath选项控制,它通常指向中央目录,然后指向用户的主目录。19.7.18.8.3节中举例说明的generic.m4域文件包含了用于.forward文件的中央位置的一个例子。
全局aliases文件中的项要优先于.forward文件中的项。因为这些文件是由不同的人维护的,所以用户必须当心,不要在无意中造成邮件循环。如果用户在网络上拥有一个邮件之家(因此在全局aliases文件中拥有一项),该用户就不能使用.forward文件把邮件路径重新改到另一台共享同一别名的机器上去。例如,在科罗拉多大学,我们使用一个在本网点范围内起作用的aliases文件,有类似:
evi: evi@boulder
这样的一项,而机器boulder上的.forward文件包含:
这就造成了一个循环。地址是evi的邮件将转发给boulder,boulder上的.forward文件又会使得它被发给cs子域中的anchor。anchor上的aliases文件使得邮件被转发回boulder,如此循环不已。在25跳之后,邮件将被退回给发件人。
如果您的主要通信模式是电子邮件,那么通知用户发生了邮件循环是很难的事情。发给\user[30]的邮件会把消息投递到本地计算机上,而不管系统范围的aliases文件或用户的.forward文件可能说什么。如果本地计算机是用户要读取邮件的地方,那很好,否则,请给postmaster发信发邮件报告出现了循环,或打个电话!
19.18.4.6
散列的别名数据库
因为aliases文件中的项没有特定的顺序,所以sendmail直接搜索这个文件的效率并不高。取而代之的做法是,用大多数UNIX版本中标准的Berkeley
DB数据库系统或ndbm数据库系统来构造一个散列的版本。这种散列法可以明显加快别名的查找,特别是在文件变大的时候。
对DB而言,从/etc/mail/aliases衍生出的文件名为aliases.db,对ndbm而言则名为aliases.dir和aliases.pag。dir文件是pag文件的一个索引,实际上数据保留在pag文件中。每当您每次修改aliases文件时,都必须用newaliases命令重建此散列数据库。newaliases其实只是被伪装起来的带命令行标志(-bi)的sendmail,这个标志告诉sendmail要重建数据库。如果自动运行newaliases,要把请保存出错的输出保存下来—您可能已经引入了格式错误。
在编译sendmail时,应该把对dbm/ndbm例程,对新Berkeley DB例程,或对这两种数据库的支持都包含在内。如果两者都包含,那么在sendmail需要创建一个数据库文件但没有指定类型时将使用DB。如果正在使用NIS,sendmail会两者都创建,但如果aliases文件的路径中包括/yp/的话,就只使用DB版本。有关NIS的更多信息请参考第18章。
由Keith Bostic和Margo
Seltzer编写并维护的DB库可以从www.sleepycat.com获得。它比ndbm系统好得多(访问更快、数据库文件更小)。DB是开放源代码和免费的,除非您把它封装在某种专利产品中;如果是这样,您就需要一份使用许可。






