第十六章 郵件伺服器

郵件伺服器是網際網路上常用的伺服器,我們平常收發電子郵件都必須經過郵件伺服器。通常一般人都是使用 ISP 或免費的電子郵件信箱,由於這種服務的使用者很多,您的電子郵件帳號通常很長,而且不是您所喜歡的名稱。例如 ,如果您的名字是 Alex,您大概很難申請到 alex@yahoo.com 這麼好記的位址,只能申請到類似 alex0706_tw@yahoo.com 這種又臭又長的信箱。如果您想要有比較好的信箱位址,則必須自行架設一台郵件伺服器。

本章將介紹如何使用 FreeBSD 架設郵件伺服器,讀完本章後,您將可以對郵件伺服器的運作更加了解。本章將包含下列主題:

16.1 電子郵件概論

一個電子郵件位址可以分為二個部份,第一個部份是使用者名稱,第二個部份是主機名稱。以 john@yahoo.com 為例,yahoo.com 就是主機名稱,而 john 為使用者名稱。john@yahoo.com 可以念作「John at yahoo.com」,翻成中文就是在 yahoo.com 上的使用者 John。

假設 Alex 使用的信箱是 alex@gmail.com,則當 Alex 要寄信給 john@yahoo.com 時,會經過下列步驟:

  1. 首先 Alex 從個人電腦中寫好一封信,送到他所屬的 gmail.com 的主機中。
  2. gmail.com 會先將信件存在自己的機器上的暫存區。
  3. gmail.com 會檢查信件目的地,並查找 yahoo.com 的 IP 位址。
  4. 接著經由網際網路將信件送到 yahoo.com 的主機。
  5. yahoo.com 的主機收到信後,發現是給自己機器中的使用者,所以將信件存放到使用者的新件匣中。
  6. 當 John 有空時,從家裡打開電腦,並主動去 yahoo.com 檢查是否有新的信件,當發現有新的信,則下載到自己的電腦中。

圖 16-1

如果 alex@gmail.com 要寄信給 john@gmail.com,因為寄信者和收信者使用同一個郵件伺服器,所以在上述步驟二中,gmail.com 的主機發現收信者是自己機器的使用者,則會將該信件存放在使用者的新件匣中。

從寄信到收信的流程中,每一個網路上的元件都扮演著不同的角色,我們分別來談一下每一個角色的功能:

圖 16-2

當我們在寄信時,所使用的是 SMTP (Simple Mail Transfer Protocol) 通訊協定,在一台郵件伺服器上,必須要先安裝郵件服器軟體,以接收 SMTP 協定所寄來的信件。MTA 和 MTA 之間傳送信件時也是使用 SMTP 協定。而收信時,使用的是 POP3 (Post Office Protocol) 或是 IMAP (Internet Message Access Protocol) 協定。

一般常用的 SMTP 軟體為 FreeBSD 內附的 Sendmail、Qmail、或 Postfix。而收信時所使用的 POP3 及 IMAP 軟體 FreeBSD 並未內建 ,因此我們必須自行安裝。然而做為一台 Mail Server,我們要設定的是最少要做到可以正常使用 POP3 及 SMTP 來讓使用者收發信。另外,我們也將介紹使用 Web 介面的郵件收發軟體,Web 介面的郵件收發軟體可以讓使用者不必使用 Outlook 等軟體即可經由任何作業系統的瀏覽器輕鬆收發信件。

傳統上,SMTP 在接受使用者寄信時,並不須經過身份認証,任何人都可以使用你的主機來製造垃圾信。因此 FreeBSD 內建的 Sendmail 是不接受 SMTP 寄信的。而一般的 ISP 業者大多是以控制連線來源的方式,禁止非允許網域的使用者 RELAY。但如果我們以控制連線來源的方式,便無法在其他非允許的IP位址使用SMTP,這對於想要任何地方都可以發信的人十分不分便。因此,本章裡我們將介紹如何讓使用者透過 FreeBSD 使用 SMTP 身份認證的功能來寄信,讓要使用諸如 Outlook 以 SMTP 寄信的使用者必須先通過本機的身份認證。

在開始架設郵件伺服器之前,您必須先設定好 DNS。由於傳送信件時,必須查找目的地主機的 IP。如果您的主機沒有合法的 DNS 設定,信件將無法正確送達。假設您要架設一台處理 twbsd.org 的郵件伺服器,在 DNS 設定方面有二種方式。第一種是直接將您的主機名稱設為 twbsd.org,並設定 DNS 將 twbsd.org 對映到您的主機 IP。第一種方法是使用 DNS 的 MX 設定,將 twbsd.org 的郵件交由另一台主機處理。如果您的 DNS 是交由申請單位代管,則只要到申請單位設定好名稱對映即可。如果您要自行架設 DNS 伺服器,請參考「DNS 伺服器」一章的說明。

