学习 Linux 101:邮件传输代理 (MTA) 基础知识

概述

在本教程中,您将学习以下内容:

  • 使用 mail 命令。
  • 创建邮件别名。
  • 配置邮件转发。
  • 了解常见的邮件传输代理 (MTA) 程序,例如 postfix、sendmail、qmail 和 exim。

控制邮件的去向

Linux 系统上的电子邮件是使用 MTA 传递的。MTA 将邮件传递给系统上的其他用户,并且 MTA 会相互通信,在整个系统组或全球范围内传递邮件。

Sendmail 是最古老的 Linux MTA。它最初源自 1979 年在 ARPANET 上使用的 deliverymail 程序。如今已经有了好几种替代 MTA。在本教程中,我还将向您介绍其他一些 MTA。

本教程将帮助您为 Linux Server Professional (LPIC-1) 考试 102 的主题 108 中的目标 108.3 做好应考准备。该目标的权重为 3。

前提条件

要想最充分地利用本系列教程,您应该掌握 Linux 的基本知识,还应该有一个正常工作的 Linux 系统,您可以在这个系统上练习本教程中涵盖的命令。您应熟悉 GNU 和 UNIX 命令。有时候,程序的不同版本将获得不同的输出格式,所以您的结果可能并不总是与这里显示的列表完全相同。

在本教程中,我将 Ubuntu 14.04 LTS 和 sendmail 8.14.4 用于 sendmail 示例。

邮件传输

邮件传输代理(例如 sendmail)用于在用户之间以及系统之间传递邮件。大多数互联网邮件都使用简单邮件传输协议 (SMTP),但是本地邮件还可以通过文件或套接字等其他方法进行传输。邮件是一种存储和转发操作,因此邮件存储在某种文件或数据库中,直到用户接收了该邮件或者接收系统或通信链路可用为止。配置和保护 MTA 是一项非常复杂的任务,其中大多数内容都不在本入门教程的范围内。

mail 命令

如果您使用 SMTP 电子邮件,可能知道有很多邮件客户端可供使用,包括 mailmuttalpinenotmuch 以及许多其他控制台和图形邮件客户端。mail 命令是一个旧的备用选项,可用于编写邮件发送脚本以及接收和管理这些邮件。

您可以通过传递地址列表以交互方式使用 mail 发送消息,如果不使用任何参数,则可以使用它来查看操作过的邮件。邮件 1 显示了如何向系统上的用户 steve 和 pat 发送消息,以及向用户 bob 发送副本。在提示输入抄送用户和主题时,通过按 Ctrl+D(按住 Ctrl 键并按 D)输入正文并完成消息。

清单 1. 以交互方式使用 mail 发送邮件

ian@attic4‑u14:~$ mail steve,pat
Cc: bob
Subject: Test message 1
This is a test message
 
Ian

如果一切顺利,您的邮件即已发送。如果出现错误,您将看到一条错误消息。例如,如果您键入无效的名称作为收件人,就不会发送邮件。注意,在此示例中,所有用户都在本地系统上,因此所有用户都必须是有效用户。

您还可以使用命令行以非交互方式发送邮件。邮件 2 显示了如何向用户 steve 和 pat 发送一条简短消息。此功能在脚本中特别有用。在不同的软件包中提供了不同版本的 mail 命令。一些版本支持用于抄送的 -c 选项,但我在这里使用的版本不支持,因此我仅指定收件人地址。

清单 2. 以非交互方式使用 mail

ian@attic4‑u14:~$ mail ‑t steve,pat  ‑s "Test message 2" <<< "Another test.\n\nIan"

如果您使用 mail 时不带任何选项,您将看到操作过的邮件列表,如邮件 3 所示。您会看到,用户 steve 收到了我上面发送的两条消息,还有我先前发送的消息以及用户 bob 后来发送的消息。所有邮件都以“N”标记,表示新邮件。

清单 3. 使用 mail 查看传入的邮件

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 中编号 为1的邮件。如果按 Enter,那么将显示下一条未读消息的首页。按空格键可逐页浏览消息。阅读完消息并回到“?”提示后,再次按 Enter 可查看下一条消息,依此类推。在任何“?”提示处,您都可以输入“h”再次查看消息标题的列表。您已阅读的消息现在会显示“R”状态,如邮件 4 中所示。

