Linux 架设 sendmail MAIL

12/3/2006来源:Qmail人气:7671

一直以来,电子邮件系统就是网路管理中一个大题目,其复杂性不亚於管理一个现行网路,甚至有些公司还专门有人负责邮件系统的管理工作呢。

认识邮件系统

在我们真正动手设定 linux 的email 系统之前,最好先了解一些关於 email 系统的术语和功能。

先让我们认识两个词:MUAMTA ,它们分别是 Mail User Agent 和 Mail Transfer Agent 的意思。MUA 从字面上看似乎好容易给它吓死,但说穿了您可能会笑耶:我们平时用的 Outlook ExPRess、Netscape Mail、或是 Linux 上面的 pine ,它们都是 MUA 。简单说,MUA 是用来给使用者流览邮件和书写邮件的程式。

MTA 呢?我们管它叫邮件伺服器好了,它负责 MUA 的请求,也负责将邮件从一个 MTA 传到另一个 MTA 。通常一个 MTA 都可以支持好几种邮件协定,例如: UUCP、SMTP、POP 等。 UUCP (Unix to Unix Communication Protocol) 现在已经比较少用了,取而代之的是 SMTP (Simple Mail Transfer Protocol) 和 POP (Post Office Protocol) 这两个协定。 SMTP 负责的将邮件从 MUA 上传给 MTA,也是 MTA 和 MTA 之间的邮件传递协定; 而在没有 POP 之前,email 的使用者一般都要用 telnet 或其它远端控制程式连上 MTA 那里,然後在那里阅读邮件,而有了 POP 之後, MTA 可以将使用者的邮件存在一个档案里,然後使用者通过 MUA 连到 MTA ,再将信件下载回本地机器阅读。另外, MUA 和 MTA 都无需是同一个厂家的软体,只要双方都支持 POP 协定就可以了,其灵活性是不言而喻的了。有些程式,如 sendmail ,表面来说,就同时具备 MUA 和 MTA 功能了。

我们用 MUA 撰写邮件之後,是通过 SMTP 协定上传给 MTA 的;而阅读邮件则是通过 POP 从 MTA 那里下载回来。所以,当您设定 MUA 的时候,就要分别指定 SMTP 和 POP 伺服器的位址了,虽然,大多数情况之下都可能会是同一台机器。如果您看一看 Linux 的 /etc/services 这个档案,您会发现如下这几行:

smtp            25/tcp          mail                                           pop-2           109/tcp         postoffice      # POP version 2pop-2           109/udppop-3           110/tcp                         # POP version 3pop-3           110/udp                                                        

它们分别指定了邮件伺服器和外面联系所使用的 Port 。您会看到 POP 也有两个版本:2 和 3 ,分别使用 109 和 110 这两个 port。

或许您已经留意到 IMAP (Internet Message access Protocol) 这个协定吧:

imap2           143/tcp         imap            # Interim Mail Access Proto v2imap2           143/udp         imap                                          

这个 IMAP 是目前新的邮件协定,通过 IMAP, 使用者在 MUA 那端就无需分别指定 SMTP 和 POP 作为上传和下载协定了,而只一个 IMAP 协定就可以,而且 IMAP 还可以让不同的使用者共用一个 MUA,非常方便哦。

现在我们对邮件系统应该有了初步的概念了吧。让我们简单的看一看一封邮件的传递流程:

  1. 使用者 A 使用 MUA 撰写了一封邮件给另一个网路的使用者 B。
  2. 通过 SMTP 上传给 MTA。
  3. 然後 MTA 通过 SMTP 再传给对方网路的 MTA。
  4. 最後使用者 B 通过其自己的 MUA 用 POP 连上 MTA 将邮件下载回来阅读。
为了加深我们对流程的理解,不如让我们用 telnet 连接一下 Linux 机器,来一番完全的手工操作:

先建立连接:
telnet redhat52 25

您会看到这样的回应:

Trying 192.168.0.17...Connected to redhat52.siyongc.domain.Escape character is '^]'.220 redhat52.siyongc.domain ESMTP Sendmail 8.9.3/8.9.3; Sun, 5 Dec 1999 21:59:57 +1100
然後我们得先介绍一下自己的所在地:
HELO redhat52.siyongc.domain
250 redhat52.siyongc.domain Hello IDENT:[email protected] [192.168.0.17], pleased to meet you
正如您看到的回应,MTA 会非常友善的跟您打个招呼。
如果您要寄信的话,先把自己的地址写在信封上(这是按照西方的信封书写习惯啦):
MAIL FROM: [email protected]
250 [email protected] Sender ok
如果您的地址没问题,然後输入收信人地址:
RCPT TO: [email protected]
250 [email protected] Recipient ok
如果收件人的地址没问题的话(嘿!他们的效率还真快哦,不像我们的邮差,要等差不多一个星期才知道收信人地址不对),接著您就可以输入:
DATA
354 Enter mail, end with "." on a line by itself
以下就是写信的内容了:
TO: [email protected]
Subject: Test Only

Hello Kenny,
This is a test only.
.

250 WAA02035 Message accepted for delivery

在开头的两行,我们称之为 Header,我们使用 MUA 写信的时候也是要输入的。然後接一空白行(这行不能省),再写信肉。当您要完成信肉的话,另起一新行,只带一个“.”符号就可以了。 

最後,我们结束 SMTP 连线:
QUIT
221 redhat52.siyongc.domain closing connectionConnection closed by foreign host.


刚才是手工的写一封信,下面,让我们手工地收一封信:

