修订历史 | ||
---|---|---|
修订 0.2.1 | 2003/03/05 | jiangxin |
sendmail 8.12.7 发现安全漏洞 | ||
修订 0.2 | 2003/2/22 | jiangxin |
补充 procmail | ||
修订 0.1 | 2003/2/11 | jiangxin |
东拼西凑出一个个人 Sendmail 配置心得 |
摘要
工作需要,不得不配置一个自己的 Mail Server。发现 sendmail 并不想以前感觉那样难配置。从网上东拼西凑出一个个人心得,有机会就不断完善。对本文档有任何补充或建议,欢迎联系作者 Johnson。
(编译自版本: 30b6c89,最后更新时间: 2007-07-31)
目录
可以通过命令 telnet <email_server> 25 , 或者命令 sendmail -dt -d0* , 来查看sendmail版本号。如果需要配置 smtp over ssl,则最好使用 8.12版本以上的 sendmail。
由于 Sendmail 有着长期的安全漏洞历史,更需要着重注意 sendmail 的版本更新。
Recent Sendmail Vulnerabilities:
|
Sendmail 作为 Linux, BSD 和其它 Unix 平台的“标配”,被广泛使用。再加上众多的相关软件支持,Sendmail 配置应该算得上是系统管理员的基本技能。Sendmail 主要的配置文件如下:
/etc/sendmail.cf
Sendmail 核心配置文件
/etc/aliases
邮件别名文件
/etc/mail/relay-domains
设定可RELAY的域名
/etc/mail/access
设定处理来信的方式:RELAY等
Sendmail的配置文件 sendmail.cf 算得上“臭名昭著”,看看这个文件一定会让你头大,几乎没有人从头来写这个文件。关于 sendmail.cf 的详细内容,参见:Sendmail Installation and Operation Guide --- THE WHOLE SCOOP ON THE CONFIGURATION FILE。
通过使用 m4 宏处理命令,由宏文件 sendmail.mc 来生成复杂的配置文件 sendmail.cf,一切变得简单多了。
/etc/mail/sendmail.mc 文件即是原始宏文件。生成配置文件 sendmail.cf 的命令为:
$ m4 sendmail.mc > sendmail.cf
默认的配置文件仅仅能在本机发送邮件,如果需要更强的功能,需要修改宏文件:sendmail.mc
缺省的sendmail.mc
文件:
divert(-1) dnl This is the sendmail macro config file. If you make changes to this file, dnl you need the sendmail-cf rpm installed and then have to generate a dnl new /etc/sendmail.cf by running the following command: dnl dnl m4 /etc/mail/sendmail.mc > /etc/sendmail.cf dnl include(`/usr/share/sendmail-cf/m4/cf.m4') VERSIONID(`linux setup for Red Hat Linux')dnl OSTYPE(`linux') dnl Uncomment and edit the following line if your mail needs to be sent out dnl through an external mail server: dnl define(`SMART_HOST',`smtp.your.provider') define(`confDEF_USER_ID',``8:12'')dnl undefine(`UUCP_RELAY')dnl undefine(`BITNET_RELAY')dnl define(`confAUTO_REBUILD')dnl define(`confTO_CONNECT', `1m')dnl define(`confTRY_NULL_MX_LIST',true)dnl define(`confDONT_PROBE_INTERFACES',true)dnl define(`PROCMAIL_MAILER_PATH',`/usr/bin/procmail')dnl define(`ALIAS_FILE', `/etc/aliases')dnl dnl define(`STATUS_FILE', `/etc/mail/statistics')dnl define(`UUCP_MAILER_MAX', `2000000')dnl define(`confUSERDB_SPEC', `/etc/mail/userdb.db')dnl define(`confPRIVACY_FLAGS', `authwarnings,novrfy,noexpn,restrictqrun')dnl define(`confAUTH_OPTIONS', `A')dnl dnl TRUST_AUTH_MECH(`DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl dnl define(`confAUTH_MECHANISMS', `DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl dnl define(`confTO_QUEUEWARN', `4h')dnl dnl define(`confTO_QUEUERETURN', `5d')dnl dnl define(`confQUEUE_LA', `12')dnl dnl define(`confREFUSE_LA', `18')dnl dnl FEATURE(delay_checks)dnl FEATURE(`no_default_msa',`dnl')dnl FEATURE(`smrsh',`/usr/sbin/smrsh')dnl FEATURE(`mailertable',`hash -o /etc/mail/mailertable.db')dnl FEATURE(`virtusertable',`hash -o /etc/mail/virtusertable.db')dnl FEATURE(redirect)dnl FEATURE(always_add_domain)dnl FEATURE(use_cw_file)dnl FEATURE(use_ct_file)dnl dnl The '-t' option will retry delivery if e.g. the user runs over his quota. FEATURE(local_procmail,`',`procmail -t -Y -a $h -d $u')dnl FEATURE(`access_db',`hash -o /etc/mail/access.db')dnl FEATURE(`blacklist_recipients')dnl EXPOSED_USER(`root')dnl dnl This changes sendmail to only listen on the loopback device 127.0.0.1 dnl and not on any other network devices. Comment this out if you want dnl to accept email over the network. DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA') dnl NOTE: binding both IPv4 and IPv6 daemon to the same port requires dnl a kernel patch dnl DAEMON_OPTIONS(`port=smtp,Addr=::1, Name=MTA-v6, Family=inet6') dnl We strongly recommend to comment this one out if you want to protect dnl yourself from spam. However, the laptop and users on computers that do dnl not have 24x7 DNS do need this. FEATURE(`accept_unresolvable_domains')dnl dnl FEATURE(`relay_based_on_MX')dnl MAILER(smtp)dnl MAILER(procmail)dnl Cwlocalhost.localdomain
修改该配置如下:
dnl Dmworldhello.net dnl Dwmail dnl define(`confDOMAIN_NAME', `$w.$m')dnl ... ... FEATURE(`domaintable',`hash -o /etc/mail/domaintable') ... ... FEATURE(`genericstable',`hash -o /etc/mail/genericstable') ... ... GENERICS_DOMAIN_FILE(`/etc/mail/genericsdomain') ... ... dnl DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA') ... ... FEATURE(`accept_unqualified_senders')dnl ... ... define(confMAX_HOP,30) ... ... Cwlocalhost.localdomain your_real_domain ... ...
在默认情况下,也就是安装完系统(Sendmail服务器)不做任何设置的情况下,则只能在本机上收发邮件,网络上(局域网或Internet)的任何其它主机不能向该SMTP服务器发送邮件。这往往并不能满足需要。
对于内部的邮件服务器或者相对简单的网络环境,允许发送邮件的用户的IP地址相对固定或者完全是内部IP地址,则配置非常简单。
允许其他机器使用邮件服务器发送邮件
若希望能实现发送,则需满足下面的任何一个条件即可(不需要同时满足):1. 发送者身份属于“本地或者被允许的发送者”;2. 接收者身份属于“本地或者被允许的接收者”。
/etc/mail/relay-domains
在配置文件/etc/sendmail.cf
中,指定了该文件的路径:
# Hosts for which relaying is permitted ($=R) FR-o /etc/mail/relay-domains
/etc/mail/relay-domains
示例:
localhost.localdomain localhost 127.0.0.1 10.0.0
即在列表中出现的主机,可以使用本邮件服务器发送邮件。
/etc/mail/access
除了使用文件relay-domains
外,还可以使用access
文件确定允许relay的主机,在配置文件/etc/sendmail.cf
中,指定了该文件的路径:
# Access list database (for spam stomping) Kaccess hash -o /etc/mail/access.db
/etc/mail/access
示例:
localhost.localdomain RELAY localhost RELAY 127.0.0.1 RELAY 10.0.0 RELAY
access文件和relay-domains格式的区别在于access文件中,允许relay的主机名添加RELAY关键字。
其它的关键字还有:
OK
当有别的规则阻挡,仍旧允许
RELAY
允许转寄
REJECT
拒绝这个来源的信件
DISCARD
丢弃。这种情况下,邮件看上去是正常投递了,但是由于没有人接 受,邮件会自动地“消失”在网络中。
错误代码+任何其他字符串
将向发信者返回这个字符串作为出错信息。错误代码是R FC 822定义的标准出错代码。如: 550 We don like a spammer!
属于本地/被允许的发送者,则RELAY
如果在relay-domains
或者access
文件中列出的是域名,则对发送者的IP地址先查找/etc/hosts
文件(一般是如此,如果文件/etc/host.conf
采用默认配置的话),如果没有,再查找DNS。查找DNS的过程是:先做IP地址的反向DNS查找,如果能够反向查找出来,且查找出来的主机的域部分属于上面两个文件中列出的域名,再对该主机名做正向DNS查找,若查找出的IP地址(主机的A记录)与发送者IP地址相同,则允许relay邮件,这表明发送者属于被允许的发送者。
如果正反向解析不一致,则会在/var/log/maillog中记录一行警告信息说"may be forged"(可能被伪造的)。如果收信人也不在access文件列表中,则拒发邮件。
本地或者被允许的接收者,则RELAY
相对于发送者,这个就非常简单了。只要接收者的email地址的域部分被列在/etc/mail/relay-domains或者/etc/mail/access 文件中,邮件被允许接收。
对于移动用户的情况,往往网络拓扑复杂,设置/etc/mail/relay-domains
,或者/etc/mail/access
就不够了。
当前的解决办法有:
公司设置自己的拨入服务器,仅仅公司员工可以用自己的用户名和密码拨入后发送邮件.
SMTP-After-POP3方法, 修改POP3程序,拨到ISP后先收一次自己的信,POP3检测到收信者IP地址后再动态地加这个IP地址到relay-domains或者access文件中,允许relay默认半个小时.
sendmail 8.10加入了SMTP用户认证功能,发送邮件时提示输入用户名和密码后允许relay.
显然第三种方法是最理想的。
首先检查是否支持 SASL 认证:
#/usr/sbin/sendmail -d0.1 -bv root |grep SASL
NAMED_BIND NETINET NETINET6 NETUNIX NEWDB NIS QUEUE SASL SCANF
如果出现了 SASL,则sendmail编译时编译了SASL模块,否则需要重新编译 SASL,
设置口令验证,需要修改宏文件 sendmail.mc,如下:
define(QUEUE_DIR,`/var/spool/mqueue/q*') TRUST_AUTH_MECH(`DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl define(`confAUTH_MECHANISMS', `DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl dnl define(`confDEF_AUTH_INFO', `/etc/mail/auth/auth-info') dnl FEATURE(`no_default_msa') dnl DAEMON_OPTIONS(`Port=smtp,Name=MTA')dnl DAEMON_OPTIONS(`Port=25,Name=MSA,M=Ea')dnl
测试:输入如下命令
$ telnet localhost 25 Connected to localhost. Escape character is '^]'. 220 localhost.localdomain ESMTP Sendmail 8.11.6/8.11.6; Wed, 12 Feb 2003 16:38:34 +0800 ehlo localhost 250-xxxxxxxxxxxxxxxxxxxxxxxxx, pleased to meet you 250-ENHANCEDSTATUSCODES 250-8BITMIME 250-SIZE 250-DSN 250-ONEX 250-ETRN 250-XUSR 250-AUTH LOGIN PLAIN 250 HELP auth login
文件:/usr/lib/sasl/Sendmail.conf
pwcheck_method:pam
既然Redhat Linux普遍使用PAM,我们就用PAM 认证。为了支持加密验证,则需要使用SASLDB方式的认证。
文件:/etc/pam.d/smtp
一个重要的邮件重写规则。root 用户可以通过对该文件的配置,建立邮件组、重定向本地用户等等。别名文件会循环检查,直到影射到的邮件地址不在本机接收之列(参见配置文件/etc/mail/local-host-names
)。
示例:
user1: me@otherdomain.com,user2,user3 user2: user2@otherdomain.com alises: :include:/etc/mail/filealiases list-request: |/usr/local/bin/auto_reply nobody: /dev/null
更改别名文件后使用newaliases或sendmail -bi建立邮件别名文件的二进制数据文件。
特殊的别名
owner-aliasname : address
设置该别名后,退信将退回到owner-xxx 别名下。
别名文件一般由root用户管理,而普通用户则可以通过用户主目录下的 .forward 文件,实现邮件别名、转发等一系列处理功能。
当一个别名解析成一个本地用户地址后,sendmail 察看该用户主目录是否存在 .forward 文件,如果存在,读取该文件中的内容,决定进一步的处理方式。
.forward 文件可以通过三种不同的处理方式,对接受的邮件进行处理:定义存储邮件的邮箱文件名(以字符“/”开始的文件名)、进行转发的目的地址、管道(以字符“|”开始,对电子邮件进行处理的外部应用程序)。可以使用第三种方法“管道”,来启动 Procmail。 该文件格式类似 aliases 文件,但是省略了冒号之前的部分,毕竟.forward只针对一个特定的本地用户么。
例如:用户 johnson,需要将其邮件拷贝一份给 jiangxin,再回复给发信人说本人正在度假(通过 vocation 程序实现),但仍然保留给自己一份。如果 .forward 内容如下,则会造成死循环:
jiangxin "|/usr/ucb/vacation johnson" johnson
解决办法是在 johnson 前面加上斜线 \,则再次发送给 johnson 时,则不会再次处理 .forward 文件。修改后如下:
jiangxin,"|/usr/ucb/vacation johnson",\johnson
如同Apache一样,sendmail也允许使用虚拟主机功能,这是通过FEATURE(virtusertable)功能实现的,而虚拟主机的文件缺省是/etc/mail/virtusertable。这个文件的形式类似于aliases文件,即:左地址 右地址 ,中间用Tab键分开。还需要注意的是,虚拟域(左地址的域名),应该属于本机接收之列。
joe@yourdomain.com jschmoe bogus@yourdomain.com error:nouser No such user here @testdomain.com test@mydomain.com @yourdomain.com %1@othercompany.com
aliases 文件同样可以将本地用户,映射到其它地址,那么和 virtusertable 的优先级如何?[1]
当接收者邮件地址的域部分在 /etc/mail/local-host-names 中又在/etc/mail/virtusertable中时,优先检查virtusertable文件,应用该文件中的定义规则.
要应用virtusertable规则,则接收者邮件地址的域部分必须在 /etc/mail/local-host-names 文件中存在
若接收者邮件地址的域部分在 /etc/mail/local-host-names 文件中但不在 virtusertable 文件中有相应的定义则先只应用 aliases 中的定义去扩展别名,一旦扩展出的别名接收者邮件的域部分在 virtusertable 中有定义行时则决不再别名下去,马上运行virtusertable中的定义规则。
优先级:domaintable > virtusertable > local-host-names > mailertable > DNS MX记录
无论什么时候,domaintable都是优先检查,且没有任何附加条件,无条件检查,与/etc/mail/local-host-names中是否有某域名无关。
而 virtusertable 要求域名属于本机接收之列。
一般地用来做域名更换,假如你的公司@abc.com可能被员工误打为abd.com,则放入下面的行到 /etc/mail/domaintable
abd.com abc.com
使用 domaintable ,发件人和收件人的地址全部被替换。
而使用 virtusertable 仅仅将邮件的信封地址替换、信头地址不变,而且也仅仅替换收件人地址。
若文件/etc/mail/genericstable 的内容为:
jwu jwu@sources.com
若文件/etc/mail/genericsdomain的内容为:
test.com
如果该SMTP服务器从互联网上收到一封发送者邮件地址为jwu@test.com的信,则发送者邮件地址被重写为jwu@sources.com,且message envelope中的return address也是jwu@sources.com
跨越DNS的MX的记录,优先于MX记录,可以与MX记录指定的主机设定不同. mailertable的运用不需要接收者邮件地址的域部分在/etc/mail/local-host-names中存在.
sh.abc.com relay:[192.168.11.1] bj.abc.com smtp:mail.bj.abc.com
则发送给jwu@sh.abc.com,发送给192.168.11.1, 并且邮件头显示:“received by shmail[192.168.11.] for jwu@sh.abc.com”
发送给 user@bj.abc.com,通过服务器 mail.bj.abc.com 转发。
我遇到的一个需要地址伪装的例子是,一个应用软件需要频繁在用户之间发送邮件,公司的邮件服务器要求身份认证,而该软件不支持,于是配置了一个内部邮件服务器作为该软件要求的SMTP服务器。但是问题又来了,如果发件人地址属于公司的邮件地址,则邮件回被退回,仍旧报告发件人需要身份验证。于是想到了将发件人地址伪装。
那么何为邮件的地址伪装呢?地址伪装只伪装邮件的发送者部分。凡是转发邮件的发送者地址属于"本地域"(不包含"@域名"只有用户名的地址,或者由 class{w})或者包含在 MASQUERADE_DOMAIN 的定义当中,则将发送者地址伪装为 MASQUERADE_AS 定义的地址。例如:采用如下配置后,user1@domain1.com 发送给 user2@domain1.com 的邮件,被重写为由 user1@domain2.com 发送给 user2@domain1.com;同样根据定义,本地域发出的邮件,也要将发送者的邮件地址写为MASQUERADE_AS 定义的地址,即 @domain2.com。配置如下:
FEATURE(masquerade_envelope) MASQUERADE_DOMAIN(domain1.com) MASQUERADE_AS(domain2.com)
FEATURE(masquerade_envelope) 很重要。如果没有定义该 Feature,则只修改邮件 header 部分的 From 地址,而不修改信封地址,邮件回复仍然回复到伪装前的地址。
常用的几个伪装规则:
MASQUERADE_AS(domain2.com) MASQUERADE_DOMAIN(domain1.com) MASQUERADE_DOMAIN_FILE(`filename') FEATURE(allmasquerade) FEATURE(masquerade_entire_domain) MASQUERADE_EXCEPTION(`host.domain1.com') EXPOSED_USER(`root majordomo') EXPOSED_USER_FILE(`filename') FEATURE(masquerade_envelope)
关于地址伪装的几个重要参考:
sendmail 使用类$w列出主机名。对于DNS中的A记录,必须在$w类中列出,但对于CNAME别名记录,DNS会自动检索出来。
如果DNS中有MX记录,则只需要在sendmail主机名中列出域名即可。
DNS的设置参见:《DNS 配置示例》。
需要安装imap。打开系统的pop3端口。
请查看/usr/sbin/下是否含有ipop2d、ipop3d文件,如没有,请安装imap-4.7c2-12.i386.rpm软件包。支持pop3,pop3 over ssl,imap,imap over ssl等。
如果系统中没有安装 sendmail,或者功能达不到需要而需要升级,就需要重新安装。
sendmail
imap
sasl
首先要下载sasl库,该函数库提供了安全认证所需函数,当前版本是1.5.28。注意2.X 版本无法与sendmail结合,因为API还未做修改。安装过程如下:
$ gzip cyrus-sasl-1.5.27.tar.gz $ tar -xvf cyrus-sasl-1.5.27.tar $ cd cyrus-sasl-1.5.27 $ ./configure -prefix=/usr --disable-krb4 --disable-gssapi --enable-login $ make $ make install
接下来,在编译sendmail之前,需要修改(或添加)配置文件: <sendmail代码树>/devtools/Site/site.config.m4,如下:
dnl APPENDDEF(`confLIBDIRS',`-L/usr/local/lib') dnl PPENDDEF(`confINCDIRS',`-I/usr/local/include') APPENDDEF(`confENVDEF',`-DSASL') APPENDDEF(`conf_sendmail_LIBS',`-lsasl')
修改配置文件: <sendmail代码树>/devtools/Site/site.config.m4,如下:
dnl Stuff for TLS APPENDDEF(`confINCDIRS', `-I/usr/local/include') APPENDDEF(`confLIBDIRS', `-L/usr/local/lib') APPENDDEF(`conf_sendmail_ENVDEF', `-DSTARTTLS') dnl add to previous direction APPENDDEF(`conf_sendmail_LIBS', `-lssl -lcrypto') APPENDDEF(`conf_sendmail_LIBS', `-lsasl -lssl -lcrypto')
修改 sendmail.mc 如下:
TRUST_AUTH_MECH(`LOGIN PLAIN DIGEST-MD5')dnl define(`confAUTH_MECHANISMS', `LOGIN PLAIN DIGEST-MD5')dnl dnl define(`confDEF_AUTH_INFO', `/etc/mail/auth/auth-info') FEATURE(`no_default_msa')dnl DAEMON_OPTIONS(`Port=25, Name=MSA, M=Ea')dnl
修改 sendmail.mc 如下:
dnl define(`CERT_DIR', `MAIL_SETTINGS_DIR`'certs')dnl define(`CERT_DIR', `/etc/mail/certs')dnl define(`confCACERT_PATH', `CERT_DIR')dnl define(`confCACERT', `CERT_DIR/cacert.pem')dnl define(`confSERVER_CERT', `CERT_DIR/cert.pem')dnl define(`confSERVER_KEY', `CERT_DIR/key.pem')dnl define(`confCLIENT_CERT', `CERT_DIR/cert.pem')dnl define(`confCLIENT_KEY', `CERT_DIR/key.pem')dnl
To make certificate authority:
$ mkdir CA $ cd CA $ mkdir certs crl newcerts private $ echo "01" > serial $ cp /dev/null index.txt $ cp /usr/local/openssl/openssl.cnf.sample openssl.cnf $ vi openssl.cnf (set values) $ openssl req -new -x509 -keyout private/cakey.pem -out cacert.pem -days 365 -config openssl.cnf
To make a new certificate:
$ cd CA #(same directory created above) $ openssl req -nodes -new -x509 -keyout newreq.pem -out newreq.pem -days 365 -config openssl.cnf $ $ #cd CA #(same directory created above) $ openssl x509 -x509toreq -in newreq.pem -signkey newreq.pem -out tmp.pem $ openssl ca -config openssl.cnf -policy policy_anything -out newcert.pem -infiles tmp.pem $ rm -f tmp.pem
Edit newreq.pem
Remove the unsigned certificate (leaving the private key)
Copy files
$ cp cacert.pem /etc/mail/certs/cacert.pem $ cp newreq.pem /etc/mail/certs/key.pem $ cp newcert.pem /etc/mail/certs/cert.pem
Set permissions
$ chmod 400 key.pem
Check key properties
$ openssl x509 -noout -in cacert.pem -text
Make sure that the CN of the CA certificate and CN of the server certificate are different, because newer versions of Mozilla and Netscape won't accept the server certificate if it is self-signed.
参见: 前面章节的描述。
-r-xr-sr-x root smmsp ... /PATH/TO/sendmail drwxrwx--- smmsp smmsp ... /var/spool/clientmqueue drwx------ root wheel ... /var/spool/mqueue -r--r--r-- root wheel ... /etc/mail/sendmail.cf -r--r--r-- root wheel ... /etc/mail/submit.cf
.forward 配置文件,可以调用外部程序处理邮件,包括邮件杀毒、自动回复、邮件转发、备份、丢弃等等。
sendmail 如果配置了 smrsh,则对调用外部程序有所限制,需要针对 smrsh 作特殊处理,参见:FAQ
在 .forward 文件中设置使用 vacation 处理邮件:
\ric, "|/usr/bin/vacation -a allman eric"
which would send messages to you (assuming your login name was eric) and reply to any messages for ``eric'' or ``allman''.
Vacation returns a message, ~/.vacation.msg by default, to the sender informing them that you are currently not reading your mail. The message is only sent to each sender once per reply interval (see -r below). The intended use is in a .forward file. For example, your .forward file might have:
~/.vacation.msg 范例
Subject: Re:$SUBJECT From: Song ( 由 vacation 程式自动回信 ) $FROM 您好: 我目前无法看到这封信。 当我回来上班并看过这封信後,我会尽快给您回信。 谢谢。
如果想在回信中使用 Reply-To:,需要用参数 -r 调用 vacation。
vacation 会把回过信的邮件地址存入 .vacation.db 中,同时在 7 天之中不会再自动回覆相同的邮件地址。7 天是系统预设值,如要修改可在启动时使用 -tN 的参数,N 是天数,如:vacation -I -r -t1 song ,这样隔 1 天就会再自动回覆相同的邮件地址了。
vacation 执行时要用到使用者的 shell,如果使用者的 shell 被设成 /dev/null或是 /bin/false 的话,会有错误出现。
procmail就是一个用于过滤用户接收到的电子邮件,并能对其自动分类、处理的一个应用软件。
在 .forward 文件中设置使用 procmail 处理邮件:
"|/usr/bin/procmail"
procmail 的配置文件为:/etc/procmailrc,或者用户主目录下的文件 ~/.procmailrc 由环境变量和过滤规则组成。邮件的投递动作由第一个匹配的过滤规则确定。如果没有匹配任何规则,则执行确省的投递动作。
投递规则的格式如下(man procmailrc):
:0 [flags] [ : [locallockfile] ] <zero or more conditions (one per line)> <exactly one action line>
冒号——`:',开始一条规则。后面的 0,代表下面列出的条件表达式的个数不限制。
可能用到的标志有:
H (确省)
只对信头进行常规表达式匹配。
B
对信体亦作常规表达式匹配。
D
大小写敏感匹配。确省是大小写不敏感。
A, a
只有当前一个不带A或者a的条件表达式匹配,才进行条件判断。
E,e
相当于 Else If。
h(确省)
将信头送入管道、文件、目的地
b(确省)
将信体送入管道、文件、目的地
f
将管道视为过滤器
c
信件拷贝,即使匹配本条规则,仍去匹配其它规则
接下来是条件部分。条件判断以星号开始——`*',后面跟一个常规表达式。可以有零个或多个条件表达式。如果是多个条件表达式,则需要各个条件均匹配,即 and 的关系。如果没有条件表达式,则结果确省为真。
范例(man procmailex):
处理由crontab出发的邮件。对于不关心的邮件予以删除,对于关心的邮件,发送到邮件列表 list-cron。
:0: * ^Subject: Cron .* /bin/sh /www/up.sh /dev/null :0: * ^Subject: Cron .* list-cron
Forward all mail from peter about compilers to william (and keep a copy of it here in petcompil).
:0 * ^From.*peter * ^Subject:.*compilers { :0 c ! william@somewhere.edu :0 petcompil }
等价的表达式
:0 c * ^From.*peter * ^Subject:.*compilers ! william@somewhere.edu :0 A petcompil
等价的,但是速度稍慢的表达式
:0 c * ^From.*peter * ^Subject:.*compilers ! william@somewhere.edu :0 * ^From.*peter * ^Subject:.*compilers petcompil
Forward all mails shorter than 1000 bytes to my home address (no lockfile needed on this recipe).
:0 * < 1000 ! myname@home
Procmail 的FAQ,参见:Timo's procmail tips and recipes
1.11.1. | 安装 majordomo,aliases 文件中有:majordomo: "|/usr/local/majordomo/wrapper majordomo"。majordomo运行时报错:smrsh: "wrapper" not available for sendmail programs (stat failed)。为什么? |
因为Sendmail使用 smrsh (SendMail Restricted SHell)。smrsh程序的目的是作为在mailer中为sendmail定义的"/bin/sh"的替代shell。smrsh是一种受限shell工具,它通过"/etc/smrsh"目录来明确指定可执行文件的列表。简而言之smrsh限制了攻击者可以执行的程序集。当它与sendmail程序一起使用的时候,smrsh有效的将sendmail可以执行的程序的范围限制在smrsh目录之下。 在 sendmail.mc 文件中的配置: FEATURE(`smrsh',`/usr/sbin/smrsh')dnl smrsh 允许执行的程序,需要在 "/usr/adm/sm.bin" 目录中创建符号连接。如果定义了环境变量 SMRSH_CMDDIR,则smrsh允许运行的程序放在该环境变量定义的目录中,否则该目录为:"/usr/adm/sm.bin"。测试 smrsh: $ ln -s /usr/bin/vim /usr/adm/sm.bin/ $ /usr/sbin/smrsh -c /usr/bin/vim |
|
1.11.2. | 尤其是在和其它软件配合使用时,Sendmail经常会因为文件或者目录的权限问题——组写权限,而报错。怎么办? |
如果不想对文件、目录的设置过于苛刻的话,可以考虑使用 DontBlameSendmail 选项。例如: define(`confDONT_BLAME_SENDMAIL', `AssumeSafeChown') define(`confDONT_BLAME_SENDMAIL', `GroupWritableAliasFile') define(`confDONT_BLAME_SENDMAIL', `GroupWritableDirPathSafe') define(`confDONT_BLAME_SENDMAIL', `GroupWritableIncludeFileSafe') define(`confDONT_BLAME_SENDMAIL', `IncludeFileInGroupWritableDirPath') define(`confDONT_BLAME_SENDMAIL', `IncludeFileInUnsafeDirPath') |
|
1.11.3. | 如何让sendmail具有泛email支持?即无需设置本机账号的邮件账户? |
通过设置 LUSER_RELAY,还和 procmail 配合使用。 define(`LUSER_RELAY', `local:root') |
|
1.11.4. | 一个用户离开了公司,但仍然收到许多关于他/她的邮件,我怎么让别人知道此人已经使用新的邮件地址? |
加下面的行到M4宏配置文件中 FEATURE(`redirect')dnl 然后加下面的行到aliases文件中: olduser: him@new.address.REDIRECT 所有发到旧的邮件地址的人将收到一个新邮件地址的通知消息. |
|
1.11.5. | 为什么我更改了上面各种配置文件后仍然不起作用? |
更改配置后,需要进入到/etc/mail 目录下,执行: cd /etc/mail make newaliases /etc/init.d/sendmail restart 或者:在任意配置文件更改后都要运行makemap,例如: # makemap hash virtusertable.db < virtusertable 但是对于local-host-names和relay-domains文件的更改要用下面的命令重启Sendmail #killall -HUP sendmail 对aliases文件的更改要运行 #newaliases |
|
1.11.6. | 怎么检查一封邮件的发封过程? |
在Sendmail邮件服务器上执行下面的命令. # echo testing | /usr/sbin/sendmail -f sender@somedomain.com -v someone@somedomain.com |
|
1.11.7. | 如果用 POP3 命令,直接在服务器上操作邮件? |
telnet 登陆服务器的 110 端口,执行 POP3 命令:
|
|
1.11.8. | 如何用 SMTP 命令,远程登录到服务器上发送邮件? |
telnet 登陆服务器的 25 端口,执行 SMTP 命令:
|
两年前配过。记得有网上有一个不错的文档《Life with qmail》,去 Google 上查一查吧。
邮件如何归档?MHonarc,一个强大的邮件归档工具,将邮件转换为 html,是一个不错的选择。
但是如何将 Outlook 的邮件转换为 MHonarc 能够识别的格式呢?在 SourceForge.net 上有几个开放源码项目:
MHonarc 的配置参见:Maillist Howto。
MUA
邮件阅读或发送程序,如 outlook, 在邮件系统中用户只与 MUA 打交道,MUA将邮件系统的复杂性与用户隔离开。
Mail Router
程序,从用户处接收邮件并决定其目的地址以及如何到达目的地。比如根据接收者的地址不同,电子邮件可能通过TCP/IP网络发送,或者通过UUCP或FAX发送。邮件路由使用接收者地址及其内部的配置信息来选择一个最好的MTA,然后将邮信件转给此MTA。
MTA(Mail Transport agent)
一个专用程序,其作用类似于邮局,用于在两个机器之间发送邮件。通常,一个机器上只有一个MTA。sendmail程序就是一个MTA,此外还有其他MTA,如MMDF,Smail 3.x, qmail以及zmailer等。
MTA能够理解特定网络的EMAIL协议并通过网络传输信件,如UUCP可通过UUCP连接发送信件,但无法处理SMTP信件。
MDA(Mail Delivery Agent:投递代理)
sendmail自己并不完成最终的邮件发送,它要调作其他的程序来完成最后的投递服务。在SVR4系统中一般是/bin/mail.
信封(envelope)和内容(content)
一个email消息由两部分组成:信封(envelope)和内容(content)。
信封告诉SMTP代理(sendmail或者postfix)如何投递消息。
内容又包括信头(Header)和 消息内容。Header 和消息内容之间用一个空行分隔。内容包括能被人们阅读的消息本身和一些标题(header)(比如消息subject),而一些内容中的header可能和envelope中的重复(比如"To"地址),这些重复的header用来显示时候使用,而envelope中的则是用来投递使用。(这也是为什么你会收到"To"地址不是你的垃圾邮件)
Envelope sender (ES), Envelope recipient (ER), Header sender (HS), Header recipient (HR)
Envelope sender (ES) -- The address provided by the MAIL FROM: SMTP command. Mail transport agents send delivery errors to this address, and often check for the existence of the hostname portion of this email address in DNS. For this reason, if you are rewriting/masquerading the HS, it may be a good idea to masquerade the ES.
Envelope recipient (ER) -- The address provided by the RCPT TO: SMTP command. It is the final destination address of the email. This may differ from the HR if the address is rewritten using the user database, aliases database, or virtusertable.
Header sender (HS) -- The From: address in the message header. This address is frequently masqueraded/rewritten from user@host.domain.com to user@domain.com, especially when host.domain.com is not configured to handle mail directly.
Header recipient (HR) -- The To: address in the message header. This is the recipient address specified by the author of the message. It is left intact unless you use the allmasquerade feature or domaintable.
$ telnet smtp.mydomain.com 25 Trying smtp.mydomain.com... Connected to smtp.mydomain.com. Escape character is '^]'. 220 smtp.mydomain.com ESMTP mail from: mailfrom@mydomain.com 250 ok rcpt to: jiangxin 250 ok data 354 go ahead Date: Tue, 1 Mar 2008 16:10:44 +0800 From: Header-From <header-from@mydomain.com> To: Header-to@mydomain.com Subject: smtp test Hi, This mail contains only a test message. Ignore it. Sincerely yours, Johnson .
Copyright © 2006 WorldHello 开放文档之源 计划 |