清单 4. 使用“h”显示邮件标题

? 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?
? 

在这里,Steve 已经阅读了来自 Ian 的三条消息,但尚未阅读 Bob 的消息。您可以按编号选择单个消息,也可以通过键入“d”来删除不需要的消息,或者键入“3d”来删除第三条消息。如果输入“q”,则将退出 mail 命令。已阅读的消息将传输到主目录中的 mbox 文件,未读的消息将保留在收件箱中,默认情况下位于 /var/mail/$(id -un) 中。参见邮件 5。

清单 5. 使用“q”退出 mail

? 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

如果您通过键入“x”退出而不是键入“q”退出,则您的邮箱将保持不变。因为您的邮箱位于 /var 文件系统上,所以系统管理员可能只允许在有限的时间内保存邮件。要重新阅读或以其他方式处理已保存到本地 mbox 文件中的邮件,可使用 -f 选项指定要阅读的文件。例如 mail -f mboxmail-fmbox

邮件别名

在上一节中,您了解了如何将邮件发送到系统上的各个用户。您可以使用标准名称(例如 ian@myexampledomain.com)将邮件发送给另一个系统上的用户。

有时,您可能希望某个用户的所有邮件都转到另一个位置。例如,您可能有一个服务器场,希望所有根邮件都发给中央系统管理员。或者,您可能想创建一个邮件列表,其中的邮件会发送给多个人。为此,可以使用别名,这样便能够为给定的用户名定义一个或多个目标。目标可以是其他用户邮箱、文件、管道或执行进一步处理的命令。可以通过在 /etc/mail/aliases 或 /etc/aliases 中指定别名来完成。根据系统,您可能会发现其中某个别名是另一个的符号链接,或者您可能只有其中一个别名。您需要 root 权限才能更改别名文件。

别名的形式一般为 name: addr_1, addr_2, addr_3, … 其中,name 是指别名的本地用户名或别名,而 addr_1, addr_2, … 则是一个或多个别名。别名可以是本地用户、本地文件名、另一个别名、命令、包含文件或外部地址。

那么 sendmail 如何区分别名(addr-N 值)?

  • 本地用户名是与该系统上的用户名相匹配的文本字符串。从技术上讲,这意味着可以通过 getpwnam 调用找到它。
  • 本地文件名是完整路径和以“/”开头的文件名。它必须可由 sendmail 写入。消息将附加到文件中。
  • 命令以管道符号 (|) 开头。使用标准输入将消息发送到命令。
  • 包含文件别名以 :include: 开头,并指定路径和文件名。文件中的别名将添加到该名称的别名中。
  • 外部地址是电子邮件地址,例如 john@somewhere.com。

您应该会找到一个示例文件,例如,与 sendmail 包一起安装的 /usr/share/sendmail/examples/db/aliases。它包含为 postmaster、MAILER-DAEMON、abuse 和 spam 推荐的一些别名。在别名 1 中,我将 Ubuntu 14.04 LTS 系统上示例文件中的条目与一些人工构建的示例相结合,说明了几种可能性。

清单 6. 人工稍作修改的 /etc/mail/aliases 示例

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 liases

#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

注意,pat 既是别名又是系统的用户。别名扩展是递归的,因此,如果别名也是名称,则将对其进行扩展。Sendmail 不会向给定用户发送邮件两次,因此,如果您就是要将“pat”作为“pat”的别名,那么由于 sendmail 已经找到并处理了“pat”,因此会将其忽略。为避免此问题,可在别名前添加“\”作为前缀,表示该名称不再受别名影响。这样便可以将 pat 的邮件连同文件和命令发送到她的正常邮箱。

别名中以“$”开头的行是注释,将被忽略。以空格开头的行被视为连续行。

别名 2 中显示了包含文件 /etc/aliases-sysadmins。

清单 7. /Etc/aliases-sysadmins 包含文件

ian@attic4‑u14:~$ cat /etc/aliases‑sysadmins

#Mailing list for system administrators
bob,pat

newaliases 命令

