字体:  

sendmail大全

linux 发表于: 2001-11-13 00:40 来源: 动力社区

sendmail大全
BBS 水木清华站 01-11-09 21:48 742p ruster
--------------------------------------------------------------------------------

发信人: ruster (尘埃*星辰*领悟), 信区: Linux
标 题: 第七章 电子邮件(上)
发信站: BBS 水木清华站 (Thu Dec 21 13:44:24 2000)

第7章 电子邮件
本章要点:
本章讨论电子邮件服务的基本概念及其配置、管理。
本章具体包括以下内容。
邮件传送的基本过程
sendmail的配置
邮件服务的一些特殊功能
qmail的简单介绍
7.1 sendmail 和SMTP

7.1.1 smtp和邮件传输代理
sendmail是最重要的邮件传输代理程序。理解电子邮件的工作模式是非常重要的。一
般情况下,我们把电子邮件程序分解成用户代理,传输代理和投递代理。
用户代理用来接受用户输入的指令,将用户给出的信件报文传送至信件传输代理。而
投递代理则从信件传输代理取得信件传送至最终用户的邮箱。显然,最终用户只能看到
用户投递代理。
当用户试图发送一封电子邮件的时候,他并不能直接将信件发送到对方的机器上,用
户代理必须试图去寻找一个信件传输代理,把邮件提交给它。
信件传输代理得到了邮件后,首先将它保存在自身的缓冲队列中,然后,根据邮件的
目标地址,信件传输代理程序将找到应该对这个目标地址负责的邮件传输代理服务器,
并且通过网络将邮件传送给它。对方的服务器接收到邮件之后,将其缓冲存储在本地,
直到电子邮件的接收者察看自己的电子信箱。
显然,邮件传输是从服务器到服务器的,而且每个用户必须拥有服务器上存储信息的
空间(称为信箱)才能接受邮件。(发送邮件不受这个限制)
可以看到,一个邮件传输代理的主要工作是监视用户代理的请求,根据电子邮件的目
标地址找出对应的邮件服务器,将信件在服务器之间传输并且将接收到的邮件缓冲或者
提交给最终投递程序。
有许多的程序可以作为信件传输代理,但是sendmail是其中最重要的一个,事实证明
它可以支持数千甚至更多的用户,而且占用的系统资源相当少。不过,sendmail的配置
十分复杂,因此,也有人使用另外的一些工具,如qmail。当然,基
于Windows NT的Exchange Server和NetScape Message Server也是这种产品的例子。
无论什么产品,它们必须支持同样的规范,如信件传输的报文格式,监听的端口等等
。一般来说,系统管理员并不需要了解信件传输的命令标准,用户代理会生成正确的命
令。但是,了解其他一些信息是重要的。
信件传输代理运行在25端口接受请求,当接受用户的请求时,它不需要了解用户的真
实身份,或者说不需要身份验证。因此用户不需要提交用户口令就可以发出电子邮件,
这意味着任何用户都可以冒充成另外一个用户发出假的电子邮件,这是电子邮件设计的
一个基础,无法消除。(关于这一点目前有一点说明。许多基于UNIX的系统运行indent
d,可以记录客户机器上的用户的登录名字。不过,这个功能实际上用处不大,毕竟大部
分人不会用UNIX/Linux作为他的个人机器)。
当sendmail程序得到一封待发送的邮件的时候,它需要根据目标地址确定将信件投递
给那一个服务器,这是通过DNS服务实现的。例如,有一封邮件的目标地址是someone@y
ahoo.com,那么,sendmail首先确定这个地址是用户名(someone)+机器名(yahoo.co
m)的格式,然后,通过查询DNS来确定需要把信件投递给某个服务器。
DNS数据中,与电子邮件相关的是MX记录,这可以在查询DNS时设置查询类型为mx来得
到:
[wanghy@mail ~]$ nslookup
Default Server: www.asnc.edu.cn
Address: 202.199.248.2

> set q=mx
> yahoo.com
Server: www.asnc.edu.cn
Address: 202.199.248.2

Non-authoritative answer:

yahoo.com preference = 0, mail exchanger = mx1.mail.yahoo.com
yahoo.com preference = 1, mail exchanger = mx2.mail.yahoo.com
mx1.mail.yahoo.com internet address = 128.11.68.225
mx2.mail.yahoo.com internet address = 128.11.68.217
显然,在DNS中说明yahoo.com有两个信件交换(MX)服务器,于是,sendmail试图将
邮件发送给两者之一。一般来说,排在前面的的MX服务器的优先级别比较高,因此服务
器将试图连接mx1.mail.yahoo.com的25端口,试图将信件报文转发给它。如果成功,你
的smtp服务器的任务就完成了,在这以后的任务,将由mx1.mail.yahoo.com来完成。在
一般的情况下,mx交换器会自动把信件内容转交给目标主机,不过,也存在这样的情况
,目标主机(比如yahoo.com)可能并不存在,或者不执行smtp服务,而是由其mx交换器
来执行信件的管理,这时候,最终的信件将保存在mx机器上,直到用户来察看它。
可以简单地在DNS记录中用MX关键字设置信件交换,例如,在我们的设置中:
@ IN SOA openlab.asnc.edu.cn. wanghy.openlab.asnc.edu.cn.
(
1997022700 ; Serial
28800 ; Refresh
14400 ; Retry
3600000 ; Expire
86400 ) ; Minimum
IN NS openlab.asnc.edu.cn.
IN MX 10 mail.asnc.edu.cn.
IN MX 20 mail2.asnc.edu.cn.
openlab IN A 202.199.248.6
openlab IN MX 10 mail2.asnc.edu.cn.
mail IN A 202.199.248.11
www IN A 202.199.248.2
mail2 IN A 202.199.248.177
这里面定义了三个MX记录,MX记录的规则是[机器名/域名] IN MX [优先级] [服务
器]。优先级是一个整数,数值越小优先级越高。第一个IN MX 10 mail.asnc.edu.cn.因
为没有机器名,使用来自named.conf的缺省后缀,就是asnc.edu.cn,这个定义也就是让
所有some@asnc.edu.cn的信件传送到mail.asnc.edu.cn。IN MX 20 mail2.asnc.edu.cn
.的概念差不多,只是其优先数为20,也就是说只有当mail.asnc.edu.cn拒绝接受(比如
,服务器忙或者当机)的时候,信件才会投递到mail2.asnc.edu.cn。openlab IN MX 1
0 mail2.asnc.edu.cn.定义凡是someone@openlab.asnc.edu.cn的信件要发送到mail2.a
snc.edu.cn,以此类推。
MX记录可以使得整个子域内的用户使用同样的邮件主机和传输代理,另外,如果你的
主机不 姨 痪了,那么信件可以暂时存储在你的信件 换主机上,直到你自己的机器恢
复为止。比如说,mail.yourdomain.com是一台smtp主机,而mx2.yourdomain.com是另外
一个smtp主机,你希望在mail.yourdomain.com正常的时候直接由其自身收发邮件,而万
一mail崩溃,mx2为它暂时存储一段时间的邮件直到mail恢复正常工作-这是常见的设置
,那么,你需要把mail以比较高的优先数设置成自己的信件交换主机,而mx2作为一个优
先数较低的信件交换主机,也就是,在你的DNS配置文件中,应该这样配置:
mail IN MX 0 mail