另外,您的伺服器 IP 也必須設好反解,IP 名稱必須和您的主機名稱對映,如果反解不正常,有的伺服器可能會拒收您所送出的信件。

16.2 具身份認證的 sendmail

本文參考自中央研究院計算機中心張毓麟先生所發表的「具身分認證的郵件傳送系統」,該文件的網址是 http://beta.wsl.sinica.edu.tw/~ylchang/Email/sendmail-auth。張先生對於在 FreeBSD 系統上建立安全的郵件伺服器有多篇文章,您可以自 http://beta.wsl.sinica.edu.tw/~ylchang/Email/index.html 取得更多內容。

由於本章有許多指令,為了避免打字錯誤造成安裝失敗,筆者將這些安裝過程寫成一個快速安裝的程式,您可以自本書光碟二中取出安裝。安裝方式如下:

# mount /cdrom
# cp -R /cdrom/mailserver /tmp/
# cd /tmp/mailserver
# sh mailserver.sh

接著依照畫面指示即可快速安裝本章具身份認證的 sendmail 了。安裝完成之後,您可以使用下列指令以啟動 sendmail:

# /usr/local/etc/rc.d/saslauthd.sh
# /usr/sbin/sendmail -bd -q30m

如果我們希望在一開機便啟動 Sendmail,請在 /etc/rc.conf 中加入下面這一行:

sendmail_enable="YES"