telnet redhat52 110
您会看到这样的回应:
Trying 192.168.0.17...Connected to redhat52.siyongc.domain.Escape character is '^]'.+OK POP3 redhat52.siyongc.domain v7.59 server ready
然後您输入POP 使用者名称:
USER kenny
+OK User name accepted, passWord please
再输入密码:
PASS lw94%26amp;TC0
+OK Mailbox open, 1 messages
然後,您输入:
LIST
+OK Mailbox scan listing follows1 334.
我们这里可以看到使用者目前有一封邮件待取,如果您要看一看邮件内容,请输入:
RETR 1
後面的数字表示邮件的排列号码,如果有您有两封邮件的话,可以输入‘RETR 2’来看第二封。然後您就会看到邮件的内容:
+OK 334 octetsReturn-Path: Received: (from [email protected])        by redhat52.siyongc.domain (8.9.3/8.9.3) id VAA01951;        Sun, 5 Dec 1999 21:44:16 +1100Date: Sun, 5 Dec 1999 21:44:16 +1100From: root Message-Id: <[email protected]>To: [email protected]: test onlyStatus:Hello kenny,This is a test only..
如果您认为邮件1没必要再留在 MTA 上面了,那麽您可以将之删除掉:
DELE 1
+OK Message deleted
如果您完成了所有事情,要离开的话,可以输入:
QUIT
+OK SayonaraConnection closed by foreign host.
嘿!真给它气死啦:居然来了句日本话呢!

如果您不能用 POP 连上您的 Linux 伺服器,可能您还没开放 pop/imap 的daemon (还记得这个东东用来做什麽的?),请修改您的 /etc/inetd.conf ,找到下面几行,将之修改过来:

# Pop and imap mail services et al#pop-2   stream  tcp     nowait  root    /usr/sbin/tcpd ipop2dpop-3   stream  tcp     nowait  root    /usr/sbin/tcpd  ipop3dimap    stream  tcp     nowait  root    /usr/sbin/tcpd  imapd#

然後,您还要让 inetd 重新读取设定哦:

/etc/rc.d/init.d/inet reload

如果状况依然不能连上 POP ,您就要确定 imap 这套软体是否已经安装好,输入:

rpm -qa | grep imap

如果得出来的结果什麽也没有,那赶快先把 imap 装好吧。

rpm -ivh /mnt/cdrom/RedHat/RPMS/imap*

到这里,您就会发现:哦~~~原来 MUA 只不过帮我们输入了那些命令罢了。在这一个过程中,关键的角色是 MTA 如何判断邮件的路由,和如何将邮件传给对方的 MTA。如果您还没忘记我们在设定 DNS 里面关於 MX 记录的设定,或许应该略为知道 MTA 是如何通过 DNS 系统来找到对方网路的 MTA。但要 MTA 判断出究竟将邮件传给哪一个 MTA 却是非常复杂的事情,恐怕已经超出这里要说的范围了。

不过,我非常推荐您看一下 http://turtle.ee.ncku.edu.tw/~tung/mailsys/ 这个网页。相信对理解邮件系统的运作,非常有帮助。

设定sendmail

在 Redhat 6.0 里面,已经自带了一个 MTA,它就是闻名遐迩的 sendmail 系统了。如果说要设定 sendmail ,看一看它的设定档 /etc/sendmail.cf 就像天书一样! 的确不是件容易的事情,如果要想弄懂它,有一本 1021 页的 O'Reilly Sendmail可以看看。

我当然也没这能力教你设定好一个完全的 sendmail 系统,不过,如果您只想 sendmail 帮您寄信的话,无需设定任何档案。但条件是您的 DNS 要设好,而且对方也能反查得到您的 domain ,也就是说,最好您的domain 是一个注册域名。因为当对方的邮件伺服器接到您的邮件请求之後,会看看寄信人地址是否可以回邮,否则会告诉您诸如“Sender domain must resolve”或“cannot route to sender” 这样的信息。

换句话说,如果您的 DNS 没有经过注册,人们又怎样寄信给您呢?有一个简单的办法是在 MAU 下面设定 repply address 到您的 ISP 或其它合法信箱。要完成一个顺利的邮件传递,最好双方都可以知道如何回邮,使用 DNS 是最普遍的做法。当然,您也可以使用 UUCP 或 static mapping 的方法啦,但别忘记设定是双向的。

好了,现在假设您已经成功的注册好 DNS 了,寄信应该没问题了吧?但您有否发现,从您的 Linux 主机几出去的邮件,其回邮地址格式是这样的:[email protected] 呢?如果您按 Repply 回复到这个地址,应该没问题的,但您有试过使用 [email protected] 这样的格式吗?试试就知道了:如果您没做任何设定,这样的地址是寄不到使用者信箱的。

有办法解决吗?当然有啦,而且很简单呢!您只要将 your.domain.name 放进 /etc/sendmail.cw这个档案就可以了,这是用来设定邮件伺服器别名的档案。如果您有多个别名(或曰 domain )要这台主机接收,那麽将它们全部写进这个档案,一个名称占一行。然後,您竟然无需重新启动 sendmail 或任何服务,设定就已经生效了!

呵呵~~~是否很开心呢?不过,您有没有意识到一个问题:您使用的 intertnet 连线是固定的还是间断的呢?如果您使用 modem 拨接的话,当您下线後,如何进行邮件交换呢?在预设情况下,如果 sendmail 收到邮件传递请求之後,会即时进行,如果因为其它原因(包括离线)而不能即时传递的话,会将邮件存列於 /var/spool/mqueue 目录之下,然後每隔 1 小时(视乎设定)尝试重递,如果 4 小时之後还未能送出,会发出一封警告信给寄信者;如果5 天之後还在 queue 里面,那麽这封信就会退回寄信者了。