IN MX 10 mx2
如果DNS查询无法找出对某个地址的MX记录(通常因为对方没有信件交换主机),那么
sendmail将是试图直接与对方的主机(来自邮件地址)对话并且发送邮件。例如,test@
openlab.asnc.edu.cn在DNS中没有对应的MX记录,因此sendmail在确定MX交换器失败后
,将从DNS取得对方的IP地址并直接和对方对话试图发送邮件。
sendmail发送邮件时,如果经过设定的时间后仍然未能将信件投递到目的主机,它将
返回一个错误信息并且休息一段时间,然后重新试图投递,如果连续多次失败,sendma
il最终将放弃投递并将错误信息投递给postmaster用户。在许多机器上,postmaster用
户是root用户的一个别名(参考下面关于别名的内容),你应该将它设置为邮件的实际
管理员的用户名。
上面说的基本就是sendmail的工作方式,然而仍然有一个很让人迷惑的东西,就是所
谓“信封地址”。简单地说,当sendmail向目标地址发信的时候,它并不是直接用你的
信件内容发送,相反,它依赖于你给它的命令。例如,你可能会用mail程序向某个地址
这样发信:
$mail someone@somedomain.com
Tother@otherdomain.com

Subject:test mail
test
.
那么,当sendmail发信的时候,它是向someone@somedomain.com发信而不是other@ot
herdomain.com。相应地,如果你想向两个人发信,例如你在outlook里面写上:“投递
给user1@a.com,抄送user2@b.com”,那么sendmail应该怎么做?直接同时向两个地址
发信吗?否,它试图构造两个包装(称为信封),每个包装上只列出一个投递地址,各
投递一次。虽然邮件正文的头部仍然包含两个地址,但是sendmail不会看它。
7.1.2 sendmail的配置
sendmail是一个极为复杂的程序,其行为主要地依赖于在UNIX界“臭名昭著”的/etc
/sendmail.cf配置文件。实际上,我怀疑会有谁真的从头去写一个sendmail.cf文件。一
般来说,我们总是用m4宏处理来书写sendmail.cf。实际上,m4程序几乎和sendmail.cf
一样复杂,不过,通常我们只需要关心一些比较重要的部分。
要使用宏处理程序,必须确定你已经安装了m4和sendmail-cf这样两个软件包,我们这
里讨论的是sendmail版本8.9.3,缺省下,sendmail-cf安装在/usr/lib/sendmail-cf目
录下。
录下。
我们首先从构造一个简单的可以使用的sendmail.cf文件开始,首先建立这样一个文件
,称为sendmail.mc,并将其拷贝到/usr/lib/sendmail-cf/cf目录下:
include(`../m4/cf.m4')
define(`confDEF_USER_ID',``8:12'')
OSTYPE(`linux')
FEATURE(redirect)
FEATURE(always_add_domain)
FEATURE(use_cw_file)
FEATURE(local_procmail)
MAILER(procmail)
MAILER(smtp)

注意里面的正反引号,而且不能随便加入空格。
然后,用m4程序可以生成一个sendmail.cf:
m4 sendmail.mc > /etc/sendmail.cf
接下来,启动sendmail程序:
killall sendmail
sendmail –bd –q15m
你会发现现在你可以在这台主机上发送电子邮件了。
一般情况下,我们可以象这样用m4程序生成sendmail.cf,通过更改模板来改变sendm
ail.cf的内容。一个mc模板文件通常可以包含几个段落:
divert
通常总是设置为divert(-1)让m4在输出中去掉一些垃圾。
OSTYPE
OSTYPE
定义使用的操作系统类型,当然在我们的情况下就是linux,但是一定要注意m4程序中
引号的用法,一个反引号和一个正引号才代表把对应的东西括起来。
define
定义一些全局设置,对于Linux系统,设置了OSTYPE之后,可以定义下面的一些全局
参数,如果不定义,就使用缺省值。例如:
define(ALIAS_FILE,/etc/aliases)
变量名 说明(方括号中为缺省值)
ALIAS_FILE [/etc/aliases]
别名文件的位置。如果有多个别名文件,需要把它们用引号括起来(别忘了引号规则
!)。
confCR_FILE [/etc/mail/relay-domains]
缺省的域定义文件,在这个域中定义的域中机器可以通过你的服务器进行邮件发送。

HELP_FILE [/usr/lib/sendmail.hf]
此文件中含有对SMTP的HELP命令进行响应时要列出的信息。
QUEUE_DIR [/var/spool/mqueue]
邮件队列文件所在目录。
STATUS_FILE [/etc/sendmail.st]
sendmail的状态信息文件。
LOCAL_MAILER_PATH [/bin/mail]
用于投递本地邮件的程序。
LOCAL_MAILER_FLAGS [rmn9]
local mailer要用到的标志,永远包含标志lsDFM。
LOCAL_MAILER_ARGS [mail -d $u]

在投递本地邮件时所传送的参数。
LOCAL_MAILER_MAX [没有]
如定义了此参数,则为此邮件服务器所能接收最大单个邮件大小。
LOCAL_MAILER_CHARSET [没有]
如果定义了此参数,则被转化为MIME格式的从其他地址到local mailer的含有8位字符
的信息将被标为此字符集。
LOCAL_SHELl_PATH [/bin/sh]
用于投递利用管道功能处理的邮件的shell.
LOCAL_SHELL_FLAGS [eu9]
prog mailer用到的标志。在此标志中永远包含标志lsDFM.
LOCAL_SHELL_DIR [$z:/]
shell运行时所要查找的目录路径。
USENET_MAILER_PATH [/usr/lib/news/inews]
用于投递电子新闻组的程序名称。
USENET_MAILER_FLAGS [rlsDFMmn]
usenet mailer的投递标志。
USENET_MAILER_ARGS [-m -h -n]
usenet mailer的命令行参数。
USENET_MAILER_MAX [100000]
usenet mailer所能接收的最大信息大小。
SMTP_MAILER_FLAGS [没有]
SMTP mailer附加标志。对所有基于SMTPmailer其默认标志为mDFMUX;基于esmtp的邮差
(mailer)加上'a'标志;而基于"smtp8"的邮差则加上'8'。

SMTP_MAILER_MAX [没有]
使用smtp,smtp8或esmtp传输的单个邮件最大容量。

SMTP_MAILER_CHARSET [没有]
如果定义了此参数,则被转化为MIME格式的从其他地址到任一个smtp mailer的含有8
位字符的信息将被标为此字符集。
POP_MAILER_PATH [/usr/lib/mh/spop]
pop邮差的路径名。
POP_MAILER_FLAGS [Penu]
pop邮差附加标志。同时总是加上标志lsDFM。
POP_MAILER_ARGS [pop $u]
传给pop邮差的参数。

PROCMAIL_MAILER_PATH [/usr/local/bin/procmail]
procmail程序的路径名。此外FEATURE(local procmail)也用到此参数。
PROCMAIL_MAILER_FlAGS [SPhnu9]加给Procmail邮差的标志。同时总是加上"DFM"标志

PROCMAIL_MAILER_MAX [没有]
procmail所接收的最大单个邮件容量。如果你对某些人发送巨大的邮件感到困扰,启
用这个选项。

FEATURE
定义sednamil的一些运行参数,通常对我们来说最重要的一些选项是:
use_cw_file
读取文件/etc/sendmail.cw以确定这台机器应该替哪些机器接受邮件。此主机的别名
。当你使用 MX记录将此主机定义为其他主机的邮件交换机时需要使用这个特性。例如:
FEATURE(use_cw_file)
relay_hosts_only
通常情况下,sendmail为sendmail.cf中明确列出的域(一般是localhost)和/etc/
mail/relay-domains中定义的域进行投递代理。缺省下这两处定义的都是域的名字。如
果你定义了这个参数,那么这两处的内容将被解释为主机名字。
use_ct_file
读取文件/etc/sendmail.ct以取得系统“信任”的用户名字,这些用户可以使用-f设
置其发信信封上的from地址而不产生警告信息。
redirect
使用REDIRECT特性,这个特性允许你对某些已经搬迁的用户发出重定向信息。(见下
一节)。例如:
FEATURE(redirect)
mailertable
包含一个用于覆盖到特定域路由(routing)的"mailer table".此特性参数定义可以是
一个关键词定义。如未指定任何参数, 其定义通常是:
FEATURE(mailertable,`hash -o /etc/mailertable')
domaintable
包含一个用于提供域名映象的"domain table",当改变你自已的域名时可能有用(如
你公司由oldname.com改为newname.com)。其定义通常是:
FEATURE(domiaintable,`hash -o /etc/domaintable')
always_add_domain
在本地发送邮件时也加上其主机域名。例如:
FEATURE(always_add_domain)
allmasquerade
如果使用了伪装(masquerading,使用MASQUERADE_AS),则此特性将使接收者的地址也伪
装为来自所伪装为主机。

limitd_masquerade
通常情况下$w所列出的所有主机将被伪装。如果使用了此特性,则只对那些$m所列出
的主机进行伪装。
masquerade_entire_domain
如使用了伪装且设置了MASQUERADE_DOMAIN,此特性将引起 地址重写,使所要伪装的网
域整个被隐藏。所有含有被伪装域名的主机用伪装域名(通常是MASQUERADE_AS)进行重写

masquerade_envelope
用此特性告知sendmail将信封和信件头中上的发送者和接收者进行伪装。
定义了有关masq的选项之后,就可以使用伪装了,可以直接将伪装命令写入mc模板,
示例如下:
MASQUERADE_AS(masq.com)
MASQUERADE_DOMAIN(foo.org)

这意味着我们的someone@foo.org发信的时候,sendmail将会把它的信封伪装为some
one@masq.com。这对于统一整个域的电子邮件是非常重要的。
virtusertable
允许在同一个主机上使用多个虚拟域。参考下一节。例如:
FEATURE(`virtusertable',`hash –o /etc/mail/virtusertable)
nullclient
这是一个特殊情况--它生成一个除了支持将所有的邮件通过本地的基于SMTP的网络转
递到一个中心邮件HUB之外不含任何内容的配置文件。其参数是此邮件HUB的主机名。唯
一可与nullclient一起使用的其他特性是"nocanonify"(这样可以使非完全地址可通过S
MTP连接进行发送;通常情况下地址将使用伪装名字转变为完全邮件名称,此伪装名字默
认值为邮件HUB主机的名字)。 在此特性使用是不应定义任何邮差。当然也不进行别名
处理或转寄。
local_procmail
使用procmail作为本地邮差。

smrsh
对到程序的邮件使用使用sendmail发行版所带的SendMail Restricted SHell (smrsh
)而不是/bin/sh。由于sendmail是以root权限执行,某个发送到恶意程序的邮件可以破
坏系统,只要利用别名转向使得邮件被转发到对应的程序,因此缺省下sendmail用smrs
h来处理邮件转发到程序的请求。这可以提高本地系统管理员控制对那些通过邮件运行程
序的行为,例如
FEATURE(`smrsh',`/usr/sbin/smrsh')
注意有些程序无法通过smrsh运行(例如majordomo的wrapper程序),这是出于安全
性的考虑,smrsh不准用户程序使用一些setuid功能。如果你一定要使用这些程序,清将
smrsh定义成其他shell程序,如sh。
access_db
本地存取控制文件的名字,缺省是/etc/mail/access.db,也可以用命令行指出,例
如:
FEATURE(`access_db')
或者
或者
FEATURE(`access_db',`hash –o /etc/mail/access')
mailertable
允许使用mailertable文件。这个文件定义对某确定的域使用什么样的邮差。例如:
FEATURE(`mailertable’,`hash –o /etc/mail/mailertable)。
blacklist_recipients
允许你用前面定义的access_db来禁止某个地方来的邮件,或是某个人的邮件,等等

relay_based_on_MX
是否允许别人用你的机器当成MX交换器。如果你设置了这个选项,那么任何人只要在
域名服务器中将你的机器设置成为他的MX交换就可以用你的机器转发电子邮件。这个功
能意味着:你的机器替它接受电子邮件,再提交给它;一般来说这个功能是不必要的;
如果你一定要使用这个选项,记住你可能被庞大的邮件流量吞没。但是在一种情况下这
个功能又是不可缺少的:假如你的系统有防火墙,只有邮件服务器能够对外连接,那么
这个功能是使网络内部其他主机能够接受自己电子邮件的唯一方法。
DOMAIN
这个关键字一般用来定义邮件中继,假如你的系统里面除了Internet互连之外还有类
似Decnet,UUCP之类的东西,那么你就需要设置DOMAIN来保证非internet的邮件被正确
中继。对于一般的系统,不需要定义这个属性。
MAILER
定义可以使用的投递程序(邮差)。
例如:
MAILER(smtp)
定义smtp投递。
MAILER(local)
定义局部投递。
如果你想做邮件服务,这样两个邮差是必须的。
一般情况下,当安装sendmail-cf包的时候,会自动在/usr/sendmail-cf/cf目录下产
生一个模板,名字是redhat.mc。我们可以根据上面的描述对它进行修改以便满足自己的
需要,最后用m4 redhat.mc > sendmail.cf产生配置文件。要注意我们这里只列出了一
些常用的配置命令,许多与时间相关的配置定义我们并没有描述,如confMESSAGE_TIME
OUT等等,这一类的命令通常缺省值已经足够,除非你准备作一个相当庞大的站点,在这
种情况下,你应该去参考/usr/lib/sendmail-cf/README文件得到更多的信息。
在生成了sendmail.cf之后,就可以启动sendmail程序了,我们需要把建立的sendmai
l-cf文件拷贝到/etc下面,然后启动sendmail。
/usr/sbin/sendmail程序支持许多命令参数,对我们来说,最重要的是-bd参数,它表
示将sendmail作为一个守护进程来运行:
sendmail –bd –q1h
-q1h表示每隔一个小时发送一次邮件,类似地,-q15m是15分钟,等等。
7.1.3 sendmail 的相关文件
我们在define和feature相关的子句中讨论了一些sendmail的相关文件,现在我们来解
释这些文件的用法。这些文件的名字通常都可以在对应的mc子句里面更改。
主机别名
首先是/etc/sendmail.cw。这个文件非常简单,它给出本地主机的别名。如果你的主
机有多个名字,或者你的主机是整个域的信件交换主机,你就需要这个文件了。例如,
按照我们在前面的那个配置,mail.asnc.edu.cn是asnc.edu.cn域的信件交换主机,所以
我们需要在sendmail.cw里面写上这样一行:
$ cat /etc/sendmail.cw
# sendmail.cw - include all aliases for your machine here.
asnc.edu.cn
如果你有多个别名或者需要负责的交换域,每个需要单独写上一行。
用户别名
接下来的文件是/etc/mail/aliases,这个文件用来设置用户的别名。最简单的情况是
需要作信件分发的情况。例如,一般情况下,电子邮件出现问题的时候,我们需要把出
错的邮件头发送到本机的postmaster用户,但是也许你的系统上有多个系统管理员,因
此每个人都需要得到一份这个邮件头的拷贝。这种情况下就需要使用用户别名文件了。
aliases文件的格式是邮件别名:实际用户名,如果一个别名有多个用户就用逗号分开
,每个别名一行。例如,要把发给postmaster的信件发送给supervisor和manager,需要
写上这样一行:
postmaster:supervisor,manager
别名还可以用在这样的情况,即定义自动的邮件转发。例如,某个用户以前在你的系
统上接受电子邮件,现在他有了一个新的电子邮件,希望发到你的机器上的邮件自动被
转发到他新的电子邮件地址上,那么,可以使用类似这样的别名方式:(假设你的机器是
joe@yourdomain.com)
joe:joe@newaddr.com
以后发给joe@yourdomain.com的电子邮件就自动中转到joe@newaddr.com。注意左边自
动加上你的机器名字,所以左边只能是账号名字,不能是全限定邮件地址。
别名的右侧也可以是文件或程序。例如,上面的postmaster别名可以用这样方法来设
置:
postmaster::include:/etc/mail/myaliases

:include:关键字表示让sendmail去读取对应的包含文件。而/etc/mail/myaliases的
内容要设置成:
supervisor
manager
就可以了。
要把邮件重定向到程序,可以使用管道,例如:
test_param:"|/home/test/test"
那么,sendmail会将发给test_param的邮件的内容作为/home/test/test程序的输入来
执行这个程序。
在修改了别名文件之后,需要用-bi参数重新初始化别名数据库:
sendmail –bi
另一个常用的办法是重定向。如果你在模板文件中定义了REDIRECT特性,那么可以使
用这个功能。例如,某个人在你的机器上开了一个账户user1,后来迁移到user2@serve
r2.com。那么,你可以将其别名写成
user1: user2@server2.com.REDIRECT
以后当有人向这个地址发信的时候,你的sendmail会将其退回,并且返回一个551 Us
er not local; please try user2@server2.com的信息。
在使用别名的时候,必须注意的是不要造成循环,例如user1转发给user2,user2又将
其转发给user1....如此循环。在这种情况下,转发17次后,sendmail将把它退还给发信
人。最常见的错误发生在你试图在转发邮件的同时在本地保留备份的情况下,例如:
user1: user1,user2
就构成了一个循环。
要在本地保留备份,使用转义符号,例如
user1: user1,user2
建立了别名文件之后,需要将其初始化,这可以通过newaliases命令完成:
[root@mail mail]# newaliases
/etc/aliases: 17 aliases, longest 31 bytes, 241 bytes total
也可以使用sendmail –bi命令:
[root@mail mail]# sendmail -bi
/etc/aliases: 17 aliases, longest 31 bytes, 241 bytes total
两种方式实际是完全一样的。
类似于通过aliases文件进行邮件转发,用户也可以使用自己的转发文件,例如,某个
用户user1想让发送给自己的邮件全部转发到user2@domain.com,但是又不希望建立全局
的用户别名,那么可以在自己的宿主目录下面建立一个.forward文件,内容只要一行:
user2@domain.com
就可以了。
这种技术可以让每个用户自己管理自己的邮件别名。
允许投递
允许投递
如同我们说的那样,smtp协议是不需要身份认证的,也就是说任何人都可能telnet到
你的25端口并且发送莫名其妙的邮件。为了避免不必要的麻烦,比较高版本的sendmail
缺省直接禁止其他不明身份的机器利用你的系统投递邮件。这种情况下,一个非本地的
机器使用你的系统投递会产生一个"550 relay denied"错误。但是如果你要作一个邮件
服务器,你终究得打开投递代理功能。
sendmail的第一个投递代理设置文件是relay-domains。这个文件是一个简单的文本文
件,文件的缺省名字是/etc/mail/relay-domains,可以在confCR_FILE中定义。内容类
似这样:
yourdomain.com
#所有*.yourdomain.com的机器可以使用你的机器作为smtp服务。
192.168
#所有192.168.*.*的机器可以使用你的机器作为服务
/etc/mail/relay-domains文件是一个简单文本文件,当需要投递的域很多的时候,其
效率不是很高。因此,sendmail还可以使用access.db来设定哪些地址的机器可以连接到
你的25端口投递信件。这个文件的缺省名字是/etc/mail/access.db,但是可以用FEATU
RE(access_db)来修改(例如:FEATURE(access_db,`hash –o /etc/access')。
一般/etc/mail/access.db是一个散列表数据库,它是用/etc/mail/access为模版产生
出来的。/etc/mail/access文件的格式是这样:
[地址] [操作]
中间的分割符是空格键。
[地址]栏可以是主机地址或者名字,也可以是统配符,规则是这样:
yourdomain.com 代表所有*.yourdomain.com的名字。
192.168.12 代表所有192.168.12.*的地址。
202.135 代表所有202.135.*.*的地址。
someone@somedomain.com 代表一个特定的邮件发信人
而在每个地址后面可以跟上相应的操作,通常的操作有
OK 正常接受这封邮件
RELAY 允许SMTP代理投递,这样这封邮件就可以从你的机器中转到别的机器上去
REJECT 拒绝接受
DISCARD 忽略这封邮件,这种情况下,邮件看上去是正常投递了,但是由于没有人接
受,邮件会自动地“消失”在网络中。
错误代码+任何其他字符串:将向发信者返回这个字符串作为出错信息。错误代码是R
FC 822定义的标准出错代码。例如
550 We don't like a spammer!
客户机器在投递邮件的时候,就会产生一个“we don't like a spammer”投递失败信
息。比如,你认为someone@spammer是个专门投递垃圾邮件的家伙,那么你可以这样写:
someone@spammer 550 we don't like a spammer
修改了access文件之后,需要重新生成一下access.db,这可以用makemap命令完成:
makemap hash access.db < access

然后重新启动sendmail就可以使用这些功能了。
虚拟域
如同Apache一样,sendmail也允许使用虚拟主机功能,这是通过FEATURE(virtuserta
ble)功能实现的,而虚拟主机的文件缺省是/etc/mail/virtusertable.db,它用/etc/m
ail/virtusertable文件生成,这个文件的形式类似于aliases文件,即左地址 右地址
,中间用Tab键分开。例如:
someone@otherdomain.com localuser
这样一行意味着本来应该发送给someone@otherdomain.com的邮件现在要发送给本机的
用户localuser。当然,这意味着:第一,你的DNS记录中,本机应该是otherdomain.co
m的MX交换器;第二,你的本机sendmail.cw文件应该包含otherdomain.com这个名字。
当然纯粹的这样的域意义不大,但是sendmail还支持邮件虚拟域的参数翻译。例如:
@testdomain.com test@mydomain.com
意味着所有发往xxx@testdomain的邮件都会被发送到test@mydomain.com。而
@testdomain.com %1test@mydomain.com
则代表参数转义,例如user1@testdomain.com的邮件被发送到user1test@mydomain.c
om,user2@testdomain.com被发送到user2test@mydomain.com。同样,这样的功能也要
通过MX记录和CW文件加上去。
建立virtusertable的方法与建立access的办法是一样的:
makemap hash virtusertable.db < virtusertable
然后重新启动sendmail。
定义邮差
/etc/mail/mailertable文件(在FEATURE(`mailertable’)里定义)用来定义对某个
域名或者用户使用什么样的邮差,如local:user,smtp:mail.test1等等。一般情况下,
并不需要定义这个功能。建立这个文件的方式与上面的几个hash数据库相同。
需要注意的是,当前版本的sendmail对各种附加文件和配置文件的属性都有着严格的
要求,特别是/etc/aliases文件,必须至少为0644以避免非授权的修改。
7.1.3 邮件分拣

Linux的sendmail使用procmail作为信件的最终投递代理。这个程序有一些非常有用的
,对于我们来说,最重要的功能是信件的自动过滤和分拣功能。
信件分拣大概是用户最希望的功能,它按照邮件的文件头(发信地址,收信地址等等
)甚至邮件的正文进行归类,并且可以自动存放在各个文件中或者转发给别的用户账号
。马上我们会看到,用procmail配置自动分拣是一件非常容易的事情。
通常的sendmail配置中已经使用了procmail作为邮件最终投递代理,如果你的sendma
il已经改乱了,可以使用FEATURE(local_procmail)设置这个功能。
procmail主要依靠用户宿主目录下面的.procmailrc中的信息来处理邮件.如果这个配
制文件不存在,则procmail只是简单的将邮件保存到用户的信箱中.
一般来说,.procmailrc文件由配置行和行为规则组成。配置行是一些基本参数的设置
,不过一般配置行可以不写;而行为规则通常由(查询)(行为)完成,下面是一个简
单的例子:
:0 H
* ^From:.*test@mydomain.com
{
{
:0 c
! who@somewhere.edu

:0
testsave
}
这个.procmailrc文件将所有来自test的信件转发给who@somewhere.edu,同时在本地
留一个保存一个备份在文件testsave中。
上面的形式是.procmailrc行为规则的基本格式,规则的一般格式是
:0 选项
[零个或多个条件,每个一行]
[动作命令]
[动作命令]
:0表示开始一条规则,后面可以加上一些单字符的选项,选项主要有下面的一些:
H 搜索匹配邮件头部
B 搜索匹配整个邮件
D 匹配时区分大小写
A 如果前面最近的一个没有A或a选项的规则执行,执行本规则
a 如果上面一条规则执行,则本规则执行
E 同A相反,前面最近的没有E或e选项的规则没有执行,则执行本规则
e 同a相反
h 通过管道传送邮件首部(缺省)
b 通过管道传送邮件主体(缺省)
c 复制一个邮件
I 忽略所有写操作中的错误
r 原始模式,即procmail不对mail进行任何模式的处理
条件用一个*号开始,后面跟上正则表达式(参考第十一章)。
动作命令就是procmail在规则成功之后使用的命令,一般的命令有下面一些:
{}
开始一个语句段,表示把一组命令集合成一个动作。如果你要嵌套处理规则,(例如
,对于来自test的邮件,区分是含有computer字符串还是含有physics字符串)那么必须
使用语句段把子规则括起来。
!
转发信件给某个用户
|
启用管道将邮件传送给后面的程序,例如|auto-reply表示启动auto-reply程序并且将
邮件内容作为标准输入传递给它。
任意文件名
将邮件存入某个文件。如果文件已经存在,就添加在文件的末尾。
显然,前面的.procmailrc的含义是:
:0 H开始了一个对邮件头部的搜索,^From.*test@mydomain.com表示邮件头部发现了
From: test@mydomain.com之类的内容,于是行为规则被启动。这里的行为规则是一个语
句块,因此在语句段里面的子规则被执行。
:0 c开始的规则首先复制一份副本,然后将邮件转发给who@somewhere.edu,这样邮件
本身消失了,但是副本仍然存在,于是副本继续执行下面的:0规则组,这个规则是存储
邮件到文件testsave,于是,邮件副本也被处理掉了,正好规则结束。

对于熟悉perl或C语言的的用户,很容易用procmail的管道功能做出邮件的自动回复程
序,这里不再介绍了,想进一步了解procmail的用户可以用
man procmail

man procmailrc
man procmailex
获得更加详细的信息。
7.1.4 Fetchmail
许多用户有多个邮件账户,有些在你的管理范围之内,有些在别的服务器上面。管理
所有这些邮件是非常恶心的事情。另外,也许你的系统仅仅是一个拨号代理(参考第八
章),不可能始终接在internet上面。你需要的是在系统连接到internet的时候发出电
子邮件,同时自动去接收电子邮件。在国内,典型的做法是每人申请一个本地电子邮件
账户和一个免费电子邮件账号,问题就是,如何从另外的ISP提供的电子邮件账号哪里自
动地接收邮件?
当然你可以让你的用户自己解决这个问题,不过这种僵硬的方法不见得合适。一般我
们采用另外的办法,就是fetchmail,它是一个自动的邮件接力程序,可以让它从远程的
pop3账号处取得邮件,然后扔进用户的本地邮箱。(关于pop3的情况参考下一节)
可以直接用命令行调用fetchmail:
$ fetchmail –p [协议] -u [用户名] [服务器]
fetchmail得到的信息将直接投入localhost机器,账号是你启动fetchmail时使用的账
号。
$ fetchmail -p POP3 -u yuanban mail.asnc.edu.cn
Enter password for yuanban@mail.asnc.edu.cn:
使用pop3协议从mail.asnc.edu.cn取得yuanban的信件。fetchmail要求你输入yuanba
n的密码,然后进行验证,成功的话会出现下面的信息:
1 message for yuanban at mail.asnc.edu.cn (551840 octets).
reading message 1 of 1 (551840 octets) ...................................
.....d
表示已经完成了一封信件的转交。
对于更复杂的情况,建议你使用fetchmail的配置文件,即用户宿主目录下面的.fetc
hmailrc。这个文件的详细资料可以参考fetchmail的文档,这里只用一个简单地例子来
介绍它。我们看一个简单的.fetchmailrc范例:

set syslog
set postmaster "isee"
poll 202.96.44.11 with proto POP3 and options
envelope Delivered-To:
user "mere" there with password "xxxxxxx" is isee@snail.home here
no keep
user "isee" there with password "yyyyyyy" is isee@snail.home here
no keep
这个范例相当简单。fetchmail在读取配置文件的时候会忽略所有的"there","here",
"and","with","has","wants","options"之类的单词。
第一行set syslog程序定义fetchmail的记录文件使用系统记录功能。set postmaste
r设置的是出错时的管理员账号,接下来的poll行定义了fetchmail使用的协议为POP3,
连接的服务器是202.96.44.11。
envelope Delivered-To:这个选项比较有趣,它在信封上加上一个Delivered-To说明
,这主要是为了让fetchmail可以把信件投递到一些使用qmail(见下面)的系统中。
接下来是fetchmail的主体部分,一个user的行定义了一个接力方法,现在的定义是取
得202.96.44.11服务器上mere账号的信件,取信的口令是xxxxxxx,然后投递到isee@sn
ail.home,同样,isee的信件也被自动投递到isee@snail.home。no-keep选项表示不在
原始服务器上保留邮件。
下面是配置fetchmail的一些常用选项:
set logfile 制定log文件
set syslog 使用系统log文件
via 指定DNS机器名来取代poll中的机器明
proto 指定协议
port 指定端口
timeout 指定超时时间
interface 指定网络界面
user 指定远程用户
is 将本地用户和远程用户联系起来
to 同is
pass 口令
preconnect 连接开始前执行的外部命令
postconnect 连接结束后执行的外部命令
keep 在服务器上保留邮件备份
no keep 不保留邮件备份
在配置了.fetchmailrc之后,只要直接执行fetchmail就可以实现自动的信件投递了。
实际上,你甚至可能使用fetchmail作为一个daemon程序来实现自动的邮件转交,或是设
置fetchmail让它支持qmail的虚拟域。
在fetchmail的发行版本中还提供了一个图形化的fetchmail配置程序,称为fetchmail
conf。如果你对fetchmail的语法感到困难,只要使用这个程序就可以进行配置。启动这
个程序的方法很简单,直接在xterm下面执行fetchmailconf &:

图7.1 配置fetchmail
选择configure fetchmail出现:

图7.2 配置fetchmail(2)
只要选择Novice Configuration,然后出现服务器设置选单:

图7.3 配置fetchmail(3)
在New Server中加入你准备收信的服务器,然后回车,服务器名字就会出现在列表框
中,双击服务器名字,编辑关于服务器的设置:

图7.4 配置fetchmail(4)
设置服务器的类型和服务器上的账户名字,双击账户名字并且输入对应的密码以及和
本地账户之间的对应关系,OK退出就可以了
7.1.5 测试sendmail
测试sendmail意味着许多东西,一方面是测试地址规则是否正确,另一方面是测试投
递代理是否正确打开。关于规则集我们不想多说,因为除非你已经理解了sendmail.cf,
否则它不会给你什么帮助;对于我们来说,主要是测试投递过程。
可以直接连接到服务器的25端口测试投递代理:
[root@mail mail]# telnet 202.199.248.11 25
Trying 202.199.248.11...
Connected to 202.199.248.11.
Escape character is '^]'.
220 mail.asnc.edu.cn ESMTP Sendmail 8.9.3/8.9.3; Fri, 3 Mar 2000 09:26:47
+0800
mail from:
250 ... Sender ok
rcpt to:
250 ... Recipient ok
data
354 Enter mail, end with "." on a line by itself
test
.

250 JAA08415 Message accepted for delivery
quit
221 mail.asnc.edu.cn closing connection
Connection closed by foreign host.
加粗的是我们输入的内容,上面的操作定义了一个从wanghy@mail.asnc.edu.cn到rus
ter@263.net的邮件发送过程。现在的回应说明邮件投递代理是正常的。如果有任何的错
误,就会在回应中出现。
为了使用这种测试技术,你需要了解SMTP协议的基本命令,这样的命令有14个,在下
面列出:
HELO
标志发起smtp请求的主机,例如,从client1发起smtp会话,可以使用
HELO client1
MAIL FROM:
MAIL FROM:
启动一个邮件会话,在这个行中需要标志发信人的信封地址,例如,要从user1@clie
nt1发出邮件,使用MAIL FROM:,注意尖括号的用法。
RCPT TO:
标志收信人的信封地址,例如,要发送给user2@mail2,使用RCPT TO:
。在一个MAIL FROM之后可以给出多个收信人地址,以便实现多副本的传送。
VRFY
验证某个地址,例如,要确定test@mail是一个可以投递的地址,使用VRFY test@mai
l。
EXPN
显示某个收件人地址或者用户名的实际名字。例如,要显示postmaster用户的实际投
递地址,使用EXPN postmaster。如果在某个用户的目录下有.forward文件,这个文件的
内容将会被自动使用。
DATA

开始写信,在MAIL和RCPT之后可以使用这个命令传输信件正文,传输完毕之后输入一
个.退出。
QUIT
关闭smtp会话
RSET
复位连接状态
HELP
显示这个命令表。
7.2 POP3服务
Sendmail并不处理最终的投递,当然也不会处理如何把邮件提交给最终用户这样的任
务。一般来说,我们总是在Windows客户机器上处理各种电子邮件,因此需要一个服务程
序负责将sendmail存储的邮件转交给Windows或其他任何客户机器。有两种基本的方法,
一种是将邮件传送到客户的本地机器上处理,这是通过所谓的邮局协议实现的;另一种
是允许用户远程操作其邮箱并且实现对邮件的浏览和管理,这是通过所谓的IMAP协议。
7.2.1 POP3服务
POP3即邮局协议3,这是目前邮件客户传输的标准协议之一。几乎所有的邮件客户程序
都会支持这个协议。
Pop3服务程序通常可以从许多程序包中得到。与Linux发行版一起提供的通常是pop和
imap放在一起的服务器程序,例如imap-4.5-4。可以用rpm程序安装这个产品。安装后,
pop3d服务程序放在/usr/sbin下,名字是ipop3d。
ipop3d程序通常是由inetd服务程序启动,不过缺省的情况下这个服务是关闭的。为了
打开这个服务,你必须确认/etc/services文件中有这样的行:
pop-3 110/tcp # POP version 3
pop-3 110/udp
然后在/etc/inetd.conf中加入:
pop-3 stream tcp nowait root /usr/sbin/tcpd ipop3d
重新启动inetd,就可以使用pop服务了。
imap程序包中还包括imap服务器,imap方式用的比较少,但是它也有自己的优点,因
为imap服务是直接操作服务器的文件夹,不需要把文件下载到本地,因此可以避免pop服
务把邮件副本弄的遍地都是。这对于没有自己的确定计算机的用户特别重要。不过,支
持imap的邮件客户程序并不是很多,好在通常使用的outlook 5可以操作imap。
要使用imap服务,在/etc/services里面加上
imap2 143/tcp imap # Interim Mail Access Proto v2
imap2 143/udp imap
然后在/etc/inetd.conf里面加上:
imap stream tcp nowait root /usr/sbin/tcpd imapd
重新启动inetd就可以了。
通常pop的配置对于任何熟悉windows的用户都是很简单的,也许将邮件处理协议设置
成imap对于某些用户可能比较困难,这是你需要给一些帮助。
安装了pop支持之后,可以直接telnet到110端口看pop服务是否正常运行了,例如:
[wanghy@mail /etc]$ telnet 202.199.248.19 110
Trying 202.199.248.19...
Connected to 202.199.248.19.
Escape character is '^]'.
+OK POP3 mail.asnc.edu.cn v7.59 server ready
这样的信息表示pop3服务已经就绪。你可以接着实验看看能否浏览邮箱:
user zhangfl
+OK User name accepted, password please
pass test
+OK Mailbox open, 3 messages
list
list
+OK Mailbox scan listing follows
1 40934
2 29619
3 6001
.
这样的返回信息说明已经一切正常,可以提供服务了。
7.2.2 安全性和其他问题
如同我们解释的那样,smtp发送信件的时候不需要知道用户口令。相反,pop3程序在
允许用户接受邮件之前必须首先确认用户口令。在一般情况下,pop3客户/服务器之间用
明文传送用户名和口令。这是一种不太可靠的方式,因为一个恶意的分析者可能通过以
太网监听你的用户口令。
解决问题的办法之一是使用qpopper程序,它提供了一些高级的选项,特别是支持以加
密方式在客户和服务器之间转发口令字,以及对pop3使用与账号登录不同的认证口令。
你可以自己到网上下载qpopper程序并且编译安装。
另外一个问题是sendmail的虚拟域。虚拟域功能是非常有用的,但是它却有一个很严
重的问题,就是pop3服务程序并不能正确地支持sendmail的虚拟域。通常这种情况意味
着你必须自己编写一个pop3服务程序。不过,实际上,最好的办法是使用某些基于web的
信件浏览程序。
7.3 管理邮件队列
一般当你发送一封邮件的时候,sendmail倾向于立刻发送这一封电子邮件。但是如果
当前网络忙使得无法立刻投递信件,或者是目标地址的连接速度太慢,无法在短时间内
投递到目标地址处,那么sendmail将把待发送的邮件排入队列,并在合适的时候重新发
送。
队列文件通常存放在/var/spool/mqueue下面,每个待发送的邮件由几个文件构成,例
如,我们可以看到下面的目录文件列表:
[root@mail mqueue]# ls
dfRAA27175 xfAAA00733 xfBAA00819 xfEAA32763 xfXAA00706
qfRAA27175 xfAAA00784 xfDAA01360 xfFAA01616
文件名字总是由一个两字符的前缀加上一个随机数字。前缀有四钟:
df:邮件内容
qf:邮件头和一些控制信息
xf:一些临时文件
tf:qf文件的临时存储文件
可以通过看队列中的qf文件来确定当前队列信息,不过通常都可以用mailq程序来完成
对队列状态的查询:
root@mail mqueue]# mailq
Mail Queue (1 request)
--Q-ID-- --Size-- -----Q-Time----- ------------Sender/Recipient-----------
-
RAA27175 22429 Fri Feb 25 17:34
(host map: lookup (21cn.net): deferred)
chaszhj@21cn.net
这表示队列中目前只有一封信,由zhangfl发出,收信人是chaszhj@21cn.net。
由sendmail接受到的信件在用户取走之前将暂时存储在/var/spool/mail目录下面,存
储的方法非常简单,就是每个有待读邮件的用户一个文件:
[root@mail spool]# ls -l /var/spool/mail |more
total 19364
-rw-rw---- 1 anyi mail 7559035 Feb 28 22:04 anyi
-rw-rw---- 1 baixuan mail 514 Nov 7 01:32 baixuan
-rw-rw---- 1 cwc mail 515 Feb 28 08:35 cwc
如果一个用户有多封电子邮件,那么这些邮件就被简单地连接在一起构成一个大文件
(所以你会看到非常巨大的邮件文件)。
要察看邮件系统的状态,使用mailstats命令。
如果你面对的是一个很庞大的邮件服务系统,有时会在某个邮件队列中拥塞太多的消
息,你可能想把这个队列暂停并且在网络空闲的时候再发送,暂停一个邮件队列的办法
非常简单,就是将/var/spool/mqueue目录移走:
killall sendmail
mv /var/spool/mqueue /var/spool/mqueue.stop
mkdir /var/spool/mqueue
sendmail –bd
当网络空闲的时候,可以用-oQ参数立即处理拥塞的队列:
sendmail –oQ/var/spool/mqueue.stop -q

--
当我越过无尽虚空的时候,我看见星辰的欲望,光荣和毁灭,这是光辉世界的宿命,
一切的一切,最终必将落入黑暗和虚无。
所以,我随着星光飞翔,去逃脱必然的终结,也许有一天,我将回到世界的原初,
等待新的星辰的诞生。
尘埃是星的起源,星的终结。

※ 修改:·ruster 於 Dec 21 13:45:26 修改本文·[FROM: 202.112.90.20]
※ 来源:·BBS 水木清华站 smth.org·[FROM: 202.112.90.20] '

  :em08: