原 著:
出 版 商: O’Reilly
出版日期: 2002年12月
中文翻译: 2006年2 月
中文译者: 李
峰 ( lifeng_AT_telebyte.com.cn )
译者网站: Http://lifeng.telebyte.com.cn
从2000年开始,作者就对于互联网电子邮件系统感兴趣,但当时没只是在公司内部架设一台Linux服务器来配置Sendmail,当时对于邮件系统并没有太多的管理知识。2002年,作者加入目前所工作的公司——北京天傲世纪科技有限公司——从事网络管理工作,从近几年的网络管理工作的实验来看,目前国内从事网络管理的人员十分需要一本能对于Sendmail 这个互联网上最早使用的邮件服务器时行详细介绍的书。由于Sendmail的管理对于没有经验的新手来说非常复杂,能对于Sendmail进行详细了解的网络技术人员在国内还是少数,且随着时代的进步,Sendmail也在不断发展。对于网络管理的新手来说,往往被早期书藉上“Sendmail威胁系系安全的言论”所蛊惑而对Sendmail产生怀疑和误解。这对于Sendmail来说是极大的不公,其实Sendmail开发人员早已修补了相应的安全漏洞,并重新设计了更安全、功能更多、性能更稳定的Sendmail。Sendmail
8.10后的版本和以前的版本相比,安全性上有了质的提高。并且对于反垃圾邮件方面有着功能非常丰富的手段来处理。
当然,如果要使用Sendmail这个功能丰富的邮件系统,你还需要仔细的阅读和理解本书的内容。并且最好有实践机会来管理和维护一个邮件系统。
新版本的Sendmail相对于Sendmail-8.12—a版本来说已经被完全重新修定过,并被添加了更多新的功能和对于类Unix的邮件程序进行基本性改变。由于最新版本的Sendmail相对于早期版本有如此明显的改变,对于这本畅销的参考手册内容大块重写的要求被本书早期版本的读者提出。如果你手头有一本Sendmail第三版,你将有能力配置你的系统所想要最具挑战性的功能。
版权@2003 Bryan Costables
第二版版权 @ 1997, 1993 O’Reilly & Associate, Inc
拥有在美国出版的所有权利。由O’Reilly & Associates, Inc, 1005 Gravenstein
Highway North, Sebastopol, CA 95472
O’Reilly &
Associates 的图书可被用于教育、商业,或销售目的。在线版本也可从这个站点 (http://safari.oreilly.com
)来得到。如需更多信息,请联系我们公司/机构销售部门:(800)998-9938 或 corporate@oreilly.com
Nutshell手册,Nutshell手册图标,和O’Reilly图标都是已被O’Reilly & Associates公司所注册的商标。商标是在不同的制造商和销售商间为了相互区别而大量被使用。这些不同在本书中得以体现,并且O’Reilly & Associates 公司明确商标的声明,这些区别已被用大写字符打印或首字母大写的方式打印出来。对于书中相关联的飞狐的图象和Sendmail的主题是O’Reilly
& Associates 公司的注册商标。
同时在本书中所有的地方都事先做了预防性的准备,出版商和作者假设对于本书中的错误和冗长描述不负任何责任,或由于对于本书中内容的使用结果对用户造成的损失承担任何责任。
中文译本版权@ 2006 李 峰
中文译者声明:对于本书中错误和用户由于使用本书内容对用户造成的损失不承担任何责任。对于本书中文翻译中的错误,请直接发送邮件到:
lifeng_AT_telebyte.com.cn 或 lifeng868_AT_hotmail.com
或在译者的个人网站上留言,我的个人网站URL是:
本书得自P.Scott Johnson 的记忆。
中文版得自李峰对于Sendmail的使用经验和对于英文理解。
写这本书的主要原因,第三版Sendmail,包售含了Sendmail的8.9版到8.12版程序。Sendmail的8.12版,在细节上和早期版本的差别是如此之大,以至于这本书的第二版中的大块的内容将需要重新编写。
你将注意到在这本指南的早期版本中,有单独的一章专门介绍本书中本章的内容。这本指南排除第二版的组织方式的原因是由于从Sendmail 8.10版本后,将所有的配置都变成基于m4的编译和配置方式。由于新版的Sendmail希望将隔离Sendmail的内部管理。因此sendmail现在十分强调mc配置文件,并且mc文件将产生99%的你所需要的规则和规则集。尽管你不时需要编写你自己的规则集,上面通过mc文件产生的规则集将被证明能满足你的大部分需求。[1]
[1]在指南中将相关章节删除的原因还由于原来的版本中有太多的版本指定信息,这些信息不可能总保持正确。作为替换措施,配置方案和示例将贯穿本指南的始终。
你将会注意到本版本中还出现了新的章节。关于执行凋整的一章已被加入本指南。这是由于目前有太多的站点正在寻找使邮件投递代理更为有效的方法。关于如何处理spam的章节已被添加入本书,这是由于sendmail的8.10版本和后续版本中目前有非常丰富的反垃圾邮件功能。还添加一个如何使用支持Sendmail程序如vacation和 makemap的章节,由于这些程序对于Sendmail日常操作来说是非常关键的。其它的章节被大量的扩展内容,这上由于sendmail已经被添加了许多的新功能、选项、和宏 。
这个版本的sendmail指南假设你正使用Sendmail 8.12版本,这是当前版本(本书英文版写作时)的Sendmail。它依照早期版本的风格和格式进行编排,但是我们意识到这对于只关注与最新版本相比有什么改变的读者来说,这样的安排有些不太方便。为了解决这个问题,我们在本书中添加了附录B,在这个附录中,所有涉及版本更新的内容都被分门别类地在附录中列出,并完整地引用到本书中相并应的章节。
佛里吉亚的国王Gordius创造了一个非常复杂的结以至于没有人能解开这个结。Gordian结紧密地缠结在那里,因此,故事开始了,直到伟大的Alexander出现并用一种完全不同的方法解开这个著名的结。向结挥动他的剑,一劳永逸的解开了这个结。
如果结是Sendmail,并能使用敏锐的洞察力来解开这个结,那将是非常美满的结果。但是,唉,它不能。转而,一种更世俗的方法必需被使用,因此,在这本书中,我们解开这个因难的方法是一次一手地解开这个结。
但是,你可能会问,“为什么如此费力?Sendmail不是计算机时代出现?没有更为新的、更为好的、更为现代的东西来替换Sendmail?”,事实并非如此,时间已使Sendmail变得更为成熟和可靠。Sendmail程序已经受住时间的考验,因为它不仅仅是一个程序,它是一种哲学:一个通用目的,拥有可伸缩、可配置来解决所有互联网邮件路由需求,从小站点到大站点,复杂或简单地解决邮件问题的哲学。
Sendmail的优点同时也是它的缺点。配置是如此复杂。Sendmail是如此难于配置更甚于对Sendmail的理解。它的配置文件,例如,可以肯定地说是令人恐惧的。但不是令人决望。如果本书在手,你将能配置Sendmail来满足你的任何需求,并使你最终成为一个Sendmail的高手。
Sendmail程序最初由Eric Allman所编写,当时他是一个加利褔尼亚大学伯克利分校的学生和工作人员,在那时,一个校园主机(Ingres)连接到ARPAnet并且放置在Eric工作的INGRES项目的房间中。另一台主机(Ernie CoVax )放置在Berkeley Unix项目,并且两台主机之间最近开始使用 Unix to Unix 通讯协议(UUCP)。这些机器(包括校园网内的其它机器)由Eric Schmidt组成一个低成本的网络,这个网络被称为BerkNet。有程序分别完成在ARPAnet内,在UUCP内,在BerkNet网内移动邮件的任务,但是没有在这三个网间移动邮件的程序。
突然增加的协议类型,网络数量爆炸性增长的预期,推动Eric Allman来改写delivermail到sendmail。Delivermail程序存在于1979年的BSD Unix的4.0和4.1中,不幸地是,delivermail不具备足够的伸缩性来满足实际的邮件路由需求。或许它最大的缺点是配置被编译进程序中。
在1980年,ARPAnet开始转而由使用网络控制协议(Network Control Protocol 缩写为NCP)到使用传输控制协议(Transmssion Control Protocol 缩写为TCP)。这个改变将网络的主机数量从255增加到超过十亿。另一个改变是由“平面型”的主机名称空间(如 MIT-XX)变成分级的名称空间(如 XX.MIT.EDU)。在发生这个改变前,邮件使用文件传输协议(File Transfer Protocol 缩写为FTP)来进行传输。后来,一种新的协议被开发用来传输邮件,这个协议被称作简单邮件传输协议(Simple Mail Transfer Protocol 缩写为SMTP)。这种发展不是瞬间发生的。在大部分网络改变到TCP后的几年有些网络继续使用NCP。SMTP在最终变成现在的样子前经历了许多的改变。
相对应于这些和其它的改变,Eric发展delivermail到sendmail。来确保邮件在网络间传输时服从相应网络的约定。Eric使用”自由(liberal)”方式来处理和更改地址信息而不是简单地拒绝邮件。在那时,如,UUCP邮件经常没有头信息,所以sendmail必需由草稿状态来创建邮件的头。
Sendmail的第一个版本在BSD
[2] 在1982年到1990年之间有很长的一段时间的间隙
但Eric不是仅有的一个为Sendmail工作的人,在1987年,瑞典的Linköping,大学的Lennart Lovstrand 开发了IDA的增强版本到BSD Sendmail版本5。IDA为Sendmail带来了一系列的性能提高(如支持dbm文件和分开重写头和信封)并修正了一系列的Bug。当快进入90年代时,两个IDA的不同分枝出现了。
Nell Rickert (Northern Illinois University)和Paul Pomes (Northern Illinois University) 对Sendmail来说超越维护IDA工作,伴随着来自全世界的贡献,新的版本(UIUC IDA)象征着开始于Lennart Lovstrand进行维护工作的继续。Neil专注于修正错误和增强配置文件到他当时的m4格式。Paul维护代码,并不断地添加和增强与修正Bug。总的来说,他们的版本是庞大的、雄心勃勃的、并且高度轻便的。它的成功在于解决了许多复杂的邮件路由的问题。
一个Sendmail不同版本的IDA同时也被Paul Vixie开发着(当时在Digital Equipment Corporation)。它被称作KJS (为King James Sendmail),它在Lennart Lovstrand的最新版本的IDA基础上更为保守地进行着开发。KJS主要关注于代码提高面不是更改配置文件。
在这些主要分支功能的增加上,许多卖主更改Sendmail来适合他们的需求。Sun Microsystems公司对于Sendmail有许多的改进和功能增强,包括支持nis和nisplus 映象。Hewlett-Packard也贡献了许多好的增强功能,包括8BITMIME支持。
这些Sendmail版本的扩展带来发极大的混乱。对于一个问题的解决对于另一个版本来说可能意味着悲惨地失败。甚至情况更糟,配置文件不是很方便,并且有些功能不能被共享。
在1992年,Eric开始创建新的Sendmail版本来融合所有其它早期版本。第8版正式采用和吸收了来自IDA,KJS,Sun,和HP的好的功能,并且保持兼容互联网工程任务组织(Internet Engineering Task Force 缩写为IETF)的最新标准。在1996年,Eric开始进行第8版Sendmail的开发工作。这个版本的发行号是V8.7,它继续了以前的开发趋势,添加了许多被请求的新功能和选项,并强调了安全问题。 在1998年,V8.9被发行,它继承了V8.8的开发方向。
在1999年,Sendmail公司,在加利褔尼亚的Emeryville成立。Sendmail公司,接管了开源版本的Sendmail维护和开发工作,并开始为一个商业化版本工作。Sendmail公司的Web站点是:
并且也是开源版本Sendmail的发起站点之一:
如需得到更多的关于开源社区和开源发起(OSI)的信息,请流览:
Sendmail公司提供的第一个版本是V8.10版的Sendmail,该版本发行于2000年。它是由Eric Allman指导开发,但是主要由Greg Shapiro编写代码。
V8.10和V8.11被同时并行开发。Claus Assmann 对V8.10添加了SMTP AUTH和STARTTLS,以及一系列的安全方面的变动,这些变动将Sendmail升级到新版本V8.11。V8.11作为一个商业版本被发行是由于出口限制的问题,很短的时间后,出口限制被解除,并且V8.11以开源的方式发行。
Claus Assmann使Sendmail具有一些开发方向并使版本升级到V8.12,他在这个版本中添加了一些新功能。V8.12支持最新版本的V8系列的Sendmail,但是V8.13和或许V8.14也可能被发行。
计划准备开发支持多线程版本的Sendmail,它将被称作V9 Sendmail,但是,当作者写作本书时,它依然是一个早期的开发计划,并且在随后的几年中可能不会以alpha发行版本的形式出现。
我必需承认我对于Sendmail的如此成功感到非常惊奇。惊奇的不是巨大的市场份额或大量的相关预算。我认为这里有三方面的原因。
首先,Sendmail参用了试图接受,整理,并投递非常“crufty”信息的方式来替代简单地拒绝这些由于不适合某些协议的邮件。我感觉这是非常重要的因为我曾经试图开发一个UUCP和ARPAnet的网关。在那时,ARPAnet非常小,UUCP处于无政府的混乱状态,并且Unix的mail程序总的来说甚至不理解邮件头。这是一项非常困难的工作,但毕竟,它的目标是通讯,而不是书生气十足追究技术细节。
第二点,我限制自己专注于路由功能,而不是专注于写用户代理或后台投递。这对于当时站统治地位的思想来说是一种背叛,当时路由逻辑,本地代理,和常用的网络代码并直接合并到用户代理中,但这使用户无法快速的进入他们新的网络中。
第三点,Sendmail的配置文件有早足够的可伸缩性来满足迅速改变的世界:在1980年代新协议、网络、用户代理呈爆炸式的增长。
并且,当然,它不能伤害它的自由,在恰当的时间的可用性,和完成用户的需求。
配置Sendmail的复杂是因为这个世界就是复杂的。配置文件是动态的是因为世界是动态的。将来Sendmail,如X11,将消亡,如同我不可能始终保持呼吸一样。在这期间,这本书或许对你会有所帮助。
当我开始重写Bryan的第一版手稿,我必需放弃手头与Sendmail相关的主要工作。然后开始阅读不同的细微的Bug和烦人的,容易改正的错误。所以我开始最小的错误修正工作,然后是较大的修正;然后我通讯RFC1123以便Sendmail能满跳最新规格,清除一系列的关于8-bit问题,并且添加ESMTP。公平地说第一版指南和Sendmail第8版的回馈对于两者相互都有提高。
我们将本书分为一个介绍和四个部分,每部分都从不同的侧面来强调Sendmail的细节。
第一章 对于新手来说有特别的帮助。它包含理解邮件投递和Sendmail在代理中所扮角色的基本概念。
第一部分 包括编译,安装,和配置Sendmail的信息,并且随Sendmail源代码一起提供的其它程序的信息。
第二部分 面向更有经验的用户,包括总的管理知识,包含执行调整,处理spam,规则测试,和其它更多的关于Sendmail管理方面的知识。
第三部分 详细地介绍了配置文件的所有方面,并包含完全的引用章节。
第四部分 包含附录
这本书主要面对同时管理邮件的系统管理员。但不是所有的系统都被管理员所管理。许多被程序员,网络工程师,甚至是无经验的用户来管理。我们的希望是能满足你的所有需要,不管你有什么级别的经验。
真正的新手将从第一部分开始阅读本书,如需要可跳过开头部分。
新的系统管理员将可能从第一部分开始阅读,以便于学习如何编译和安装Sendmail,然后读第二部分以便帮助理解如何管理Sendmail。注意第二部分和第三部分将对许多其它地方没有回答的唠叨问题进行解答。
有经验的管理员如果想安装和管理V8 Sendmail,他应当首先阅读第一部分和第二部分来获得背景知识。然后阅读第三部分。
Unix专家和Sendmail专家将发现第三部分的有用价值(甚至Eric也在他的案头放有一册本指南)。在第三章,关于Sendmail的每个不可思议的细节都按照字母顺序被列出。例如,在第三部分,你将发现一个单独的章节来专门介绍选项,对于每一个选项都被列出并被解释。
你的经验级别不会成为问题,本书贯穿始终都假设你熟悉Unix每天的系统工作。如果你对此不熟悉,你必需在其它的地方学习Unix。
在许多地方,我们在类BSD版Unix和它的变种(如FreeBSD)上解释Sendmail。然而AT&T System V (SysV)有些不同(如 Sun 的 Solaris 2.x ),我们将解释这些不同。
贯穿本书主要关注于Sendmail的V8.12版。为了完整,同时有些地方需要,我们也讨论V8.11和更早期(如 BSD的第5版[3],IDA,早期的Sun,Ultrix ,和 NeXT )。
[3]版本号从5跳升至8是因为BSD 4.4 Unix发行版的经理希望所有的软件包都以第8版的版本号发行。在这个决定生效前,新的BSD Sendmail被设计成版本号为6。V6在变成V8前只有alpha和beta版本被发行。
在本书中使用下面的排版约定:
斜体
用于名称,包括路径名,文件名,程序名和命令名,用户名,主机名,机器名,和邮件列表名,以及邮件地址。它也被用于指出一个程序的输出部分。例如,”error: number
or file”指示错误将以一文件或数字的方式显示。斜体也被用来强调被介绍的新术语和概念。
等宽字体
在示例中显示文件的内容或命令的输出。这包括配置文件中的示例或其它文件如信息文件,shell脚本,或C语言程序源文件。等宽文字在显示包含空格的情况时才是必需的;如,五个字符”From “头。
单字符,符号表达式,和命令行开关总是以等宽字体来显示。如,选项说明一个单字符,规则$-说明一个符号表达式,并且-d说明一个命令行开关。
等宽黑体
用于显示由用户键入的文本或其它命令。例如,段落 cat /var/run/sendmail.pid 意味着用户将严格按照示例的样子键入”cat /var/run/sendmail.pid”。
等宽斜体
在示例中用于显示上下文指定或将产生的变量。在串Snum 中,例如,num 将是一个用户分配的整数。
%
指示一个普通用户权限的shell。
#
指示一个root用户权限的shell。
(
对于Sendmail程序的必读资源来自Sendmail程序的作者所写的文档。Sendmail Installation and Operations Guide (位于源代码的 doc/op 目录下 ) 提供安装说明和简洁的配置文件说明。许多厂商也同时提供展示厂商特别的、在本书没有说明的自定义功能在线手册。并且,如果你有源代码,查看 RELEASE_NOTES 文件和所有的 */README 文件。
在本书中仅仅提到的两个主题是域名系统(Domain Name System 缩写为 DNS )和TCP/IP网络通讯。在典型的站点,大量的与邮件相关的间题产生自与Sendmail相关的其它领域的问题。
DNS已被由 Paul Albitz 和 Cricket Liu 编写的的《DNS and BIND》第四版是详细介绍(该书由O’Reilly & Associates, Inc 2001年出版)
在互联网上用于通讯的协议在《TCP/IP 网络管理》这本书中被详细介绍。该书由Craig Hunt 编写(O’Reilly & Associates, Inc 1992)。
最终,许多邮件问题仅能被系统管理员来解决。Sendmail程序由root用户来运行,并且只能由root用户来安装和管理。使Unix系统有效运转的艺术在《Unix System Administration Handbook》这本书中被壮丽地展现给读者。该书由Evi Nemeth, Garth Snyder, Scott Seebass,和Trent R.Hein ( Prentice Hall , 第三版,2000年 ) 。
我们已经尽最大努力来测试和验证本书的信息,但你可能发现事情好像改变了(或甚至我们犯了错误)。请通知我们你发现的任何错误,以及你对于将来版本的建议,通过写信到:
O'Reilly &
Associates, Inc.
(800) 998-9938 (in
the
(707) 829-0515
(international or local)
(707) 829-0104
(fax)
我们对于本书有一个Web站点,在那个站点上我们列出了勘误表,例子,或任何附加信息。你可以在:
http://www.oreilly.com/catalog/sendmail3
来访问这个站点。对本书的评论或询问技术问题,请发邮件到:
对于本书的更多的信息,讨论会,资源中心,和O’Reilly网络,查看Web站点:
首先同时也是最重要的是,我必需感谢Greg Shapiro和Claus Assmann,他们不但维护Sendmail的代码还在不同的邮件列表中回答关于Sendmail的问题,同时对于每个单独的章节都阅读了三次,以便在本书正式出版时不发生错误。
Bruce Mah和Sean Brennan 对于本书第二版做了大量测试工作,另外,Chris Fedde 对于第三版做了大量的测试工作。他们按照本书早期版本草稿建立和运行Sendmail,因此能发现许多描述冗长和需要更正的错误。Gavin Cameron 勇敢地在实际方案中应用checkcompat()示例,因此,对我来说能帮助调试代码。Mark D.Roth 亲切地检查了ph数据库类型并对代码进行了有益的精减。
无需说明,如果没有Eric Allman 首先编写 Sendmail 这本书也不可能完成。每版的手草稿都送到他手中,并且他花费了很多时间来确保技术正确性,提升内在质量,并对Sendmail的问题提出了有意思的解决建议。
对于第二版,Cricket Liu 亲切地检查了第九章,并发现了逃过许多人眼睛的几个错误。
George Jansen,是一位杰出的编译,将我所有早期手稿文字调整到新的,更适合出版的样了。他不知疲倦地从我的第一稿一直帮我改正到这个版本。
同时还应该称赞和感谢Tim O’Reilly同意首先开始本书的出版工作。他的经验将本书发展到目前这个样子。他知道“大图”贯穿本书的意义他并且始终倾听读者的心声。没有他的建议,这本书将变得难以忍受的复杂和厚重。
另外的感谢必需送给Lenny Muellner和 Mike Slerra ,他们调整本书的手稿的troff宏来满足本书的独特需求,并且Edle Freedman 温文地接受我令人苦恼的,除了本书之外封面、和图片的绘制工作。
在O’Reilly & Associates 公司的产品部的工作人员们对于本书的完成做出了许多突出的工作。对于早期版本要特别感谢Barbara Willette 的文字编辑工作,Nancy Kotary 对于最终产品化提供了帮助,Kismet McDonoughChan对于产品的每一段都提供了帮助,Chris Reilly提供了配图,Mary Anne Weeks Mayo进行质量控制工作,Curt Degenhart, Madeleine Newell,和 Ellie Fountain Maden 进行编辑工作,Seth Maislin完成索引方面的工作,Danny Marcus进行校对工作。
对于第三版来说,要特别感谢Robert J.Denn来管理这个项目,Darren Kelly帮助本书最终产品化,Rob Romano和Jessamyn 准备图片,Mary Brady, Linley Dolby, Matt Hutchinson,和Claire Cloutier完成质量控制工作,Reg Aubry , Julie Hawks,Genevieve d’Entremont,和Judy Hoer 提供产品支持,Brenda Miller 对第二版的索引进行更新,并且Audrey Doyle进行校对。
本书的中文版,译者要首先感谢我的妻子杲纪伟,她是河北省南宫一所普通的乡村中学的教师,没有她日夜操劳照顾我们不满一周岁的女儿小佳璐,我不可能有时间来完成本书中文版的翻译。另外还要感谢美国北卡莱罗那州的Raceigh的Clyde Goodrum,在约十年前是他在相对偏僻河北南部小城邢台,给当时刚出校门打工的我在英文上予以指导,使我的英文水平得以提高。另外,还要感谢1998年在北京师范大学中文系进修的英国朋友Dan,由于当年我们之间的语言交流,使我的英文水平更进一步,同时还他还教我使用互联网。没有这些亲人和朋友们的帮助,就不会有该书中文版。
想像一下你拿着纸和笔,给远方的朋友写了一封信。你在写完信后签上自己的名字,反思一下自己写了什么,然后将信摺起放入信封。你将朋友的地址写在信封的前面,你自己的回复地址写在左上角,邮票粘在右上角,这时信已准备好能进行邮寄了。电子邮件(email是它的缩写)也是按照同样的方式时行准备的,但是一个计算机用于替代纸和笔。
邮局将实际的信件放入实际的邮包,与之相对,Sendmail在电子的邮包中传送电子信件。如果你的朋友(收信人)是在你隔壁的房间(同一台计算机),仅单个邮局(Sendmail运行于本地)发生投递事件。如果你的朋友在很远的外地,邮件信息将从本地邮局(Sendmail运行于本地主机)转发到远方的另一个邮局(Sendmail运行于远方)来进行投递。尽管Sendmail在许多方面与一个真实世界中的邮局很相似,但在一些方面Sendmail具有一些高级特性:
投递发生在几秒钟内而不是几天。
地址改变(转发)立即生效,并且邮件可以转发到世界的任何地方。
主机地址是进行动态查询。因此,机器可以被迁移或重新命名,这时邮件仍然可以成功投递。
邮件通过能访问其它网络的程序进行投递(如UUCP和BITNET)。这和联邦包裹公司为邮局投递头一天的信件的情况有些相似。
这个在邮局和Sendmail之间的简单类比将掩盖Sendmail工作的许多技术细节。但是这个类比能说明Sendmial在工业中的角色,所以我们继续用这个类比来说明Sendmail的更明显的特点。
如果没有深入理解由互联网工程师任务协会(IETF)在网络信息中心(NIC)发布的注释请求(Requests for Comments 缩写为RFC )要完成理解Sendmail是不可能的。 这些被编号的文档定义(还有其它的事务)了SMTP和电子邮件的信息头。
当你在本书中遇到对一个RFC的引用时,它将被列出,例如,如RFC2821。与Sendmail相关的RFC在后面的参考书目章节中被列出。
一个邮件用户代理(MUA)是用户运行来用于读取,回复,编写,和处理电子邮件的一类程序。MUA的例子包括源自Unix mail程序(/bin/mail);Berkeley Mail程序;系统V与之相对应的是(mailx);自由软件程序如mush, elm, 和mh ;和商业化程序如Zmail 。在PC上也有MUA的程序例子。Eudora和ClarisWorks是两个标准的MUA程序。许多MUA能在单机上存在。MUA有时执行功能有限的邮件传输,但对于MUA来说由于这个任务过于复杂而不适合它。在本书中我们不汲及MUA的内容。
邮件传输代理(MTA)是在机器之间进行投递和传输的高级专用程序,类似邮局完成的工作。通常,在一个机器上只有一个MTA。Sendmail程序就是一个MTA。
从V8.10开始,sendmail也认可邮件提交代理(MSA)的角色(mail submission agent 缩写为MSA),MSA在RFC2476中被定义。MTA不支持改动邮件的文字,除了添加 Received:,Return-Path:,和其它必需的头。被MUA提交的电子邮件可能需要被MTA进行更多的改动来满足电子邮件的合法性,所以一个新角色MSA被创建了。一个MSA从一个MUA接受邮件,并且有合法的权力来对邮件进行添加,删减,屏蔽和更改电子邮件。一个MSA,例如,能确保所有的主机名是完全合格的,并且邮件的头,如Date:,总被包括进电子邮件中。
其它的MTA
Sendmail程序不是唯一的被出售MTA。其它的MTA已经存在了一阵子时间,并且每过一段时间就会出现一种新的MTA。在这里我们简要介绍几种主要的MTA:
Qmail
强调模块化和安全,qmail号称要替代sendmail,qmail程序是一个开源项目,可以从 http://www.qmail.org 来得到它的源代码。
Postfix
由Wietse Venema编写,他是一个在IBM研究部门工作的安全专家,Postfix声称是sendmail的替代产品,它能更快、更方便、更安全地投递电子邮件。Postfix程序是一个开源项目,它可以从 http://www.postfix.com 获得。
Sun ONE Messaging Server
这是一个支持多线程的商业化MTA产品,它声称比sendmail更稳定,更快速,并且大量的商业信息由http://www.sun.com 上提供。
Sendmail Switch [1]
这个产品和我们在本书中说明的Sendmail一样的产品,但是它有选择的进行了商业化的增强,并且有一套支持软件来完成电子邮件的解决方案。更多的信息能在 http://www.sendmail.com 上获得。
目前还有许多其它的MTA,有些好有些不是很好。我们在这里仅提到上面的五个,是毕竟,这是一本关于开源sendmail的
为什么Sendmail是如此复杂
在最简单的情况下,在同一台机器上从一个用户将邮件传递到另一个用户时,sendmail显得微不足道。所有提供商销售提供发送邮件服务的软件(和配置文件)都能满足这项功能。但是当你的要求增加时,发送邮件的工作变得更为复杂,并且配置文件也变得更为复杂。在连结到互联网的主机上,例如,sendmail将使用DNS将主机名转换成网络地址。使用UUCP连接的机器,在网络的另一端,需要sendmail运行uux程序。
由于sendmail需要在大量不同的机器之间传输邮件,因此,它的配置文件被设计成非常强的可伸缩性。这个概念允许单个二进制程序能布署于许多不同的机器上,但是它的配置文件能被自定义来满足不同的独特要求。这个配置需求使得sendmail变得如此复杂。
当邮件需要被投递到特殊用户,例如,sendmail程序基于配置文件来决定最适合的投递方法。决定过程包括如下步骤:
如果邮件接收者和发送者位于同一台主机,投递邮件时使用 /usr/sbin/mail.local程序。
如果邮件接收者和邮件发送者的主机通过UUCP连接,则使用uux来发送邮件。
如果邮件的接收者主机在互联网上,发送主机使用SMTP来传输邮件。
否则,邮件信息可能需要通过其它的网络来传输(如 BITNET )或可能被拒绝。
Sendmail程序实际上由几部分组成,包括程序,文件,目录,和它提供的服务。它的基础是定义位置和其它部分行为,和一系列对邮件地址进行重写规则组成配置文件。一个队列目录保存邮件直到它被投递。一个别名文件允许更改用户名并创建邮件列表。数据库文件可以处理垃圾邮件拒绝和虚拟主机等方面的搜索任务。
配置文件
配置文件中包含sendmail要完成工作的所有信息。在你所提供的信息内,如文件位置,许可权限,操作模式。重写规则和规则集也配置文件中列出。重写规则的作用是对需要进行投递的邮件的地址由一种格式转换成另一种格式。它可能是在配置文件中唯一一个使人糊涂的部分。因为配置文件被设计成能被sendmail快速读取和解析的格式,规则集的样子对于人类来说显得十分神秘。
R $+ @ $+ $: $1 < @ $2 > focus on domainR $+ < $+ @ $+ > $1 $2 < @ $3 > move gaze right
但它们看起来复杂其实是什分简洁。在每行开始的R,例如,标记 rewrite 规则,并且$+这个表达式意味着匹配地址的一个或多个部分。依照经验,如此表达(在整个配置文件中的确如此)很快将变得很神秘。
幸运地是我们不需要学习规则集配置的细节来安装和配置sendmail。 如mc格式的配置文件将你同这些细节相隔离,并且允许你很容易地执行非常复杂的任务。
队列
并不是所有的邮件都能被立即投递。当投递被延时,sendmail必需有能力将邮件保留以便于日后进行传输。Sendmail队列包含一个或多个用于保存邮件直到被投递的目录。一封邮件可能被排队等候投递:
l
当目的主机不可达或宕机。邮件信息在目的主机重启服务后将被重新投递。
l
当邮件信息有许多接收者。有些邮件能成功投递但有些不能。这些投递失败的邮件将排在队列中供以后投递。
l
当邮件信息比较昂贵,昂贵的邮件(如邮件通过长途电话线进行投递)能被排入队列中直到费率降低时再被投递。
l
当(从V8.11)开始鉴定或流编码遭到临时中断而重新开始时,信息被排队用于日后重试投递。
l 总是因为主要涉用安全原因,sendmail程序被配置成默认将所有邮件排队,因此能最小化在机器崩溃时邮件丢失的风险。
别名和邮件列表
别名允许发往一个邮箱的邮件被重定向到其它地址。他们也允许邮件通过管道被附加到一个文件或程序,并形成邮件列表的基础。别名的核心是aliases文件(通常被存储成数据库格式以便于相关搜索)。别名也可以在用户的家目录下通过 .forward文件来为每个用户单独创建。
在这章,我们将测试建立邮件的三个部分:邮件头,邮件体,信封。但在我们开始下面的步骤前,我们必需首先示范如何通过手动启动Sendmail,以便于你能看到信息各部分的样子。
手动运行sendmail
大多数用户不直接运行sendmail。作为替换,他们使用许多MUA中的一个来撰写邮件。这些MUA在后台不可见地将邮件传递给sendmail,创建合适的传送实例外观。接着sendmail程序以表面上神秘的方式来专注于电子邮件的投递工作。
尽管多数用户不直接运行sendmail,但最好是合法的进行这项工作。你,如同许多系统管理员,可能需要参用这种措施来根踪和逋捉邮件并以此为依据来解决邮件问题。
这里有一个手动运行sendmail的演示。首先创建一个命名为sendstuff的文件内容如下:
This is a on-line message.
然后,将这封邮件发送给你自已,使用下面的命令,在这里you是你在系统的登录名:
$ /usr/sbin/sendmail you <sendstuff
这里,你直接通过指定全路径来运行sendmail。[2]当你运行sendmail,任何不是以一个 – 开始的命令行参数都被视作你将发送的邮件用户名。
[2]在你的系统上,路径名可能不同。如果文件存在一单独行,行中只有一个点。这行将被看作文件结尾的标志。例如,尝试在路径/usr/lib 或 /usr/ucblib 中搜索 sendmail。
其中
<sendstuff序列将引起你创建的文件(sendstuff)内容被重定向到sendmail程序。Sendmail程序将所有从标准输入传送过来的内容(直到文件尾)都当作邮件来传投。[3]
[3]为了简单起见,我在这里蒙大家。如果文件存在只有一个点的单行,这行将被看作文件结束的标志。如果你需要一个有如此字面输入的行,使用 IgnoreDots选项 (IgnoreDots)。
现在查看你刚才发送的邮件信息。你如何做是非常不同的。许多用户仅敲击mail来查看邮件。其它用户使用mh(1)包并敲击inc来接收和显示和查看邮件。不管你通过什么正常方式查看邮件。接收的邮件都将以文件形式保存下来。它的内容看起来如下:
From you@Here.US.EDU Fri Dec 13 08:11:44 2002Received: (from you@localhost) by Here.US.EDU (8.12.7 /8.12.7) id d8BILug12835 for you; Fri, 13 Dec 2002 08:11:44 -0600 (MDT)Date: Fri, 13 Dec 2002 08:11:43From: you@Here.US.EDU (Your Full Name)Message-Id: 200201011548.d872mLW24467@Here.US.EDU>To: you此处可能看起来如其它样子 (see NoRecipientAction)
This is a one-line message.
首先要注意的事情是文件开头七行的文本不是你当时原始邮件中所有的。这些行被sendmail程序所添加并且你的本地邮件投递代理程序要调用邮件头。
从你的文件sendstuff的最初行。它被分一个空行分开。邮件信息正文跟在邮件头后并且存在首部的空行后是信件的全部内容。(查看 图
1-1 )
(Figure 1-1 )
平常,当你使用你的MUA发送邮件时,MUA添加邮件头并对sendmail注入邮件头和邮件正文。这时,然而,你能直接运行sendmail并且仅对sendmail提供邮件正文;邮件头将被sendmail所添加。
邮件头
下面让我们更加详细的介绍一下邮件头。
From you@Here.US.EDU Fri Dec 13 08:11:44 2002Received: (from you@localhost) by Here.US.EDU (8.12.7 /8.12.7) id d8BILug12835 for you; Fri, 13 Dec 2002 08:11:44 -0600 (MDT)Date: Fri, 13 Dec 2002 08:11:43From: you@Here.US.EDU (Your Full Name)Message-Id: 200201011511.d872mLW24467@Here.US.EDU>To: you可能是其它的一些东西 (查看 NoRecipientAction)
注意邮件头的许多行开始于一个紧随冒号单词。每个单词告䜣行的其余部分的种类。在一个邮件信息中可以有很多种类的邮件头行。有些是必需的,有些是可选的,并且有些可以显示很多次。这封你发送给你自己的邮件所显示的信息都是必需的,[4] 这是为什么sendmail添加这些到邮件信息中的原因。以“From ”这五个字符开始的行(第五个字符是空格)被一些程序(如/bin/mail)添加但不是被其它的程序(如 mh )。
[4]为了简单表达,我们在这里蒙人。Message-ID:头不是严格的必需。
一个Received:行是当每次一台主机接收到邮件时添加的。(如果这里有太多的行,邮件信息将被弹回,因为它可能被回环并且被当作发送失败邮件而返回给邮件发送者。)缩进行是上面Received:行的继续。Date:行给出邮件最初发送时的日期和时间。From:行列出电子邮件地址和发送邮件者的全部名。Message-ID:行如同一个序列号来保证邮件信息的统一标识。To:[5] 行显示一系列一个或多个邮件接收者。(多个邮件的接收者将用逗号隔开。)
[5] 依赖于NoRecipientAction选项是如何设定,这将是一个Apparently-To:头,一个Bcc:头,或甚至一个To:头紧随着“undisclosed-recipients:;”(查看 NoRecipientAction 选项 )
邮件正文
邮件信息的正文存在由从第一个空行到文件的结尾部分所组成。当你发送你的sendstuff文件,它仅有正文。现在,编辑文件sendstuff并添加一个小头:
In this section, we will examine the three parts that make up a mail message: the header, body, and envelope. But before we do, we must first demonstrate how to run sendmail by hand so that you can see what a message's parts look like.
Most users do not run sendmail directly. Instead, they use one of many MUAs to compose a mail message. Those programs invisibly pass the mail message to sendmail, creating the appearance of instantaneous transmission. The sendmail program then takes care of delivery in its own seemingly mysterious fashion.
Although most users don't run sendmail directly, it is perfectly legal to do so. You, like many system managers, might need to do this to track down and solve mail problems.
Here's a demonstration of one way to run sendmail by hand. First create a file named sendstuff with the following contents:
This is a one-line message.
Second, mail this file to yourself with the following command line, where you is your login name:
% /usr/sbin/sendmail you <sendstuff
Here, you run sendmail directly by specifying its full pathname.[2] When you run sendmail, any command-line arguments that do not begin with a - character are considered to be the names of the people to whom you are sending the mail message.
[2] That path might be different on your system. If so, substitute the correct pathname in all the examples that follow. For example, try looking for sendmail in /usr/lib or /usr/ucblib.
The <sendstuff sequence causes the contents of the file that you have created (sendstuff) to be redirected into the sendmail program. The sendmail program treats everything it reads from its standard input (up to the end of the file) as the mail message to transmit.[3]
[3] We are fudging for simplicity here. If the file contains a line that contains only a single dot, that line will be treated as if it marks the end of the file. If you need to include such a line as part of literal input, use the IgnoreDots options (IgnoreDots).
Now view the mail message you just sent. How you do this will vary. Many users just type mail to view their mail. Others use the mh(1) package and type inc to receive and show to view their mail. No matter how you normally view your mail, save the mail message you just received to a file. It will look something like this:
From you@Here.US.EDU Fri Dec 13 08:11:44 2002Received: (from you@localhost) by Here.US.EDU (8.12.7 /8.12.7) id d8BILug12835 for you; Fri, 13 Dec 2002 08:11:44 -0600 (MDT)Date: Fri, 13 Dec 2002 08:11:43From: you@Here.US.EDU (Your Full Name)Message-Id: 200201011548.d872mLW24467@Here.US.EDU>To: you
might be something else (see NoRecipientAction)This is a one-line message.
The first thing to note is that this file begins with seven lines of text that were not in your original message. Those lines were added by sendmail and your local delivery program and are called the header.
The last line of the file is the original line from your sendstuff file. It is separated from the header by one blank line. The body of a mail message comes after the header and consists of everything that follows the first blank line (see Figure 1-1).

Ordinarily, when you send mail with your MUA, the MUA adds a header and feeds both the header and the body to sendmail. This time, however, you ran sendmail directly and supplied only a body; the header was added by sendmail.
Let's examine the header in more detail.
From you@Here.US.EDU Fri Dec 13 08:11:44 2002Received: (from you@localhost) by Here.US.EDU (8.12.7 /8.12.7) id d8BILug12835 for you; Fri, 13 Dec 2002 08:11:44 -0600 (MDT)Date: Fri, 13 Dec 2002 08:11:43From: you@Here.US.EDU (Your Full Name)Message-Id: 200201011511.d872mLW24467@Here.US.EDU>To: you
might be something else (see NoRecipientAction)
Notice that most header lines start with a word followed by a colon. Each word tells what kind of information the rest of the line contains. Many types of header lines can appear in a mail message. Some are mandatory, some are optional, and some can appear many times. Those that appeared in the message you mailed to yourself were all mandatory.[4] That's why sendmail added them to your message. The line starting with the five characters "From " (the fifth character is a space) is added by some programs (such as /bin/mail) but not by others (such as mh).
[4] We are fudging for simplicity. The Message-ID: header is not strictly mandatory.
A Received: line is added each time a machine receives the mail message. (If there are too many such lines, the mail message will bounce梑ecause it is probably in a loop梐nd will be returned to the sender as failed mail.) The indented line is a continuation of the line above, the Received: line. The Date: line gives the date and time when the message was originally sent. The From: line lists the email address and the full name of the sender. The Message-ID: line is like a serial number in that it is guaranteed to uniquely identify the mail message. And the To:[5] line shows a list of one or more recipients. (Multiple recipients would be separated with commas.)
[5] Depending on how the NoRecipientAction option was set, this could be an Apparently-To: header, a Bcc: header, or even a To: header followed by an "undisclosed-recipients:;" (see NoRecipientAction).
A complete list of all header lines that are of importance to sendmail is presented in Chapter 25. The important concept here is that the header precedes, and is separate from, the body in all mail messages.
The body of a mail message consists of everything following the first blank line to the end of the file. When you sent your sendstuff file, it contained only a body. Now, edit the file sendstuff and add a small header:
Subject: a test添加
添加This is a one-line message.
Subject:头行是可选的。Sendmail程序将按原样来传送它。这里,Subject:行被一个空行紧随,之后是信息文本,格式化的邮件头和邮正文。注意空行必需是真的空行。如果你输入空格或tab字符,因此其格式是一个“空的行”,邮件头将不会按照你的需要从邮件正文分开邮件头。
再次给你自己发送邮件,如上次一样手动运行sendmail程序:
$
/usr/sbin/sendmail you <sendstuff
注意我们的Subject:头行被没有改变的传送:
From you@Here.US.EDU Fri Dec 13 08:11:44 2002Received: (from you@localhost) by Here.US.EDU (8.12.7 /8.12.7) id d8BILug12835 for you; Fri, 13 Dec 2002 08:11:44 -0600 (MDT)Date: Fri, 13 Dec 2002 08:11:43From: you@Here.US.EDU (Your Full Name)Message-Id: 200201011511.d9BMTuX29709@Here.US.EDU>Subject: a test注意
To: you This is a one-line message.
邮件信封
为了便于更加容易地对不同邮件接收者进行邮件投递,sendmail程序使用信封的概念。信封的概念类比用于邮局投递邮件的物理信封。想像一下你希望一个文件的两个拷贝,一个给你的隔壁办公室的朋友另一个给跨国友人:
To: friend1, friend2@remote
在你复印的文档后,你将不同的文档塞入不同的信封。你将一个信封递给办事员,办事员将该信件传送到隔壁并交给相邻办公室的 friend1 。这如同在本地主机进行投递。办事员将其它的拷贝投入角落的邮筒中,之后邮局按照信封上的国家将邮件投递到 friend2@remote 。这如同sendmail将邮件传送到远程主机。
为了图示说明信封是什么样的,考虚sendmail可能运行的 /usr/lib/mail.local,一个执行本地投递的程序:
deliver to friend1's mailbox
![]()
/usr/lib/mail.local -d friend1
sendmail
runs
![]()
the envelope recipient
在这里sendmail运行使用 –d 选项来 /usr/lib/mail.local 程序,这将告诉 /usr/lib/mail.local来将 friend1的邮箱添加到邮件信息中。
信息说明了邮件的发送者和接收者,但不是信息头的部分,它被考虑成信封信息。这两者可能或可能不存在相同的信息(现在这点将被掩盖)。在/usr/lib/mail.local的情况下,电子邮件信息在邮件头上显示两个邮件的接收者:
To: friend1, friend2@remote
the header
但是传给/usr/lib/mail.local仅显示一个信封信息 (查看一个合适的本地投递 ):
-d friend1
指定信封
现在考虑在网上邮件信封的传递。当发送网络邮件时,sendmail在发送邮件信息前,必需给远程站点信封—发送地址和一系列分开的邮件接收者地址(头和邮件正文)。 图 1-2 显示这是一个非常简单的在本地sendmail和远程主机的sendmail之间的会话。
本地的sendmail告诉远程主机的sendmail这里有一个邮件发自你(信封的发送者)并给 friend2@remote 。它在传送邮件信息头前分别传达邮件发送者信封和邮件接收者信息。因为这些信息被邮件头分别传送,它被称作信封。
仅一个邮件接收者在信封中被列出,无论是否有两个收信人在邮件信息头中被列出:
To: friend1, friend2@remote
远程主机将不需要知道本地用户,friend1 , 所以很少的接收信息会被排除在信封外。
一个给定的邮件信息能被许多不同的信封所发送(如上面的两个不同的接收者)。但
后 记