假如别人也是用 sendmail 来寄信给您的 domain 的话,如果您的伺服器下线了,对方也会将信存在 queue 里面。由此可见,使用 ppp 连线并不是理想的邮件传递方式。如果您不能建立一条固定的 internet 连线,那麽,将 DNS 和 Mail 都交由您的 ISP 保管好了。如果是这样的话,您只要在 /etc/sendmail.cf 这个档案里面,找到这行(大约在 97 行的位置),将之修改为:

DSmailserver.isp.net

(注意句子没有空白键)。这样的话,当您的伺服器在线的时候,那些不能即时传递而存在 queue 的邮件,或那些伺服器本身不知道如何传递的邮件(如那些非本地邮件),就会第一时间传给 ISP 的邮件伺服器,让他们代理您的传递,而您呢?Sit back %26amp; relax!

设定 fetchmail

哈哈,别高兴得太早啦~~~ 收信呢??是哦~~~ 怎麽收?您大可叫您的 ISP 为每一个使用者建立信箱,然後让他们通过 POP 去取信。但这样的话,费用显然会比较高,而且如果以後人员更换的话,还得劳烦上头帮您修改。为何不这样:只需在 ISP 建立一个帐号,然後所有的使用者都可以收信呢?

可以造到吗?

没问题!

不过,除了 sendmail 之外,您还得使用另一个程式,叫做 fetchmail 的东东。不过,条件是 DNS 交由 ISP 管理,或从外面透过 DNS 查询到的 MX 记录指向 ISP 的伺服器;也就是说,他们会帮您代收所有传给您 domain 的邮件;同时 ISP 还必须会将所有传给您 domain 的邮件喂进那个单一信箱去。如果他们不会做,只要他们也使用 sendmail ,您教他们修改一个档案:/etc/mail/virtusertable ,加入:

@your.domain.name [email protected]

跟著执行:

makemap -r hash /etc/mail/virtusertable.db < /etc/mail/virtusertable

这里假设他们在设定 sendmail 的时候已经定义出‘FEATURE(virtusertable)’这个功能。而且,使用的资料库格式为‘hash’,如果他们使用 dbm 格式的话,将 hash 改成 dmb 就可以了。

然後,您自己还要修改/etc/sendmail.cf 这个档案(大约在 91 、136、141 和 1032 行):

......Dj$w.your.domain.name......#CL root#CE rootCM root......DMyour.domain.name......R$*                     $#error [email protected] 5.7.1 $: "550 Relaying denied"......

(在修改 /etc/sendmail.cf 的时候务必注意:句子开头带空白键,或 Tab,或是没有空白,效果都不一样。以上所举的句子都是直接用字母开头的!)

修改好之後,重新启动 sendmail :

/etc/rc.d/init.d/sendmail restart

接著,我们在 root 的家目录 /etc/root 里面,建立这样一个档案:.fetchmailrc (别少了前面的‘.’!) :

set postmaster "postmaster"poll mail.isp.net with proto POP3  localdomains your.domain.name       user "isp_account" there with password "hBg7-rE10" is * here options fetchall

如果您能进入 X Windows,可以执行 fetchmailconf 用 GUI 来设定这个档案。因为在这个档案里面,包含了您的 ISP 帐号和密码,为避免其它使用者看到,请执行:

chmod 0600 .fetchmailrc

这样设定基本已经完成了,以 root 的身份执行fetchmail -d 300,这样每隔 5 分钟,fetchmail 就会帮您从 mail.isp.net 的 isp_account 帐号下载邮件,同时还会分发到各个使用者的本地邮箱中去。但您也可以使用定时器来设定 fetchmail 的执行动作。例如,执行:

crontab -e

然後加入这行:

0,20,40 * * * * /usr/bin/fetchmail -v

这样系统每隔 20 分钟就会帮您执行 fetchmail 了,当然,您的连线也要设定好啦。例如,您可以使用 Diald 来实现自动连线,不过,我这里略过这部份的讨论,因为我还没实际设定过。如果您设定 diald 成功,可否将步骤寄来给我呢?或许有空我测试出来再和大家分享吧。

设定转递 (aliases)

如果您不善忘的话,我们在设定 httpd 、news、fetchmail 等服务的时候,都常会指定一个管理者的信箱名称(也可以是地址),例如:webmastet、postmaster 等等。您或许知道这些使用者其实并没有出现在 /etc/passwd 中,那麽传给他们的邮件又会寄哪里去了呢?这个秘密,就是邮件伺服器的 alias 功能啦,也有人称之为‘mail list’。说穿了其实只是一个档案:/etc/aliases 。如果您用 vi 去开启这个档案,多看两遍您就知道是怎麽回事了。

在 /etc/aliases 这个档案中,您会发现没有“#”注解的每一行,开始都是一个名称,然後跟著一个“:”符号,然後在其右边又有其它的名称。其工作原理是:当 sendmail 收到一个本地邮件的时候,会检查这个 /etc/aliase 档案,如果发现“:”左边的名字跟接收者名称吻合,就会将邮件转递给“:”右边的名称。在右边的名称,可以多过一个;也可以是另一个邮件地址;也可以指向一个档案或程式。当邮件转给右边之後,又重新找一遍这个 /etc/alias 里面的设定,直到再找不到左边名称为止。例如下面这个例子:

MAILER-DAEMON:  postmasterpostmaster:     rootdaemon:         rootroot:          netman, kennykenny: "| sendmail [email protected]"sales: sales-listsales-list: ":include:/etc/sales.list"