如果您希望自行一步步操作,請依下列各小節的說明來安裝,但請特別注意一些標點符號的差異,例如 ` (位於鍵盤左上角) 及 ' (位於鍵盤右邊) 等符號。 筆者建議您如果要自行安裝,在輸入設定檔內容時請使用本書光碟片中的範例,以免打字錯誤。

16.2.1 安裝 Cyrus SASL

SASL (Simple Authentication and Security Layer) 可以讓一些通訊協定 (例如 SMTP、IMAP 等) 具有身份認證的功能。Sendmail 自從 8.10 就支援 SASL 的功能。目前 cyrus-sasl 版本是 cyrus-sasl-2.1.22.tar.gz,我們可以 ftp 到各大 FTP 站台的 distfiles 目錄下去取得最新版的 cyrus-sasl 或從本書光碟中 的 mailserver 目錄中取得。取回後以下列指令安裝。

# tar zxf cyrus-sasl-2.1.22.tar.gz
# cd cyrus-sasl-2.1.22
# ./configure --enable-login --enable-plain
# make
# make install
# cd /usr/local/lib
# ln -s libsasl2.so.2.22 libsasl2.so
# cd /usr/lib
# ln -s /usr/local/lib/sasl2 .
# ln -s /usr/local/lib/sasl2 sasl
# ln -s /usr/local/lib/libsasl* .
# echo "pwcheck_method: saslauthd " > /usr/lib/sasl2/Sendmail.conf

接著我們要在一開機時就執行 saslauthd 這支認證用的程式,請新增檔名為 /usr/local/etc/rc.d/saslauthd.sh 的執行檔,內容如下:

#!/bin/sh

case $1 in
"start")
	echo "Starting saslauthd"
	/usr/local/sbin/saslauthd -a pam
	;;
"stop")
	echo "Stoping saslauthd"
	killall saslauthd
	;;
*)
	echo "Usage $0 start|stop"
	;;
esac

然後將該檔案屬性變為可執行,並建立一個 saslauthd 所需使用的工作目錄:

# chmod 755 /usr/local/etc/rc.d/saslauthd.sh
# mkdir -p /var/state/saslauthd

16.2.2 安裝 Sendmail

在安裝 Sendmail 之前,如果系統中正在執行舊版的 Sendmail,請先使用以下指令將它停掉:

# kill -9 `cat /var/run/sendmail.pid|head -1`

接著請到 www.sendmail.org 去下載最新版的 sendmail,您也可以在光碟二的 /ports/mailserver 目錄中找到 Sendmail 8.14.2。Sendmail 自 8.12.0 版起,需要先建立一個使用者smmsp及所屬群組供 Sendmail 使用。而 FreeBSD 自從 4.5-RELEASE 起己經內建了該使用者,如果你使用的是 4.5-RELEASE 以前的版本,請先編輯 /etc/group 加入下面一行:

smmsp:*:25:

再來增加使用者,執行 vipw 並增加下面一行:

smmsp:*:25:25::0:0:Sendmail user:/var/spool/clientmqueue:/sbin/nologin

將抓回來的 sendmail.8.14.2.tar.gz 放到 /tmp 底下,並以下列指令解壓縮:

# tar zxvf sendmail.8.14.2.tar.gz

接著 ee /tmp/sendmail-8.14.2/devtools/Site/site.config.m4 建立檔案並加入下列內容:

PREPENDDEF(`confENVDEF', `-DMAP_REGEX')
PREPENDDEF(`confOPTIMIZE', `-O2')
APPENDDEF(`confENVDEF', `-DTCPWRAPPERS -DSASL=2')
APPENDDEF(`conf_sendmail_LIBS', `-lwrap -lsasl2')
APPENDDEF(`confLIBDIRS', `-L/usr/local/lib')
APPENDDEF(`confINCDIRS', `-I/usr/local/include')
APPENDDEF(`confENVDEF', `-DMILTER')

由於上述檔案內容中,有很多特殊的符號,為了避免打錯字,建議您直接使用本書所附第二片光碟中的 /examples/site.config.m4 。完成後就可以開始安裝 Sendmail 了:

# cd /tmp/sendmail-8.14.2
# sh Build
# sh Build install

為了要讓本地的使用者不必經由身份認證使用 SMTP,還須再做下列設定:

# cd /tmp/sendmail-8.14.2/obj*
# cd mail.local
# make force-install
# chown root /usr/libexec/mail.local
# chmod u+s /usr/libexec/mail.local

接下來編輯 sendmail 設定範本檔案以便產生出具有身分認證功能的 sendmail.cf 設定檔,請以下列指令執行:

# cd /tmp/sendmail-8.14.2/cf/cf
# cp generic-bsd4.4.mc MYCF.mc
# cd ../feature
# cat access_db.m4 >> ../cf/MYCF.mc
# cat delay_checks.m4 >> ../cf/MYCF.mc
# cat virtusertable.m4 >> ../cf/MYCF.mc
# cd ../cf
# cat >> MYCF.mc
TRUST_AUTH_MECH(`LOGIN PLAIN')dnl
define(`confAUTH_MECHANISMS', `LOGIN PLAIN')dnl
^D(同時按Ctrl+D)

上述要增加到 MYCF.mc 的二行字串,您一樣可以在本書所附第二片光碟中的 /examples/ 目錄中找到 MYCF.mc.append 。為了避免打字錯誤,您可以使用下列指令來將上述二行附加在 MYCF.mc 中:

# mount /cdrom
# cat /cdrom/example/MYCF.mc.append >> MYCF.mc

接著我們要建立 sendmail.cf

# sh Build MYCF.cf
# cp MYCF.mc /etc/mail/sendmail.mc
# cp MYCF.cf /etc/mail/sendmail.cf

接下來請編輯 /etc/mail/access 這個檔案,我們可以在 access 指定哪些 IP 或 domain 來源的機器是否可以經由我們的伺服器寄信。如果您希望自己內部網域的機器可以不必使用身份認証,你可以在這個檔案中加入內部網域的 IP。

127.0.0.1	     RELAY
192.168.0.1	RELAY
# 內部網路不需要認証
192.168.0	    RELAY

接著請產生二個 sendmail 所需要的檔案:

# touch /etc/mail/virtusertable
# touch /etc/mail/aliases

然後請新增 /etc/mail/local-host-names 的檔案, 裡面填入 localhost 以及機器的完整名字 (如 mail.abc.com),當收到信的收件者不是給 mail.abc.com 時便會拒絕。接著,再新增一個檔名為 /etc/mail/relay-domains 的檔案填入本地的 domainname,例如 mydomain.com,這樣一來由本地的 domain 發信時便不需再一次做使用者認證。然後將這些檔案做成 sendmail 能接受的 DB 格式:

# cd /etc/mail
# makemap hash access.db < access
# makemap hash virtusertable.db < virtusertable
# newaliases

這樣就完成了。您可以執行 sendmail -d0.1 -bv root | grep SASL 應該會出現 SASL 的字樣,表示己可認証。

最後,我們可以使用下列指令來啟動認證所需的程式及 Sendmail:

# /usr/local/etc/rc.d/saslauthd.sh start
# /usr/sbin/sendmail -bd -q30m

在啟動 Sendmail 之後,如果執行 telnet localhost 25 ,再打ehlo localhost,我們應該看到一堆 250- 開頭的訊息,其中有一行 250-AUTH LOGIN PLAIN 就代表 Sendmail 己經具有身份認證的功能,此時請輸入 quit 結束。萬一沒有出現,請閱讀 /var/log/maillog 裡面的訊息可以知道錯在哪裡。

# telnet localhost 25
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 vmware.alexwang.com ESMTP Sendmail 8.13.5/8.13.5; Sat, 24 Sep 2005 19:16:09 +0800 (CST)
ehlo localhost  <--輸入 ehlo localhost
250-vmware.alexwang.com Hello localhost [127.0.0.1], pleased to meet you
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-EXPN
250-VERB
250-8BITMIME
250-SIZE
250-DSN
250-ETRN
250-AUTH LOGIN PLAIN  <-- 有這一行表示安裝成功了!!
250-DELIVERBY
250 HELP
quit  <-- 輸入 quit 以離開
221 2.0.0 vmware.alexwang.com closing connection
Connection closed by foreign host.

如果我們希望在一開機便啟動 Sendmail,請在 /etc/rc.conf 中加入下面這一行:

sendmail_enable="YES"

16.2.3 Client 端的設定

微軟的 outlook 由 4.0 版開始支援發信時身分認證功能,只要在 outlook 的設定裡面將『外寄郵件伺服器需要查驗身分』的選項打勾就可以了。

第一步驟,選取『工具』功能表的『帳號』選項:

圖 16-3

第二步驟,選取帳號選單中的『內容』按鈕:

圖 16-4

步驟三,將『外寄郵件伺服器需要查驗身分』功能項打勾:

圖 16-5

按確定鈕回到 outlook 中,即可使用身分認證功能發信。

16.3 POP3 及 IMAP 設定

傳統上使用 Outlook 等收信軟體時,我們會使用 POP3 來下載伺服器上的信件。使用者有新的信件時,該信件會存放於 /var/mail/username 中,這個檔案我們稱之為 inbox。當我們使用 POP3 收信軟體下載信件時,在下載完畢後,除非我們有設定在伺服器上保留原本的信件,否則預設會在下載後自動將該信件自伺服器中移除,以節省空間。

然而,如果您平常使用多台電腦,或是想在不同的地方依然可以看到之前的信件,則 POP3 就不太符合需求。除了 POP3 外,還有一個郵件通訊協定名為 IMAP。IMAP 和 POP3 最主要的差異在於 IMAP 一開始只下載信件標題,直到點選該信件後,它才會將信件下載至您所使用的電腦中。而在下載之後,IMAP 並不會將伺服器上的郵件刪除,所有瀏覽過的信件依然保存於 /var/mail/username 中。隨著信件越來越多,inbox 的資料也會越來越大。此時我們可以使用 IMAP 建立新信夾的功能,在使用者家目錄中建立許多新的資料夾,並將 inbox 的信件移至新建立的資料夾中,以減少 inbox 的大小,並加快收信的速度。而且,當我們寄出新信件時,若使用 POP3 協定,則寄件備份只會存放於您寄信時所使用的電腦中,但 IMAP 則會將寄件備份存於於伺服器中。因此,如果您常使用多台不同的電腦收信,使用 IMAP 會蠻方便的,但 IMAP 在使用上速度會比 POP3 慢。

本章中,我們將介紹 dovecot,dovecot 同時支援 POP3 及 IMAP,在功能及效能上都比傳統的 IMAP 收信軟體好。

16.3.1 安裝 dovecot

我們使用下列指令來安裝 dovecot:

# cd /usr/ports/mail/dovecot
# make install clean

接著將出現進階選項的視窗,我們選擇預設值:KQUEUE、SSL、IPV6、POP3、LDA。

安裝完後,我們要開始編輯 dovecot 的設定檔,請先將預設的範例檔複製一份出來:

# cp /usr/local/etc/dovecot-example.conf /usr/local/etc/dovecot.conf

以下是 dovecot.conf 中我們所必須修改的部份:

protocols = imap pop3 imaps pop3s
disable_plaintext_auth=no
ssl_cert_file = /usr/local/etc/apache22/server.crt
ssl_key_file = /usr/local/etc/apache22/server.key

在這裡,我們使用 Apache Server 所做出來的 SSL 憑證檔,如果您沒有 SSL 憑證,請參考「網頁伺服器進階應用」一章中的說明。

接著,請編輯 /etc/rc.conf,加入下列這一行以在開機時啟動 dovecot:

dovecot_enable="YES"

最後,我們就可以使用下列指令啟動 dovecot 了:

# /usr/local/etc/rc.d/dovecot start

現在我們就可以設定使用 Outlook 來收發。如果您想使用加密的 IMAP 或 POP3 連線,您可以在設定完新的郵件帳號後,點選內容,並選取 [進階] 的部份,將 [這個伺服器需要安全連線] 打勾,即可設 IMAP 或 POP3 收信時使用加密的連線。

圖 16-6

16.4 進階郵件伺服器設定

架設郵件伺服器只是伺服器管理的第一步,後續的維護更是重要。好的系統管理者不僅僅是把機器架好,而是要管理好系統安全、解決使用者問題、並盡可能滿足使用者需求。因此,我們接下來必須說明伺服器的進階管理議題,在使用者有問題時,我們才知道要如何處理。

16.4.1 設定郵件別名及自動轉寄

當有同事離職時,我們常會被要求將該同事的信件轉給某人。這種自動轉寄的功能在 Sendmail 中很容易就可以做到,我們只要設定 /etc/aliases 即可。

/etc/aliases 是用以告知 sendmail 要將信轉給哪個使用者或是交由哪個程式處理。aliases 這個檔案是用來設定郵件的別名,也就是可以設定要將某人的信件轉給其他地方(人員或程式),你也可以同時將某人的信轉給很多人。這個檔案的位置是由 sendmail.cf 檔案中的 AliasFile 這個選項所決定的。當 sendmail 收到信時,會一行一行比對,當第一行符合後,就不會再繼續下去,所以應注意優先順序。

我們來看下列幾個設定的範例:

#本檔案的語法開頭的 "#" 代表該行是註解,大小寫都視為一樣。
# 範例一
root: alex

# 範例二
john: alex,john

# 範例三
webmanager: alex,jack,jim@other.hostname.com

# 範例四
nobody: /dev/null

# 範例五
homework: |/usr/local/bin/homework.sh

# 範例六
olduser: :include: /usr/local/olduser_list

當設定了一堆複雜的別名之後,我們要看最後信會寄到哪裡時,可以使用下面指令來看寄給 username 的信最後寄給誰:

# sendmail -bv username

aliases 檔中將很多東西都轉向 root,因此你可以去讀 root 的信箱或是將 root 的信轉給別的地方,下面這一行是將 root 的信都轉給 my@my.domain:

root:	me@my.domain

當郵件無法送出被退回時給使用者時,都是以 MAILER-DEAMON 為帳號寄出。因為使用者可能會回覆那封被退回的信,所以這個別名是必備的。而 postmaster 則負責處理所有關於郵件問題的信件,因此也是必備的,一定要保留下面二行,這是必要的系統基本設定:

MAILER-DAEMON: postmaster
postmaster: root

請注意,修改完 /etc/aliases 後,我們必須使用下列指令來讓所做的修改在 Sendmail 中發生作用:

# newaliases

16.4.2 一舨使用者設定自動轉寄及自動回信

除了管理者可以經由設定 /etc/aliases 來轉信使用者的信件外,一般使用者也可以設定將寄給自己的信轉寄一份給其它人。

一般使用者只要在自己的家目錄中新增一個檔名為 .forward 的檔案,並設定要轉寄的對象即可。以下為 .forward 的設定範例:

\alex
alexwang@yahoo.com

如果我們在使用者 john 的家目錄中新的上述的 .forward 檔,則所有寄給 john 的信都會轉寄給本機的 alex 及 alexwang@yahoo.com。我們必須要注意的是在上述的設定中,使用者 john 並不會收到寄給自己的信。如果自己也要收到信的設,必須在 .forward 檔中加入自己的名字。

另外,如果您要出國旅遊,可能有很長的一段時間無法收信,並希望當有人寄信給您時,系統能自動回信告訴寄件者,則可以使用 .forward 的功能加上 vacation 這個指令來達成。

假設您的使用者名稱是 alex,首先,我們先在 alex 的家目錄下新增檔案 .forward,其內容如下:

\alex
"|/usr/bin/vacation alex"

接著,我們要在家目錄下新增檔案 .vacation.msg 並加入下列內容:

From: "Alex Wang" <alex@alexwang.com>
Subject: I am on vacation now

Hello,

I will not be reading my mail for a while.
Your mail will be read when I return.

Thanks,
Alex

如果有人寄信給 alex 的話,除了 alex 會收到信外,寄件者也會收到一封標題為「I am on vacation now」的信,內容就是 .vacation.msg 中的內容。

vacation 這個指令名字取的很有趣,作者大概認為無法收信就是渡假去了。我們在 .forward 檔中設定了當有信件進來時,就交由 vacation 去處理,而 vacation 會自動將 .vacation.msg 的內容回覆給寄件者,這樣就達到了自動回信的功能了。

小提示

一般使用者可以經由設定 .forward 及 .vacation.msg 來自動回信,但是這種設定方式對於一般使用者而言可能不太方便。我們可以使用下一章要介紹的 Openwebmail 來提供從網頁中設定自動回覆的功能。

16.4.3 限制每封郵件大小上限

不論您的系統硬碟多大、網路多快,在複雜的網路世界中,難保沒有人會惡意寄送大型郵件來灌瀑您的信箱。不論如何,我們還是應該要做好基本的防護。在 Sendmail 的設定檔中,可以讓我們限制接收的郵件大小。

如果您要限制接收信件的大小,可以修改 /etc/mail/sendmail.cf,將下列項目開頭的註解移除:

# maximum message size
O MaxMessageSize=5000000

我們限制最大的信件大小為 5000000 bytes (即 5MB)。修改完後,您必須重新啟動 sendmail 設定才會生效。

# killall sendmail
# /usr/sbin/sendmail -bd -q30m

16.5 郵件問題處理

在管理郵件伺服器時,我們常會遇到使用者報怨信件無法送出、信件收不到、寄信出現錯誤等等。在遇到這類問題時,我們必須具備問題追蹤的能力,以協助使用者解決寄信的問題。

在處理收發信件問題時,您可能必須查詢 DNS 的設定、了解郵件結構。在說明如何處理收發信件問題前,我們先來了解一些基本的郵件管理知識。

16.5.1 郵件結構

Sendmail 會將所有的使用者新收到的信件放在 /var/mail 中,並將使用者剛寄出的信放在 /var/spool/mqueue 中。在 /var/mail 目錄中,每個使用者的新件匣都是一個和使用者名稱一樣的檔案。例如,使用者 alex 的新件匣是 /var/mail/alex、使用者 john 的新件匣是 /var/mail/john。當我們使用 Outlook 或 webmail 收信時,隨然我們看到的是一封封的郵件,但在系統中,這些郵件是以純文字模式全部存放在同一個檔案中。所以,當使用者的信件很多時,該檔案會越來越大,在使用 IMAP 或 webmail 收信時,速度也會變得比較慢。

由於 /var/mail/var/spool/mqueue 中的信件都是以純文字格式存放信件,管理者可以直接使用任何文書編輯軟體打開使用者的信箱。因此,管理者本身的操守很重要,否則所有人的機密都會被看見。

為了了解一封信的結構,我們還是要看一下信件的內容。您可以打開 /var/mail 目錄中自己的信件,或是在 Outlook Express 中對著信按右鍵 -> [內容],再選 [詳細資料] -> [郵件原始檔],即下圖示:

圖 16-7

接下來,我們可以看到一個郵件原始資料如下:

# Return-Path 表示要回信則會回給 edm@ebp.eracom.com.tw
Return-Path: <edm@ebp.eracom.com.tw>

# 這是由 alexwang.com 的 Sendmail 所產生的標頭。表示信件是由 ebp135.eranet.net
# 所寄出,並由 alexwang.com 處理此信件。
Received: from eracom.com.tw (ebp135.eranet.net [203.95.231.171])
	by alexwang.com (8.13.5/8.13.5) with ESMTP id j8QE1IpL059750
	for <alex@alexwang.com>; Mon, 26 Sep 2005 22:01:24 +0800 (CST)

# 這是由 eracom 的郵件軟體所產生的標頭。
Received: from mail pickup service by eracom with Microsoft SMTPSVC;
	 Mon, 26 Sep 2005 22:01:25 +0800

# Thread-index 及 Thread-Topic 是用來在回信時讓客戶端的軟體判斷信件是和哪幾封信
# 同一個主題用的。
thread-index: AcXCg/dY0ifrCKOiTJO8PTlqFlJD/A==
Thread-Topic: =?big5?B?pn6lTrDiVkqvqVPVIp9yp2qq6xV2kT6FJsXqkU6vnr+A=?=
	=?big5?B?v/m5TA==?=

# From 是寄件者的名稱及 Email。
From: =?big5?B?pn6lTrDisrw=?= <edm@ebp.eracom.com.tw>

# 這是收件者的信箱。
To: <alex@alexwang.com>

# CC 是複本收件者。
Cc:

# Subject 是本封信件的主題。 
Subject: =?big5?B?pn6lTrDisrwgLqvmhqVPVIp9yp2qq6xV2kT6FJsXqkU6vnr+A=?=
	=?big5?B?v/m5TA==?=

# Date 是收信的時間。
Date: Mon, 26 Sep 2005 18:20:49 +0800

# Message-ID 是由發信軟體所產的郵件編號。
Message-ID: <9a3d401c5c283$f7587140$abe75fcb@louis1712gid2f>

# 此封郵件所使用的 MIME 版本。
MIME-Version: 1.0

# 郵件內容格式。
Content-Type: multipart/alternative;
	boundary="----=_NextPart_000_9A3D5_01C5C2C7.057BB140"

# 郵件的優先順序。
Priority: normal

# 表示這是 multi-part MIME 格式的郵件。
This is a multi-part message in MIME format.

# 以下為郵件本文
... 略 ...

我們可以從郵件的標頭中看到信件真正的來源。有的郵件來源可能會假造,我們也可以從郵件的標頭中看出來。

16.5.2 限制寄件者來源

郵件信箱用久了,難免會收到垃圾信。如果您常收到垃圾信,或是想要阻擋某一個網域寄來的信件,最簡單的做法是使用 Sendmail 內建的阻擋功能。

我們可以經由設定 /etc/mail/access 來阻擋某個網域的信件。以下是幾個設定的範例:

192.168                RELAY
free.spammail.com      REJECT
cyperspammer.com       550 We don't accept from spammers
somespammer.com        DISCARD
sendmail.org           OK

/etc/mail/access 的格式是先列出網域、網址、或 Email,再加上 DISCARD、REJECT、RELAY、OK、或是一串有錯誤代碼的訊息。如果是 OK,表示可以寄信到這一台機器中,這是預設值,所以我們很少用到 OK 這個關鍵字。而 RELAY 表示可以使用這台機器送信到其它的機器。REJECT 表示不可以使用這台機器的郵件服器。DISCARD 表示將信收下,並直接刪除,寄件者會以為信件正常被送出。550 加上一個字串表示回應此字串給寄件者。

在設定完 /etc/mail/access 後,我們必須執行下列指令,以將該檔案做成 Sendmail 所使用的資料檔:

# makemap hash /etc/mail/access < /etc/mail/access

我們當我們收到垃圾信時,寄件者往往是假造的,但我們還是可以從郵件標頭中看出該信件的真正來源。以下列標頭為例:

Received: from hoho88_nserver.cx (10p2.ppp.odn.ad.jp [219.66.191.46])
by alexwang.com (8.13.1/8.13.1) with SMTP id j8P6ke57004728
for <alex@alexwang.com>; Sun, 25 Sep 2005 14:46:40 +0800 (CST)
Date: Sun, 25 Sep 2005 14:46:40 +0800 (CST)
Delivered-To: <alex@alexwang.com>

Message-ID: 20030120467mail@mail.hi9658754215_starweb88_mainserver.cx
From: mikas_mail_0911@yahoo.co.jp
To: alex@alexwang.com
Subject: =?iso-2022-jp?B?gXWCqJCimGKCyYLIgsGCxIKoguiC3IK3gUk=?=
MIME-Version: 1.0
Content-Type: text/plain;
charset="iso-2022-jp"

我們可以看到雖然寄件者是 mikas_0911@yahoo.co.jp、發信的主機是 hoho88_nserver.cx,但實際上是的來源 IP 是 219.66.191.46,這個 IP 就是我們要阻擋的位址。或者,您可以阻擋整個 ppp.odn.ad.jp 的信件。

16.5.3 處理未寄出之信件

系統中所有未寄出的信件都會放在 /var/spool/mqueue 中,在該目錄中,一封未寄出的信會有二個檔案,這二個檔案包含了原始信件及寄件失敗的原因。我們可以使用下列指令列出所有未寄出的信件。

# mailq
               /var/spool/mqueue (1 request)
-----Q-ID----- --Size-- -----Q-Time----- ------------Sender/Recipient-----------
j8NFunJe071657    15472 Fri Sep 23 23:56 <>
                (Deferred: Connection refused by mail.somewhere.com.)
                                        <www@some.your.com>
               Total requests: 1

我們可以看到有一封信未送出,原因是被 mail.somewhere.com 拒絕了。

一般而言,Sendmail 每隔一段時間 (依啟動 Sendmail 所加的 -q 參數而決定) 會自動重新送出佇列中的信件,最後都無法送出則會通知寄件者。如果您要立即重新送出佇列中的信件,可以使用下列指令:

# sendmail -qf

如果您要刪除某一封在佇列中的信件,請先使用 mailq 查看 Q-ID,再到 /var/spool/mqueue 中刪除 qfXXXX 及 dfXXXX 的檔案,其中 XXXX 是您要刪除的 Q-ID。

16.5.4 收發信件問題處理

電子郵件在現在的企業中使用非常頻繁,很多公司幾乎所有事務都經由電子郵件處理,收發信不正常往往是 MIS 人員的惡夢。很多時候問題可能不是出現在郵件伺服器本身,而是網路設定、DNS 問題、或是對方伺服器的問題。當您遇到收發信件問題時,就必須要從系統記錄、發信軟體中查出蛛絲馬跡。在檢查問題之前,請先確認您的郵件伺服器的 DNS 設定沒問題,而且郵件伺服器 IP 和主機名稱正反解都正確。DNS 設定不正常的伺服器往往是不能收發信件的主因。

發信問題處理

在發信問題方面,如果您使用發信軟體寄不出信件,請先檢查發信軟體所秀出的訊息,再找解決之道。通常發信問題可以分為二類,一種是在使用 Outlook Express 送信時就已經送不出去,另一種是信送出了,但對方沒收到。第一種問題比較好解決,我們只要看 Outlook Express 的錯誤訊息即可看出端倪。以下列訊息為例:

圖 16-8

我們可以看到錯誤訊息中有「Relaying denied. Proper authentication required.」,很明顯的是因為這一台伺服器必須經過身份認證後才可以使用,我們只要在送信設定中使用身份認證即可。在 Outlook Express 的訊息中,也有可能出現類似 DNS 找不到、主機找不到、使用者不存在等問題。我們只要依這些訊息來查看設定、Email 位址,即可找到原因。

第二種問題是信件寄出了,但是對方沒收到。這種情形,我們就必須要多花點心力了。首先,我們先到伺服器上 /var/spool/mqueue 查看信件是否在佇列中。如果在,則查看一下送出去出的原因,並依錯誤訊息解決問題。如果從錯誤訊息中看不出問題,則可以查閱 /var/log/maillog,並找出該信件的寄送訊息:

Sep 23 00:22:42 mail sendmail[22426]: j8MGMKkE022408: 
to=john@myfriend.com, ctladdr=john@myfriend.com (1029/501), 
delay=00:00:22, xdelay=00:00:05, mailer=esmtp, mailer=esmtp,  
relay=alexwang.com, dsn=5.1.2, stat=Host unknown (Name server: 
myfriend.com: host not found)

以上述範例為例,就是因為找不到 myfriend.com 這台主機。這時候,我們可以手動使用 nslookup 查找該主機,並檢查 DNS 的設定是否有問題。如果是 DNS 主機的問題,則可以更換 DNS 伺服器設定。

如果收件者的伺服器有安裝防垃圾信軟體,有的時候我們的伺服器所使用的 IP 可能會因為某些列為垃圾信。在發信後,您可能會收到下列退信:

 ----- The following addresses had permanent fatal errors -----
<jousset@sultant.com>
(reason: 554 EMail from mailserver at 10.22.102.129 is refused. 

See
http://spamblock.outblaze.com/10.22.102.129)

----- Transcript of session follows -----
... while talking to sultant-com.outblaze.com.:
>>> DATA
<<< 554 EMail from mailserver at 10.22.102.129 is refused. See
http://spamblock.outblaze.com/10.22.102.129
554 5.0.0 Service unavailable
<<< 554 Error: no valid recipients

這時候我們就必須依該信件指示,到該黑名單網站中要求對方將我們的 IP 從黑名單中移除。

如果從 /var/log/maillog 中確認信已經從本機寄出而對方還是沒收到,則接下來就要請對方 MIS 人員查看對方伺服器是否有問題了。

總結關於發信問題處理步驟如下:

收信問題處理

在收信問題方面,和發信問題一樣,最關鍵的還是 DNS 設定。我們必須先檢查客戶端所使用的電腦是不是可以正常的找到郵件伺服器。如果找不到,則必須修改 DNS 設定。

接下來,必須確認客戶端的發信軟體有連到伺服器,並可以正常使用 POP3 或 IMAP。如果在連線時出現錯誤,您一樣可以從 /var/log/maillog 中看出問題。以下列連線記錄為例:

Sep 23 02:16:12 mail sm-mta-in[24776]: j8MV5024776: ruleset=check_rcpt,
arg1=<peter.fr@mail1.stofan.dk>, relay=[219.93.1.218], reject=550 5.7.1
<peter.fr@mail1.stofane.dk>... Relaying denied. IP name lookup failed

從記錄中,我們可以看出來是因為反查 mail1.stofane.dk 失敗,所以我們的伺服器拒收此封信件。這就是為什麼郵件伺服器最好還是要設定好 IP 反查的原因。

如果有人抱怨一直沒有收到客戶寄來的信,我們可以從 /var/log/maillog 中找出該寄件者到底有沒有將信件寄到我們的伺服器。如果沒有,則可以請對方檢查郵件信箱是否正確、對方伺服器中是否有其它訊息。