sendmail 使用的大多数配置文件都被编译成数据库文件。对于邮件别名也是如此。可以使用 newaliases 命令将 /etc/mail/aliases 以及包含的所有文件编译到 /etc/mail/aliases.db 中。注意,newaliases 等效于 sendmail -bisendmail-bi。Newalias 1 显示了一个示例。

清单 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

别名用法示例

别名 3 显示了一个简单的 Shell 脚本,它在我的别名示例中用作命令。

清单 9. makemailcopy.sh 脚本

ian@attic4‑u14:~$ cat ~pat/makemailcopy.sh
#!/bin/bash

#Note: Target file ~/mail‑copy must be writeable by sendmail!
cat >> ~pat/mail‑copy

别名 4 显示了当您对所有这些都进行测试时更新的文件。

清单 10. /Etc/aliases-sysadmins 包含文件

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

须注意的几个要点:

  • 这里有一个用户“mail”,包含由 sendmail 使用的组名“mail”。
  • 用户邮件由 sendmail 存储在 /var/mail 中,该目录也是用户“mail”的主目录。用户“ian”的收件箱默认为 /var/mail/ian。
  • 如果要让 sendmail 在某个用户目录中写入文件,则 sendmail 必须有该文件的写入权限。通常是将该文件设置为可写入组,并将该组设为“邮件”,而不是将该文件变为全局可写。您可能需要让系统管理员为您执行此操作。

使用 .forward 文件来转发邮件

别名文件必须由系统管理员来管理。单个用户可以使用各自主目录中的 .forward 文件为自己的邮件启用转发功能。您可以在 .forward 文件中输入别名文件右侧允许的任何内容。该文件包含纯文本,无需编译。当您是邮件的目标收件人时,sendmail 会检查您的主目录中的 .forward 文件,并采用与处理别名相同的方式来处理条目。

邮件队列和 mailq 命令

Linux 邮件处理使用存储转发模型。您已经了解到,尚未阅读的传入邮件会存储在 /var/mail 中的文件中。外发邮件也存储在这里,直到接收服务器连接可用为止。您可以使用 mailq 命令来查看加入队列中的邮件。Mailq 1 显示了将邮件发送给外部用户 ian@attic4-c6 的示例,以及运行 mailq 命令的结果。在这种情况下,当前没有指向 attic4-c6 的活动链接,因此邮件将保持排队状态,直到链接变为活动状态为止。

清单 11. 使用 mailq 命令

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 (less thanian@attic4‑u14.hopto.org>
   (less- hanian@attic4‑c6.hopto.org>
  Total requests: 1

其他的邮件传输代理

为了解决 sendmail 的安全问题,人们在上世纪 90 年代就开发了其他几种邮件传输代理。Postfix 也许最受欢迎,但是 qmail 和 exim 也使用广泛。

Postfix 源自于 IBM 研究院,旨在替代 sendmail。它的目标是速度更快、更易于管理且更安全。它的外观看起来有点像 sendmail,但是内在却完全不同。

Qmail 是由 Dan Bernstein 开发的安全、可靠、高效且简单的邮件传输代理。但是,qmail 的核心包已经多年没有更新。Qmail 和其他几个包现在已集成到 IndiMail 中。

Exim 是剑桥大学开发的另一种 MTA。起初,该名称代表实验性互联网邮件程序 (EXperimental Internet Mailer)。

所有这些 MTA 都旨在替代 sendmail,因此它们都在某种形式上兼容 sendmail。它们都可以处理别名和 .forward 文件。一些 MTA 提供了 sendmail 命令作为特定 MTA 自有命令的前端。大多数则都允许使用通常的 sendmail 选项,但某些选项可能会被静默忽略。直接支持 mailq 命令,或者通过具有类似功能的替代命令来支持。例如,您可以使用 mailq 或 exim -bpexim-bp 来显示 exim 邮件队列。当然,这里的输出与 sendmail 的 mailq 命令生成的输出可能会有所不同。

参阅右侧的资源,可找到有关所有这些 MTA 的更多信息。

有关 Linux 上的邮件传输代理的介绍到此结束。

本文翻译自:Learn Linux, 101: Mail transfer agent (MTA) basics(2017-12-21)

Legend