这样,凡是传给 MAILER-DAEMON 的就会转给 postmaster ,然後再转给 root,另外 daemon 也会转给 root,而 root 呢,又分别转给 netman 和 kenny,最後 natman 再也找不到名称了,直接送到 netman 的信箱去;而 kenny 呢?则通过 sendmail 转到 [email protected] 那个地址去。另外,我们只需建立一个 /etc/sales.list 这样的档案,在里面写上所有 sales 的名称,可以全部为一行,用‘,’和一个空白键分隔;这样,所有 salse 都会收到寄给 sales 的邮件了。

不过,刚才稍微骗了您一下,sendmail 真正读取的并不是 /etc/aliases 这个档案,而是另一个经过资料库格式过的档案,我们无需知道它叫什麽,只要您满意您的 /etc/aliases 档案之後,马上执行:

newaliases
注意一下有没有错误信息,有则重复修改档案和执行 newaliases ,直到再没错误为止。

进一步修改

到此为止,您的 sendmail 已经足以应付日常需要了,但有时候您还可能进行额外的设定,以符合实际的需求。如果您懂得直接修改 sendmail 的设定档的话,您可以直接修改,例如 /etc/sendmail.* ,而 /etc/mail/* 的档案呢,您会发现它们大多数都是配对的,每个档案都会对著一个 *.db 的档案。您可对那些没有 .db 的档案修改,然後执行:

makemap -r hash /etc/mail/file.db < /etc/mail/file

就可以将之编译成指定的数据库格式了(通常会是 hash 或 dmb 两种),因为 sendmail 只会去读取经过格式化的数据库啦。例如,sendmail 在预设情况下是将 RELAY 功能关闭了,也就是说,除非指定的主机(或 domain),别的邮件伺服器是不能通过您的 sendmail 传递邮件的。如果您要开放 RELAY 给某些主机(或 domain),您可以先修改 /etc/mail/access 这个档案:

debian  RELAYdebian.home RELAYhome  RELAY192.168.1 RELAY

然後执行下列命令就可以了:

makemap -r hash /etc/mail/access.db < /etc/mail/access

但还有一个更简单的方法,就是确定 /etc/sendmail.cf 档案有这样一行(大约在 123 行附近吧):

FR-o /etc/mail/relay-domains 

然後建立起 /etc/mail/relay-domains 这个档案,将所有要 relay 的机器(或 domain ) 写进这个档案,每个名称占一行,这样就可以了。

其实,来来去去这些设定,无非都在 /etc/sendmail.cf 这个档案中,但要修改这个一千多行的档案可不容易哦,搞不好您的 sendmail 就不工作了呢。如果您要手工修改它,一定要备份一个 copy 哦~~~。

那麽,有没有容易些的设定呢?有的,就是使用 M4 啦。不过,我不打算详细教您怎样用 M4 来设定 sendmail.cf ,但您可以从下面的案例中看看如何使用 M4 这个程式。

设Mail Proxy

我们都知道,如果使用邮件伺服器,最好有自注册了的 domain ,否则充其量只能用在内部网路之上。难道这是缩命吗?非也!在下面的案例中,我主要参考 http://www.linuxgazette.com/issue42/stumpel.html 这篇文章,成功让没有注册的 domain 使用者分享一个 ISP 邮件信箱。准确来说,还不是 100% 成功啦。例如,我暂时不能使用同一台主机同时负责 SMTP 和 POP 的服务,同时,还得装一台 Debian 2.1机器(请参考:http://www.linpus.com.tw/manual/debian2.1/index.htm 进行安装),在 Debian 上不能跑 sendmail,而是用 Exim 代替;最缺陷的是,在回邮地址中,必须使用‘ user’的格式,缺一不可。

如果您对这样的一个系统有兴趣,可以继续往下看,也欢迎共同研究研究。

1,首先,修改您的 /etc/sendmail.mc

divert(-1)dnl This is the macro config file used to generate the /etc/sendmail.cfdnl file. If you modify thei file you will have to regenerate thednl /etc/sendmail.cf by running this macro config through the m4dnl preprocessor:dnldnl        m4 /etc/sendmail.mc > /etc/sendmail/cfdnldnl You will need to have the sendmail-cf package installed for this todnl work.include(`/usr/lib/sendmail-cf/m4/cf.m4')define(`confDEF_USER_ID',``8:12'')OSTYPE(`linux')define(`ALIAS_FILE',`/etc/aliases')undefine(`UUCP_RELAY')undefine(`BITNET_RELAY')define(`confAUTO_REBUILD')define(`confTO_CONNECT', `1m')define(`confTRY_NULL_MX_LIST',true)define(`confDONT_PROBE_INTERFACES',true)define(`PROCMAIL_MAILER_PATH',`/usr/bin/procmail')FEATURE(masquerade_envelope)FEATURE(genericstable, `hash -o /etc/mail/genericstable')GENERICS_DOMAIN_FILE(`/etc/mail/genericsdomain')define(`SMART_HOST',`mail.isp.net')FEATURE(`smrsh',`/usr/sbin/smrsh')FEATURE(`virtusertable',`hash -o /etc/mail/virtusertable')FEATURE(redirect)dnl FEATURE(always_add_domain)FEATURE(use_cw_file)FEATURE(local_procmail)MAILER(procmail)MAILER(local)MAILER(smtp)FEATURE(`access_db')FEATURE(`blacklist_recipients')dnl We strongly recommend to comment this one out if you want to protectdnl yourself from spam. However, the laptop and users on computers that dodnl not hav 24x7 DNS do need this.dnl FEATURE(`accept_unresolvable_domains')dnl FEATURE(`relay_based_on_MX')

注意:请将 SMART_HOST 改成您自己的 ISP 邮件主机。

2,然後备份好 /etc/sendmail.cf 再执行 m4:

cp /etc/sendmail.cf /etc/sendmail.cf.orig
m4 /etc/sendmail.mc > /etc/sendmail.cf

3,将您的邮件主机名称和本地 domain 名称 加进 /etc/mail/genericsdomain里面去(一个名称一行)。

4, 设定好使用者的邮件地址转换,请修改/etc/mail/genericstable,其内容类似如下(请参照自己的实际情形修改):

netman        [email protected]         [email protected]         [email protected]

其中:左边为本地使用者,右边为 ISP 的邮件帐号地址。

5,产生genericstable.db,请执行:

makemap -r hash /etc/mail/genericstable.db < /etc/mail/genericstable
/etc/rc.d/init.d/sendmail restart

6,然後转到在 Debian 2.1 机器上面,进入 X Windows 里面执行 fetchmailconf 来设定,或直接修改 .fetchmailrc 档案(在执行下载任务之使用者家目录之下) ,其内容类似如下:

# Configuration created Mon Sep 27 00:37:13 1999 by fetchmailconfset postmaster "postmaster"poll mail.isp.net with proto POP3       user "isp_account" there with password "hBg7-rE10" is netman here options fetchall warnings 3600

(注意,这个档案比前面的例子略有不同。)

7,在 netman (或是在 fetchmailrc 指定的本地接收者) 的家目录里面修改 .forward 档案,让其内容类似如下:

#Exim filterif $header_to: contans netman then deliver netman endifif $header_to: contans kent then deliver kent endifif $header_to: contans usr1 then deliver user1 endif

(注意:如果使用 sendmail 来执行本地邮件的话则会出现错误。)

设定基本如此,您只需在 MUA 那端将 SMTP 指向 Redhat 机器,而将 POP 指向 Debian 机器就可以了,且 ‘Identity’那里一定要输入使用者名称(和本地邮件帐号名称一至) 。通过 Redhat 传出去的信件都会自动将回邮地址改成 user 的地址,所以对方只要按 Repply 就可以了。但是如果对方要新撰写邮件给您的本地用户,必须也要依照上述格式才可。否则所有邮件都只能下载到 fetchmail 指定的使用者那里,而不会再分发出去了。

架设虚拟邮件主机

相信您已经知道如何修改 sendmail.cw 让 sendmail 接收不同 domain 的邮件了。而且,从前面的 virtusertable (也就是“ 设定 fetchmail ”那里)的设定例子来看,也知道如何让 sendmail 将一个地址转寄到另外一个地址去。但无论如何设定,如果目的地的信箱是在本 sendmail 机器上的话,所使用的帐号将会是 Linux 的系统帐号。举个例子说:

我们修改 /etc/sendmail.cw 让 sendmail 可以接收另外两个 domain 的邮件:

##--- 下面是虚拟 domain: ---v1.test.domainv2.test.domain 

负责这两 domain 的邮件主机分别为 mail.v1.test.domain 和 mail.v2.test.domain。这里,我们假设这两台虚拟主机的 IP Alias 和路由都已经设定好了。同时 DNS 那边也已经设定好这两个 domain 了(DNS 的设定方法请参考“ 架设 DNS ”),MX 和 A 记录都指向本主机。

然後,我们建立两个帐号:v1test1 和 v2test2 。当 sendmail 接收到 [email protected][email protected] 这样的邮件时,它可以轻松的将邮件分寄给 v1test1 和 v2test2 这两位使用者。他们只要将 POP server 分别设为 mail.v1.test.domain 或 mail.v2.test.domain ,或干脆用本机的真实名称: redhat52.siyongc.domain ,就可以将信件取回去阅读。Tips: 如果您想让帐号只能上来收 email 的话,可以直接修改 /etc/passwd,将使用者的 GID 设为 45 ,同时将 shell 改为 /bin/false 。假如 GID 45 还没存在於 /etc/group 中的话,可以用这个命令设定: groupadd -g 45 popusers 。

但如果 v1.test.domain 和 v2.test.domain 都想有一个帐号 test 来接收各自的邮件呢?注意:他们可不是相同的人哦,怎麽办呢?

方法之一是用 virtusertable 来做:修改 /etc/mail/virtusertable,让它包括这两行:

[email protected] [email protected] v2test2

然後执行:

makemap -r hash /etc/mail/virtusertable.db < /etc/mail/virtusertable
service sendmail restart

这样的话,v1test1 就可以收到 [email protected] 的邮件了,而 [email protected] 则会转给 v2test2 这位使用者。这时候,v1test1 的 POP server 可以用 mail.v1.test.domain ,而 v2test2 则可以用 mail.v2.test.domain 。但有一个问题是:在 v1 和 v2 这两 domain 下,他们不能共用 test 这个帐号来登录:要麽将 test 给 v1 用,让 v2 继续用 v2test2 ;或者是相反。

假如 v1 和 v2 都坚持要用 test 这个帐号来取信,有办法解决吗?

哈哈,诚如您一直看下来的感觉:凡是网中人在 study-area 提出这样的问题,大多数情形是已经备好答案的了。没错:可以!

做法是:将您的 Redhat 升级到 6.1 或以後的版本,同时确定下面的程式存在:

/usr/lib/linuxconf/lib/vpop3d

再来呢,参考 RUN PC 第 74 期刊 163 页的介绍就可以做到。底下的步骤是网中人参考 RUN PC 的做法,在 Linpus6.4 (Redhat6.2)的实作经验:

  1. 完成并确定 IP Alias、routing、DNS 等相关设定,我建议您为 domain 本身指定一个 A 记录。下面是 v1.test.domain 的正解范例:

    $TTL [email protected] IN SOA linpus64.dmz.domain. root.linpus64.dmz.domain.        ( 00071401 7200 3600 3600000 86400 )@ IN NS [email protected] IN MX 10 [email protected] IN A 203.30.35.132mail    IN A 203.30.35.132        IN MX 5 mail.v1.test.domain.

  2. 将 /etc/sendmail.cf 备份好:
    cp /etc/sendmail.cf /etc/sendmail.cf.bak

  3. 修改 /etc/inetd.conf ,找到 pop-3 那句,将之修改如下:
    pop-3 stream tcp nowait root /usr/sbin/tcpd /usr/lib/linuxconf/lib/vpop3d ipop3d
    (注意:上面为一整句。)

  4. 接著执行:
    service inet restart

  5. 再来执行:
    linuxconf

  6. Config 下选择 Networking Server tasks Mail delivery system (sendmail) Basic Configure virtual email domain。

  7. 按 Tab 键跳到 Add ,在 Virtual domain (fqdn) 後面填上虚拟 邮件的 domain 名称,如: v1.test.domain。

    这里要注意的一个问题是:不建议您同时为 mail.v1.test.domain 和 v1.test.domain 设定虚拟 domain,仅用 domain name 就好了。因为,如果两个都设定起来的话,[email protected][email protected] 将是不同的两个帐号。只要 DNS 的 MX 设定好就行,反而 sendmail.cw 的设定却与此无关。

  8. 按 Tab 键跳到 Accept ,并 Enter。

  9. 按 Tab 键跳到 Quit ,并 Enter。

  10. 当看到“ Generating /etc/sendmail.cf ”警告的时候,按 Tab 键跳到 Yes ,并 Enter。(如果再有警告字眼的话,也是按 Tab 键跳到 Yes),最後 OK。

  11. Config 下选择 Users accounts Special accounts Virtual POP accounts (mail only)。

  12. 选择刚才建立的虚拟邮件主机,并 Enter。

  13. 按 Tab 跳到 Add,在 Login name 输入虚拟帐号名称,如: test 。

  14. 按 Tab 键跳到 Accept ,并 Enter。

  15. 输入第一次密码并 Enter,然後才输入第二次密码。如果您错过了,多按几次 Tab 就是了。

  16. 按 Tab 键跳到 Accept ,并 Enter。然後 OK。

  17. 按 Tab 键跳到 Quit ,并 Enter。连续三次,直至见到 “ Activate the changes ”字句,再直接 Enter。

到这里,可以说已经完成了虚拟邮件主机的设定了。您只要将 client 的 POP server 指向虚拟邮件主机(mail.v1.test.domain)就可以将邮件下载回来。不过有一个地方要注意的是:不建议在 MUA 上使用 IP 来指定虚拟主机的地址,而应该用它的 FQDN 。而且,当虚拟主机架设起来後(使用 vpop3d),原来真实的帐号反而用不了,您必须将真实 domain 虚拟化。其情形就像 Apache 的 Name-based Virtual Host 一样。

到目前为止,我还找不出除了 linuxconf 之外的方法来建立虚拟邮件主机和帐号。只知道系统会去修改 /etc/sendmail.cf、/vhome、/etc/vmail、和 /var/spool/vmail 等地方。假如日後测试出来再和大家分享经验吧。

设定 SMTP 认证

通过 POP 协定连接远端邮件主机的时候,使用者要提供帐号和密码,等通过认证後才能将邮件取回。但是,使用 SMTP 连接远端邮件主机送信的话,却无需使用认证,这完全取决於 sever 那端如何设定其 RELAY。虽然 sendmail 利用 RELAY 的限制来阻止了许多不必要的邮件转递,但是如果您想开放您的 sendmail 给那些从不同 ISP 上网的员工或有关人员的话,这样的限制反而会变得非常的麻烦。您可以参考一篇小州先生的文章,看看如何解决这个问题。

不过,如果您有打算将 sendmail 升级到 8.10 或以後的版本,您可以利用一个叫做“ SMTP 认证”的功能,让那些通过认证的使用者解决 RELAY 的问题,而且还可以为系统提供更好的安全保护和追踪。下面是我根据 http://beta.wsl.sinica.edu.tw/~ylchang/Email/sendmail-auth/index.html 上面的文章而实作出来的。同时还用 poprelayd 这苹 perl script 来架起 POP Before SMTP 这个方案,请参考http://poprelay.sourceforge.net/poprelay.html 一文。

步骤如下:

  1. 假如您已经装有旧版的 cyrus-sasl ,那麽将 /usr/lib/sasl 和 /usr/local/lib/sasl 移除。

  2. cyrus-sasl-1.5.21.tar.gzsendmail-8.10.2.tar.gz 还有 poprelayd 下载至 /usr/src 目录。(或请运用自自己的搜索能力寻找以上档案)

  3. 然後依顺序执行:
    cd /usr/src
    tar zxvf cyrus-sasl-1.5.21.tar.gz
    tar zxvf sendmail-8.10.2.tar.gz
    tar zxvf poprelayd.tgz
    cd poprelayd
    cp poprelayd /usr/local/sbin/
    cd http://www.study-area.org/gb/?http://www.study-area.org/linux/cyrus-sasl-1.5.21
    sh http://www.study-area.org/gb/?http://www.study-area.org/linux/servers/configure --enable-login --enable-plain
    make
    make install
    ln -s /usr/local/lib/sasl /usr/lib
    ln -s /usr/local/lib/libsasl* /usr/lib
    cat > /usr/lib/sasl/Sendmail.conf
    #(注:请留意大小写)
    pwcheck_method: shadow
    (按 Enter 後按 ctrl+D)
    cd http://www.study-area.org/gb/?http://www.study-area.org/linux/sendmail-8.10.2/devtools/Site
    cat > site.config.m4

    PREPENDDEF(`confMAPDEF', `-DMAP_REGEX') dnl #(注:左边的 ` 符号在 1 键左边)
    PREPENDDEF(`confOPTIMIZE', `-O6') dnl #(注:O为大写英文字母 o )
    APPENDDEF(`confENVDEF', `-DTCPWRAPPERS -DSASL')
    APPENDDEF(`conf_sendmail_LIBS', `-lwrap -lsasl')
    APPENDDEF(`confLIBDIRS', `-L/usr/local/lib')
    APPENDDEF(`confINCDIRS', `-I/usr/local/include')
    (按 Enter 後按 ctrl+D)
    cd http://www.study-area.org/gb/?http://www.study-area.org/linux/http://www.study-area.org/gb/?http://www.study-area.org/linux/sendmail
    sh Build
    cd http://www.study-area.org/gb/?http://www.study-area.org/linux/cf/cf
    cp generic-linux.mc sendmail.mc
    cat http://www.study-area.org/gb/?http://www.study-area.org/linux/feature/access_db.m4 >> sendmail.mc
    cat http://www.study-area.org/gb/?http://www.study-area.org/linux/feature/delay_checks.m4 >> sendmail.mc
    cat http://www.study-area.org/gb/?http://www.study-area.org/linux/feature/virtusertable.m4 >> sendmail.mc
    cat >> sendmail.mc

    TRUST_AUTH_MECH(`LOGIN PLAIN')dnl
    define(`confAUTH_MECHANISMS', `LOGIN PLAIN')dnl
    (按 Enter 後按 ctrl+D)

    然後将下面这个内容也加入刚才建立的 sendmail.mc 档内:

    # We probably want the access_db feature enabled.## FEATURE(access_db)dnl# List of IP addresses we allow relaying from.Klocalip hash -a /etc/mail/localipKpopip hash  -a /etc/mail/popipLOCAL_RULESETSSLocal_check_rcpt# Put the address into cannonical form (even if it doesn't resolve to an MX).R$*   $: $>Parse0 $>3 $1R$* < $* > $*  $: $1 < $2 . > $3    Pretend it's canonical.R$* < $* . . > $* $1 < $2 . > $3     Remove extra dots.# Allow relaying if the connected host is a local IP address.R$*   $: < $%26amp;{client_addr} >   Get client IP address.R<>   $#OK     Local is ok.R< $* . $- > $* $(localip $1.$2 $: < $1 > . $2 $) Check last three octets.R$* < MATCH >  $#OKR< $- > $*  $: $(localip $1 $: < > $1 $2 $)  Check first octet.R$* < MATCH >  $#OK# Allow relaying if the connected host has recently POP3 authenticated.R$*   $: < $%26amp;{client_addr} >   Get client IP address.R< $* >   $(popip $1 $)    Check full address.R$* < MATCH >  $#OK# IP address didn't match.

    完成後,继续下面的动作:

    sh Build sendmail.cf
    service sendmail stop
    mv /etc/mail /etc/mail.bak
    mv /etc/sendmail.cf /etc/sendmail.bak
    mkdir /etc/mail
    cp sendmail.cf /etc/mail
    cd http://www.study-area.org/gb/?http://www.study-area.org/linux/http://www.study-area.org/gb/?http://www.study-area.org/linux/sendmail
    sh Build
    sh Build install
    cd ..
    sh Build install
    cd /etc/mail
    mv http://www.study-area.org/gb/?http://www.study-area.org/linux/sendmail.cw http://www.study-area.org/gb/?http://www.study-area.org/linux/servers/local-host-names
    ln -s /etc/mail/local-host-names /etc/sendmail.cw
    cp /etc/mail.bak/access .
    makemap -r hash access.db < access
    makemap -r hash virtusertable.db < virtusertable
    mv http://www.study-area.org/gb/?http://www.study-area.org/linux/aliases* .
    ln -s /etc/mail/aliases* /etc
    newaliases
    echo "192.168" > localip
    makemap hash localip.db < localip
    makemap hash popip < /dev/null

  4. 好了,到这里,可以说已经完成任务了。然後输入:
    sendmail -O Loglevel=20 -bs
    ehlo localhost
    quit

    假如您有看到其中有这样的字眼:250-AUTH LOGIN PLAIN ,那就真的恭喜您了!否则的话,您应该从头 debug 所有的步骤。假如您认为您的 /etc/mail/sendmail.cf (注意路径) 可能有问题,那您可以试试我这边测试用的范例,请 点这里 下载。

    根据网友 阿丁 提供的参考,如果您按以上步骤安装完还不能工作,可以考虑试试下这样的命令:

    chmod 755 -R /etc/mail
    chmod 755 -R /usr/lib/sasl

  5. 当确定 sendmail 那边已经测试成功之後,别忘了将 sendmail 重新启动:
    /usr/local/sbin/poprelayd -d
    echo "/usr/local/sbin/poprelayd -d %26amp;" >> /etc/rc.d/rc.local

    service sendmail start

  6. 再来就是设定您的 MUA,例如:


    Outlook Express: 将“我的伺服器需要查验身份”打勾。


    Nescape Mail: 填上“Outgoing mail server user name:”。

    另外,很感谢 曾文彦 兄 的热心回报,您可以 参考这里 以确定您的 Outlook Express 设定。

    如果您不想设定 MUA,那麽只要您先连线到邮件主机的 POP 服务,退出後就可以用该主机来寄信了,不管您在哪里连上来都行。在 POP 登录後,您有 15 分钟时间将信寄出;而系统则预设则每 5 秒钟检查一次是否有人 POP 上来过,从而为之打开 RELAY 的大门。如果您想修改这些时间间隔,可以编辑 /usr/local/sbin/poprelayd 这个档,分别修改如下两行中的数字则可:

    $timeout_minutes = 15;          # Minutes an entry lasts.$log_wait_interval = 5;         # Number of seconds between checks

我必须在这里指出一点是:我这里用的系统是一个新装的 Linpus6.4 Linux,其实就是 Redhat6.2,而且是从原已运作的 sendmail 升级上来的。如果您在编译的过程中遇到 library 的问题(诸如: xxxxxx undeclared ...),那就需要更多的努力先将套件所需的 library 装好才能继续。同时,编写设定档的时候也要格外小心键盘敲击的准确性,就算由於拼写错误而令设定档有误,安装并不会因此而中断,且较难察觉其中的不实。

假如您将 SMTP AUTH 和前面介绍的“虚拟邮件主机”混合在一起使用,在将来的修改过程中,可能会引至某些问题。而至於所引出的问题,恐怕已经超过这里要说明的了。我建议同时保留 /etc/sendmail.cf 和 /etc/mail/sendmail.cf 两份档案,如果您会得将两者的内容同步就更好不过。

其它

另外,有些公司或许会想到照顾离职的员工的转信要求,但又不想将所有信件都转到其新邮箱去,例如,和原工作相关的客户邮件,那最好是让系统自动回覆一封邮件给发信人,告知员工离职的消息,如果还有其新的信箱地址,也一并告知,然後让发信人自己决定。为此,网中人写了一只 script 来解决这个需求,如果您有兴趣的话,可以 点这里 将script 下载回去,然完成如下的操作:

  1. 执行:
    tar zxvf mailrtn.sh.tgz
    cp mailrtn.sh /etc/smrsh
    mkdir /etc/mail/disable

  2. 然後将离职员工的新邮件地址写好:
    echo "[email protected]" > /etc/mail/disable/user_name

  3. 修改 /etc/mail/aliases,参考如下格式:
    user_name: "|/etc/smrsh/mailrtn.sh user_name"

  4. 更新 aliases 资料库:
    newaliases

这样的所有寄到 user_name 这个账号的邮件,都将产生一封回应给寄信人,告知员工离职的消息,同时把新的邮件地址也告诉对方。不过,要提醒一点的是,虽然我将 script 放在 /etc/smrsh 目录下,但其实我的 sendmail 并没有启用 smrsh 功能。如果您使用 smrsh 的话,那就要先先花时间解决 smrsh 的问题了。

测试

如果您在测试过程中遇到困难,可以先查一查 /var/log/maillog 这个档案,看看 server 传递是否完成(denied 或 accepted),由此判断出问题的原因:

  • 如果您在寄信的时候会遇到 Relay denied 的问题,这可能是您的 MUA 所在的机器(或网域)不在 /etc/mail/access 或 /etc/mail/relay-domains 档案里面。(也可以参考下一提示内容)
  • 如果您碰到“sender domain must exist”或“cannot route to sender” 的问题,那厶要确定在 MUA 所填写的 Repply Address 是一个合法地址,或是能够被对方 route back 得到的。
  • 如果可以寄信却不能收信,那麽检查一下 /etc/inetd.conf 里面的 POP 和 IMAP 是否打开了。还要确定 imap 软体已经装好。
    另据何金营网友提供的讯息,用这个动作或许有助哦:执行netconf → 点server tasks → 点Basic Services → 点servers → 点POP3 → 设Active,然後退出後储存即可。
  • 另外,和 sendmail 最紧密合作的莫过於 DNS 了,您一定要确定您的 DNS 要设定正确(完全正确!)。例如:如果您遇到 MX loop back 的问题,那麽查一下这台主机所有的别名,将它们全部加入到 /etc/sendmail.cw(或/etc/mail/local-host-names) 档案内。
  • 如果您设定好 sendmail.cw(或/etc/mail/local-host-names) 但仍然不能用 domain.name 收信,那麽请检查 DNS 有没有为 domain 指定 MX;同时也可以试试为 domain 自己指定一个 A 记录(但我不鼓励如此),如:
    @ IN MX 10 mail.server.domain.name.
    @ IN A 192.168.0.1
  • 如果您在启动 sendmail 的时候会延迟很久,那麽请确定 /etc/hosts、/etc/HOSTNAME、 和 DNS 关於这台机器的名称设定正确。同时,手工输入
    hostname your.mail.server.name
    也可以(暂时)解决问题。
  • 还有,如果您使用 fetchmail 来下载邮件,要确定 .fetchmailrc 的执行权限,还有双方的使用者(及密码)要指定正确,以及各使用者的信箱要被建立好。
  • 有时候,使用前面教的 telnet 方式连接,也有助於我们发现问题所在。
  • 再有其它问题的话,还是到 BBS 或 NEWS 板问问吧,但问之前先把资料整理出来,越详细越好。
  • 假如您将 sendmail 升级到 8.10 版本以後,要留意一点是:sendmail 的设定档都搬到 /etc/mail 目录下面了,包括 sendmail.cf、aliases 等。而且, sendmail.cw 已经改用 local-host-names 了。
善用 sendmail ,您可以做到许多意想不到的事情哦~~~,您自己慢慢发掘吧!
P.S:原文转自:http://oaunix.hlhs.hlc.edu.tw/bcc/study-area/-http---www.study-area.org-linux-servers-linux_mail.htm