郵件傳輸代理(MTA)基礎
概述
本教程中,你將學習:
控制郵件去向
Linux 系統上的電子郵件是使用 MTA 投遞的。你的 MTA 投遞郵件到你的系統上的其他用戶,並且 MTA 彼此通訊跨越系統投遞到全世界。
Sendmail 是最古老的 Linux MTA。它最初起源於 1979 年用於阿帕網(ARPANET)的 delivermail 程序。如今它有幾個替代品,在本教程中,我也會介紹它們。
前提條件
為完成本系列教程的大部分內容,你需要具備 Linux 的基礎知識,你需要擁有一個 Linux 系統來實踐本教程中的命令。你應該熟悉 GNU 以及 UNIX 命令。有時候不同版本的程序的輸出格式可能不同,因此,在你的系統中輸出的結果可能與我在下面列出的稍有不同。
在本教程中,我使用的是 Ubuntu 14.04 LTS 和 sendmail 8.14.4 來做的演示。
郵件傳輸
郵件傳輸代理(比如 sendmail)在用戶之間和系統之間投遞郵件。大量的網際網路郵件使用簡單郵件傳輸協議(SMTP),但是本地郵件可能是通過文件或者套接字等其它可能的方式來傳輸的。郵件是一種存儲和轉發的操作,因此,在用戶接收郵件或者接收系統和通訊聯繫可用之前,郵件一直是存儲在某種文件或者資料庫中。配置和確保 MTA 的安全是非常複雜的任務,它們中的大部分內容都已經超出了本教程的範圍。
mail 命令
如果你使用 SMTP 協議傳輸電子郵件,你或許知道你可以使用許多郵件客戶端,包括 mail
、mutt
、alpine
、notmuch
、以及其它基於主機控制台或者圖形界面的郵件客戶端。mail
命令是最老的、可用於腳本中的、發送和接收以及管理收到的郵件的備用命令。
你可以使用 mail
命令互動式的向列表中的收件人發送信息,或者不使用參數去查看你收到的郵件。清單 1 展示了如何在你的系統上去發送信息到用戶 steve 和 pat,同時抄送拷貝給用戶 bob。當提示 Cc:
和 subject:
時,輸入相應的抄送用戶以及郵件主題,接著輸入郵件正文,輸入完成後按下 Ctrl+D
(按下 Ctrl
鍵並保持再按下 D
之後全部鬆開)。
ian@attic4-u14:~$ mail steve,pat
Cc: bob
Subject: Test message 1
This is a test message
Ian
清單 1. 使用 mail
互動式發送郵件
如果一切順利,你的郵件已經發出。如果在這裡發生錯誤,你將看到錯誤信息。例如,如果你在接收者列表中輸入一個無效的用戶名,郵件將無法發送。注意在本示例中,所有的用戶都在本地系統上存在,因此他們都是有效用戶。
你也可以使用命令行以非互動式發送郵件。清單 2 展示了如何給用戶 steve 和 pat 發送一封郵件。這種方式可以用在腳本中。在不同的軟體包中 mail
命令的版本不同。對於抄送(Cc:
)有些支持一個 -c
選項,但是我使用的這個版本不支持這個選項,因此,我僅將郵件發送到收件人。
ian@attic4-u14:~$ mail -t steve,pat -s "Test message 2" <<< "Another test.nnIan"
清單 2. 使用 mail
命令非互動式發送郵件
如果你使用沒有選項的 mail
命令,你將看到一個如清單 3 中所展示的那樣一個收到信息的列表。你將看到用戶 steve 有我上面發送的兩個信息,再加上我以前發送的一個信息和後來用戶 bob 發送的信息。所有的郵件都用 'N' 標記為新郵件。
steve@attic4-u14:~$ mail
"/var/mail/steve": 4 messages 4 new
>N 1 Ian Shields Tue Dec 12 21:03 16/704 test message
N 2 Ian Shields Tue Dec 12 21:04 18/701 Test message 1
N 3 Ian Shields Tue Dec 12 21:23 15/661 Test message 2
N 4 Bob C Tue Dec 12 21:45 17/653 How about lunch tomorrow?
?
清單 3. 使用 mail
查看收到的郵件
當前選中的信息使用一個 >
來標識,它是清單 3 中的第一封郵件。如果你按下回車鍵(Enter
),將顯示下一封未讀郵件的第一頁。按下空格楗將顯示這個郵件的下一頁。當你讀完這個郵件並想返回到 ?
提示符時,按下回車鍵再次查看下一封郵件,依次類推。在 ?
提示符下,你可以輸入 h
再次去查看郵件頭。你看過的郵件前面將顯示一個 R
狀態,如清單 4 所示。
? h
R 1 Ian Shields Tue Dec 12 21:03 16/704 test message
R 2 Ian Shields Tue Dec 12 21:04 18/701 Test message 1
>R 3 Ian Shields Tue Dec 12 21:23 15/661 Test message 2
N 4 Bob C Tue Dec 12 21:45 17/653 How about lunch tomorrow?
?
清單 4. 使用 h
去顯示郵件頭
在這個圖中,Steve 已經讀了三個郵件,但是沒有讀來自 bob 的郵件。你可以通過數字來選擇單個的信息,你也可以通過輸入 d
刪除你不想要的信息,或者輸入 3d
去刪除第三個信息。如果你輸入 q
你將退出 mail
命令。已讀的信息將被轉移到你的家目錄下的 mbox
文件中,而未讀的信息仍然保留在你的收件箱中,默認在 /var/mail/$(id -un)
。如清單 5 所示。
? h
R 1 Ian Shields Tue Dec 12 21:03 16/704 test message
R 2 Ian Shields Tue Dec 12 21:04 18/701 Test message 1
>R 3 Ian Shields Tue Dec 12 21:23 15/661 Test message 2
N 4 Bob C Tue Dec 12 21:45 17/653 How about lunch tomorrow?
? q
Saved 3 messages in /home/steve/mbox
Held 1 message in /var/mail/steve
You have mail in /var/mail/steve
清單 5. 使用 q
退出 mail
如果你輸入 x
而不是使用 q
去退出,你的郵箱在退出後將不保留你做的改變。因為這在 /var
文件系統中,你的系統管理員可能僅允許郵件在一個有限的時間範圍內保留。要重新讀取或者以其它方式再次處理保存在你的本地郵箱中的郵件,你可以使用 -f
選項去指定想要去讀的文件。比如,mail -f mbox
。
郵件別名
在前面的節中,看了如何在系統上給許多用戶發送郵件。你可以使用一個全限定名字(比如 ian@myexampledomain.com)給其它系統上的用戶發送郵件。
有時候你可能希望用戶的所有郵件都可以發送到其它地方。比如,你有一個伺服器群,你希望所有的 root 用戶的郵件都發給中心的系統管理員。或者你可能希望去創建一個郵件列表,將郵件發送給一些人。為實現上述目標,你可以使用別名,別名允許你為一個給定的用戶名定義一個或者多個目的地。這個目的地或者是其它用戶的郵箱、文件、管道、或者是某個進一步處理的命令。你可以在 /etc/mail/aliases
或者 /etc/aliases
中創建別名來實現上述目的。根據你的系統的不同,你可以找到上述其中一個,符號鏈接到它們、或者其中之一。改變別名文件你需要有 root 許可權。
別名的格式一般是:
name: addr_1, addr_2, addr_3, ...
這裡 name
是一個要別名的本地用戶名字(即別名),而 addr_1
,addr_2
,... 可以是一個或多個別名。別名可以是一個本地用戶、一個本地文件名、另一個別名、一個命令、一個包含文件,或者一個外部地址。
因此,發送郵件時如何區分別名呢(addr-N)?
- 本地用戶名是你機器上系統中的一個用戶名字。從技術角度來說,它可以通過調用
getpwnam
命令找到它。 - 本地文件名是以
/
開始的完全路徑和文件名。它必須是sendmail
可寫的。信息會追加到這個文件上。 - 命令是以一個管道符號開始的(
|
)。信息是通過標準輸入的方式發送到命令的。 - 包含文件別名是以
:include:
和指定的路徑和文件名開始的。在該文件中的別名被添加到該名字所代表的別名中。 - 外部地址是一個電子郵件地址,比如 john@somewhere.com。
你可以在你的系統中找到一個示例文件,它是與你的 sendmail 包一起安裝的,它的位置在 /usr/share/sendmail/examples/db/aliases
。它包含一些給 postmaster
、MAILER-DAEMON
、abuse
和 `spam 的別名建議。在清單 6,我把我的 Ubuntu 14.04 LTS 系統上的一些示例文件,和人工修改的示例結合起來說明一些可能的情況。
ian@attic4-u14:~$ cat /etc/mail/aliases
# First include some default system aliases from
# /usr/share/sendmail/examples/db/aliases
#
# Mail aliases for sendmail
#
# You must run newaliases(1) after making changes to this file.
#
# Required aliases
postmaster: root
MAILER-DAEMON: postmaster
# Common aliases
abuse: postmaster
spam: postmaster
# Other aliases
# Send steve's mail to bob and pat instead
steve: bob,pat
# Send pat's mail to a file in her home directory and also to her inbox.
# Finally send it to a command that will make another copy.
pat: /home/pat/accumulated-mail,
pat,
|/home/pat/makemailcopy.sh
# Mailing list for system administrators
sysadmins: :include: /etc/aliases-sysadmins
清單 6. 人工修改的 /etc/mail/aliases 示例
注意那個 pat 既是一個別名也是一個系統中的用戶。別名是以遞歸的方式展開的,因此,如果一個別名也是一個名字,那麼它將被展開。Sendmail 並不會給同一個用戶發送相同的郵件兩遍,因此,如果你正好將 pat 作為 pat 的別名,那麼 sendmail 在已經找到並處理完用戶 pat 之後,將忽略別名 pat。為避免這種問題,你可以在別名前使用一個 `` 做為前綴去指示它是一個不要進一步引起混淆的名字。在這種情況下,pat 的郵件除了文件和命令之外,其餘的可能會被發送到他的正常的郵箱中。
在 aliases
文件中以 #
開始的行是注釋,它會被忽略。以空白開始的行會以延續行來處理。
清單 7 展示了包含文件 /etc/aliases-sysadmins
。
ian@attic4-u14:~$ cat /etc/aliases-sysadmins
# Mailing list for system administrators
bob,pat
清單 7 包含文件 /etc/aliases-sysadmins
newaliases 命令
sendmail 使用的主要配置文件會被編譯成資料庫文件。郵件別名也是如此。你可以使用 newaliases
命令去編譯你的 /etc/mail/aliases
和任何包含文件到 /etc/mail/aliases.db
中。注意,newaliases
命令等價於 sendmail -bi
。清單 8 展示了一個示例。
ian@attic4-u14:~$ sudo newaliases
/etc/mail/aliases: 7 aliases, longest 62 bytes, 184 bytes total
ian@attic4-u14:~$ ls -l /etc/mail/aliases*
lrwxrwxrwx 1 root smmsp 10 Dec 8 15:48 /etc/mail/aliases -> ../aliases
-rw-r----- 1 smmta smmsp 12288 Dec 13 23:18 /etc/mail/aliases.db
清單 8. 為郵件別名重建資料庫
使用別名的示例
清單 9 展示了一個簡單的 shell 腳本,它在我的別名示例中以一個命令的方式來使用。
ian@attic4-u14:~$ cat ~pat/makemailcopy.sh
#!/bin/bash
# Note: Target file ~/mail-copy must be writeable by sendmail!
cat >> ~pat/mail-copy
清單 9. makemailcopy.sh 腳本
清單 10 展示了用於測試時更新的文件。
ian@attic4-u14:~$ date
Wed Dec 13 22:54:22 EST 2017
ian@attic4-u14:~$ mail -t sysadmins -s "sysadmin test 1" <<< "Testing mail"
ian@attic4-u14:~$ ls -lrt $(find /var/mail ~pat -type f -mmin -3 2>/dev/null )
-rw-rw---- 1 pat mail 2046 Dec 13 22:54 /home/pat/mail-copy
-rw------- 1 pat mail 13240 Dec 13 22:54 /var/mail/pat
-rw-rw---- 1 pat mail 9442 Dec 13 22:54 /home/pat/accumulated-mail
-rw-rw---- 1 bob mail 12522 Dec 13 22:54 /var/mail/bob
清單 10. /etc/aliases-sysadmins 包含文件
需要注意的幾點:
- sendmail 使用的用戶和組的名字是 mail。
- sendmail 在
/var/mail
保存用戶郵件,它也是用戶 mail 的家目錄。用戶 ian 的默認收件箱在/var/mail/ian
中。 - 如果你希望 sendmail 在用戶目錄下寫入文件,這個文件必須允許 sendmail 可寫入。與其讓任何人都可以寫入,還不如定義一個組可寫入,組名稱為 mail。這需要系統管理員來幫你完成。
使用一個 .forward
文件去轉發郵件
別名文件是由系統管理員來管理的。個人用戶可以使用它們自己的家目錄下的 .forward
文件去轉發他們自己的郵件。你可以在你的 .forward
文件中放任何可以出現在別名文件的右側的東西。這個文件的內容是明文的,不需要編譯。當你收到郵件時,sendmail 將檢查你的家目錄中的 .forward
文件,然後就像處理別名一樣處理它。
郵件隊列和 mailq 命令
Linux 郵件使用存儲-轉發的處理模式。你已經看到的已接收郵件,在你讀它之前一直保存在文件 /var/mail
中。你發出的郵件在接收伺服器連接可用之前也會被保存。你可以使用 mailq
命令去查看郵件隊列。清單 11 展示了一個發送給外部用戶 ian@attic4-c6 的一個郵件示例,以及運行 mailq
命令的結果。在這個案例中,當前伺服器沒有連接到 attic4-c6,因此郵件在與對方伺服器連接可用之前一直保存在隊列中。
ian@attic4-u14:~$ mail -t ian@attic4-c6 -s "External mail" <<< "Testing external mail queues"
ian@attic4-u14:~$ mailq
MSP Queue status...
/var/spool/mqueue-client is empty
Total requests: 0
MTA Queue status...
/var/spool/mqueue (1 request)
-----Q-ID----- --Size-- -----Q-Time----- ------------Sender/Recipient--------vBE4mdE7025908* 29 Wed Dec 13 23:48 <ian@attic4-u14.hopto.org>
<ian@attic4-c6.hopto.org>
Total requests: 1
清單 11. 使用 mailq
命令
其它郵件傳輸代理
為解決使用 sendmail 時安全方面的問題,在上世紀九十年代開發了幾個其它的郵件傳輸代理。Postfix 或許是最流行的一個,但是 qmail 和 exim 也大量使用。
Postfix 是 IBM 為代替 sendmail 而研發的。它更快、也易於管理、安全性更好一些。從外表看它非常像 sendmail,但是它的內部完全與 sendmail 不同。
Qmail 是一個安全、可靠、高效、簡單的郵件傳輸代理,它由 Dan Bernstein 開發。但是,最近幾年以來,它的核心包已經不再更新了。Qmail 和幾個其它的包已經被吸收到 IndiMail 中了。
Exim 是另外一個 MTA,它由 University of Cambridge 開發。最初,它的名字是 EXperimental Internet Mailer
。
所有的這些 MTA 都是為代替 sendmail 而設計的,因此,它們它們都兼容 sendmail 的一些格式。它們都能夠處理別名和 .forward
文件。有些封裝了一個 sendmail
命令作為一個到特定的 MTA 自有命令的前端。儘管一些選項可能會被靜默忽略,但是大多數都允許使用常見的 sendmail 選項。mailq
命令是被直接支持的,或者使用一個類似功能的命令來代替。比如,你可以使用 mailq
或者 exim -bp
去顯示 exim 郵件隊列。當然,輸出可以看到與 sendmail 的 mailq
命令的不同之外。
查看相關的主題,你可以找到更多的關於這些 MTA 的更多信息。
對 Linux 上的郵件傳輸代理的介紹到此結束。
via: https://www.ibm.com/developerworks/library/l-lpic1-108-3/index.html
作者:Ian Shields 譯者:qhwdw 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive