Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-doc
Path: blob/main/documentation/content/zh-cn/books/handbook/mail/_index.adoc
18099 views
---
title: 第 29 章 电子邮件
part: 部分 IV. 网络通讯
prev: books/handbook/ppp-and-slip
next: books/handbook/network-servers
showBookMenu: true
weight: 34
params:
  path: "/books/handbook/mail/"
---

[[mail]]
= 电子邮件
:doctype: book
:toc: macro
:toclevels: 1
:icons: font
:sectnums:
:sectnumlevels: 6
:sectnumoffset: 29
:partnums:
:source-highlighter: rouge
:experimental:
:images-path: books/handbook/mail/

ifdef::env-beastie[]
ifdef::backend-html5[]
:imagesdir: ../../../../images/{images-path}
endif::[]
ifndef::book[]
include::shared/authors.adoc[]
include::shared/mirrors.adoc[]
include::shared/releases.adoc[]
include::shared/attributes/attributes-{{% lang %}}.adoc[]
include::shared/{{% lang %}}/teams.adoc[]
include::shared/{{% lang %}}/mailing-lists.adoc[]
include::shared/{{% lang %}}/urls.adoc[]
toc::[]
endif::[]
ifdef::backend-pdf,backend-epub3[]
include::../../../../../shared/asciidoctor.adoc[]
endif::[]
endif::[]

ifndef::env-beastie[]
toc::[]
include::../../../../../shared/asciidoctor.adoc[]
endif::[]

[[mail-synopsis]]
== 概述

"电子邮件",或通常所说的 email,是现今使用最广泛的通信方式之一。 本章将对如何在 FreeBSD 上运行邮件服务,以及如何使用 FreeBSD 来收发电子邮件作基本的介绍; 然而,它并不是一份完整的参考手册,实际上,许多需要考虑的重要事项都没有提及。 我们推荐读者阅读 crossref:bibliography[bibliography,参考文献] 中的参考书籍,以获得对于这部分的全面认识。

读完这章,您将了解:

* 哪些软件与收发电子邮件有关。
* FreeBSD 下的基本 sendmail 配置文件在哪里。
* 本地和远程邮箱之间的区别。
* 如何阻止垃圾邮件制造者非法地使用您的邮件服务器作为转发中继。
* 如何安装和配置用于替代 sendmail 的其他邮件传输代理。
* 如何处理常见的邮件服务器问题。
* 如何使用 SMTP 和 UUCP。
* 如何设置系统使其只能发送邮件。
* 如何在拨号连接时使用邮件。
* 如何配置 SMTP 验证以增加安全性。
* 如何安装并使用用户邮件代理,如 mutt 来收发邮件。
* 如何从远程的 POP 或 IMAP 服务器上下载邮件。
* 如何在进入的邮件上自动地应用过滤器和规则。

阅读本章之前,您需要:

* 正确地配置您的网络连接 (crossref:advanced-networking[advanced-networking,高级网络]).
* 正确地为您的邮件服务器配置 DNS 信息 (crossref:network-servers[network-servers,网络服务]).
* 知道如何安装第三方软件 (crossref:ports[ports,安装应用程序. Packages 和 Ports]).

[[mail-using]]
== 使用电子邮件

邮件交换可以分为 5 部分。它们是: <<mail-mua,用户端程序>>、<<mail-mta,服务端守护进程>>、<<mail-dns,DNS>>、<<mail-receive,远程或本地的邮箱>>、 当然,<<mail-host,还有邮件主机自己>>。

[[mail-mua]]
=== 用户端程序

这包括一些基于命令行的程序,例如 mutt、 alpine、elm 和 `mail`,以及类似 balsa、 xfmail 这样的 GUI 程序。 此外,还有我们更"熟悉的"WWW 浏览器这样的程序。 这些程序简单地通过调用<<mail-mta,服务守护进程>>把邮件事务交给本地的 <<mail-host,"邮件主机">>,或者通过 TCP 把邮件发出去。

[[mail-mta]]
=== 邮件主机上使用的服务程序

FreeBSD 默认情况下采用 sendmail, 但它也支持为数众多的其它邮件服务程序, 这其中包括:

* exim;
* postfix;
* qmail.

邮件服务器后台守护程序通常有两个功能 - 接收外面发来的邮件和把邮件传送出去。 但它 _不_ 负责使用类似 POP 或 IMAP 这样的协议来帮您阅读邮件, 也不负责连接到本地的 [.filename]#mbox# 或 Maildir 信箱。 您可能需要其它的 <<mail-receive,服务程序>> 来完成这些任务。

[WARNING]
====

较早版本的 sendmail 有一些严重的安全问题, 他们可能导致攻击者从本地和/或远程操作您的电脑。 您应该确认自己使用的是最新版本以避免这些问题。 另外, 也可以从 crossref:ports[ports,FreeBSD Ports Collection] 来安装其它的 MTA。
====

[[mail-dns]]
=== Email 和 DNS

域名系统 (DNS) 及其服务程序 `named` 在email的投递过程当中扮演着很重要的角色。 为了能够从您的站点向其它的站点传递邮件, 服务程序需要通过 DNS 查找接收邮件的远程站点的位置。 类似地, 在远程站点向您的主机投递邮件时也会发生这样的查找。

DNS 负责将主机名映射为 IP 地址, 同时, 也需要保存递送邮件时所需要的信息, 这些信息称作 MX 记录。 MX (Mail eXchanger,邮件交换) 记录指定了哪个, 或哪些主机能够接收特定域下的邮件。 如果您没有为主机名或域名设置 MX 记录, 则邮件将被直接递交给主机名对应 IP 所在的主机。

您可以通过 man:host[1] 命令来查找任何域或主机名对应的 MX 记录, 如下面的例子所示:

[source,shell]
....
% host -t mx FreeBSD.org
FreeBSD.org mail is handled (pri=10) by mx1.FreeBSD.org
....

[[mail-receive]]
=== 接收邮件

为您的域接收邮件是通过邮件服务器来完成的。 它收集发送给您的域的那些邮件,并保存到 [.filename]#mbox# (存储邮件默认的方法) 或 Maildir 格式, 这取决于您采用的配置。 一旦邮件被保存下来, 就可以在本地通过类似 man:mail[1] 或 mutt 这样的程序, 或在远程通过 POP 或 IMAP 这样的协议来读取了。 简单地说, 如果您只在本地阅读邮件,那就没有必要安装 POP 或 IMAP 服务。

[[pop-and-imap]]
==== 通过 POP 和 IMAP 访问远程的邮件

如果希望在远程访问邮箱, 就需要访问 POP 或 IMAP 服务器。 这些协议允许用户从远程方便地访问他们的信箱。 尽管 POP 和 IMAP 都允许用户从远程访问信箱, 但 IMAP 有很多优点, 这包括:

* IMAP 既可以从远程服务器上抓取邮件, 也可以把邮件放上去。
* IMAP 支持并发更新。
* IMAP 对于使用低速网络的用户尤为有用, 因为它能够让这些用户把邮件的结构下载下去, 而无需立即下载整个邮件。 它还可以在服务器端执行类似查找这样的操作, 以减少客户机和服务器之间的通讯量。

您可以按照下面的步骤来安装和配置 POP 或 IMAP 服务器:

[.procedure]
====
. 选择一个最符合需要的 IMAP 或 POP 服务器。 下列 POP 和 IMAP 服务器是最著名的, 而且都有很多成功案例:
+
** qpopper;
** teapop;
** imap-uw;
** courier-imap;
** dovecot;
+
. 通过 ports collection 安装 POP 或 IMAP 服务。
. 根据需要修改 [.filename]#/etc/inetd.conf# 来加载 POP 或 IMAP 服务。
====

[WARNING]
====

此外还应注意的是 POP 和 IMAP 传递的信息, 包括用户名和口令等等, 通常都是明文的。 这意味着如果您希望加密传输过程中的信息, 可能需要考虑使用 man:ssh[1] 隧道或者使用SSL。 关于如何实施隧道在 crossref:security[security-ssh-tunneling,SSH 隧道] 中进行了详细阐述, SSL 部分在crossref:security[openssl,OpenSSL]。
====

[[local]]
==== 操作本地的信箱

信箱可以在邮件服务器本地直接用 MUA 来进行操作。 这通常是通过 mutt 或 man:mail[1] 这样的应用程序实现的。 

[[mail-host]]
=== 邮件服务器

邮件服务器是通过服务器给的一个名字 (译注:来识别主机), 这也正是它能在您的主机和网络上发送和接收邮件的原因。

[[sendmail]]
== sendmail 配置

man:sendmail[8] 是 FreeBSD 中的默认邮件传输代理 (MTA)。 sendmail 的任务是从邮件用户代理 (MUA) 接收邮件然后根据配置文件的定义把它们送给配置好的的寄送程序。 sendmail 也能接受网络连接, 并且发送邮件到本地邮箱或者发送它到其它程序。

sendmail 使用下列配置文件:

[.informaltable]
[cols="1,1", frame="none", options="header"]
|===
| 文件名
| 功能

|[.filename]#/etc/mail/access#
|sendmail 访问数据库文件 

|[.filename]#/etc/mail/aliases#
|邮箱别名

|[.filename]#/etc/mail/local-host-names#
|sendmail 接收邮件主机列表

|[.filename]#/etc/mail/mailer.conf#
|邮寄配置程序

|[.filename]#/etc/mail/mailertable#
|邮件分发列表

|[.filename]#/etc/mail/sendmail.cf#
|sendmail的主配置文件 

|[.filename]#/etc/mail/virtusertable#
|虚拟用户和域列表
|===

=== [.filename]#/etc/mail/access#

访问数据库定义了什么主机或者 IP 地址可以访问本地邮件服务器和它们是哪种类型的访问。 主机可能会列出 `OK`、 `REJECT`、`RELAY` 或者简单的通过 sendmail 的出错处理程序检测一个给定的邮件错误。 主机默认列出 `OK`,允许传送邮件到主机, 只要邮件的最后目的地是本地主机。列出 `REJECT` 将拒绝所有的邮件连接。如果带有 `RELAY` 选项的主机将被允许通过这个邮件服务器发送邮件到任何地方。

.配置 sendmail 的访问许可数据库
[example]
====
[.programlisting]
....
cyberspammer.com                550 We do not accept mail from spammers
FREE.STEALTH.MAILER@            550 We do not accept mail from spammers
another.source.of.spam          REJECT
okay.cyberspammer.com           OK
128.32                          RELAY
....

====

在上面的例子中我们有 5 条记录。 与左边列表匹配的发件人受到右边列表动作的影响。 前边的两个例子给出了 sendmail 的出错处理程序检测到的错误代码。 当一个邮件与左边列表相匹配时,这个信息会被打印到远程主机上。 下一条记录拒绝来自 Internet 上的一个特别主机的邮件 `another.source.of.spam`。接下来的记录允许来自 `okay.cyberspammer.com` 的邮件连接, 这条记录比上面那行 `cyberspammer.com` 更准确。更多的准确匹配使不准确的匹配无效。最后一行允许电子邮件从主机和 `128.32` 开头的 IP 地址转发。 这些主机将被允许通过这台邮件服务器前往其它邮件服务器发送邮件。

当这个文件被升级的时候,您必须在 [.filename]#/etc/mail/# 运行 `make` 升级数据库。

=== [.filename]#/etc/mail/aliases#

别名数据库包含一个扩展到用户,程序或者其它别名的虚拟邮箱列表。 下面是一些在 [.filename]#/etc/mail/aliases# 中使用的例子:

.邮件别名
[example]
====
[.programlisting]
....
root: localuser
ftp-bugs: joe,eric,paul
bit.bucket:  /dev/null
procmail: "|/usr/local/bin/procmail"
....

====

这个文件的格式很简单; 冒号左边的邮箱名, 会被展开成右边的形式。 第一个例子简单地将 `root` 邮箱扩展为 `localuser`, 之后将继续在别名数据库中进行查找。 如果没有找到匹配的记录, 则邮件会被发给本地用户 `localuser`。 第二个例子展示了一个邮件列表。 发送到 `ftp-bugs` 的邮件会被展开成 `joe`, `eric` 和 `paul` 这三个邮箱。 注意也可以通过 mailto:[email protected][[email protected]] 这样的形式来指定远程的邮箱。 接下来的例子展示了如何把邮件写入到文件中, 这个例子中是 [.filename]#/dev/null#。 最后一个例子展示了如何将邮件发给一个程序, 具体而言是通过 UNIX(R) 管道发到 [.filename]#/usr/local/bin/procmail# 的标准输入。

更新此文件时, 您需要在 [.filename]#/etc/mail/# 中使用 `make` 来更新数据库。

=== [.filename]#/etc/mail/local-host-names#

这是一个 man:sendmail[8] 被接受为一个本地主机名的主机名列表。 可以放入任何 sendmail 将从那里收发邮件的域名或主机。例如,如果这个邮件服务器从域 `example.com` 和主机 `mail.example.com` 接收邮件,它的 [.filename]#local-host-names# 文件,可以看起来象如下这样:

[.programlisting]
....
example.com
mail.example.com
....

当这个文件被升级,man:sendmail[8] 必须重新启动,以便更新设置。

=== [.filename]#/etc/mail/sendmail.cf#

sendmail的主配置文件 [.filename]#sendmail.cf# 控制着 sendmail 的所有行为, 包括从重写邮件地址到打印拒绝远程邮件服务器信息等所有事。 当然,作为一个不同的角色,这个配置文件是相当复杂的, 它的细节部分已经超出了本节的范围。幸运的是, 这个文件对于标准的邮件服务器来说很少需要被改动。

sendmail 主配置文件可以用 man:m4[1] 宏定义 sendmail 的特性和行为。它的细节请看 [.filename]#/usr/src/contrib/sendmail/cf/README#。

当这个文件被修改时, sendmail 必须重新启动以便对新修改生效。

=== [.filename]#/etc/mail/virtusertable#

[.filename]#virtusertable# 映射虚拟域名和邮箱到真实的邮箱。 这些邮箱可以是本地的、远程的、[.filename]#/etc/mail/aliases# 中定义的别名或一个文件。

.虚拟域邮件映射的例子
[example]
====
[.programlisting]
....
[email protected]                root
[email protected]          [email protected]
@example.com                    joe
....

====

在上面这个例子中, 我们映射了一个域 `example.com`。 这个文件是按照从上到下, 首个匹配的方式来处理的。 第一项将 mailto:[email protected][[email protected]] 映射到本地邮箱 `root`。 下一项则将 mailto:[email protected][[email protected]] 映射到位于 `noc.example.net` 的 `postmaster`。 最后, 如果没有来自 `example.com` 的匹配, 则将使用最后一条映射, 它表示将所有的其它邮件发给 `example.com` 域的某个人。 这样, 将映射到本地信箱 `joe`。

[[mail-changingmta]]
== 改变您的邮件传输代理程序

先前已经提到,FreeBSD 中的 sendmail 已经安装了您的 MTA (邮件传输代理程序)。因此它负责着您的收发邮件的工作。

然而,基于不同的理由,一些系统管理员想要改变他们系统的 MTA。这些理由从简单的想要尝试另一个 MTA,到需要一个特殊的特性或者 package 依赖某个邮寄程序等等。幸运的是,不管是什么理由,FreeBSD 都能容易的改变它。

=== 安装一个新的 MTA

对于可用的 MTA 您有很多的选择。一个好的出发点是 crossref:ports[ports,FreeBSD Ports Collection],在那里您能找到很多。 当然您可以从任何位置不受任何限制的使用 MTA,只要您能让它运行在 FreeBSD 下。

开始安装您的新 MTA。一旦它被安装, 它可以让您有机会判定它是否能满足您的需要, 并且在它接管 sendmail 之前让您有机会配置您的新软件。 当完成这些之后,您应该确信安装的新软件不会尝试更改系统的二进制文件例如 [.filename]#/usr/bin/sendmail#。 除此以外, 您的新邮件软件启用之前要已经配置好它。

具体配置请参考您所选择的 MTA 软件的配置文档或其它相关资料。

[[mail-disable-sendmail]]
=== 禁用 sendmail

[WARNING]
====

如果您打算禁用 sendmail 的邮件发出服务, 保持系统中有一个替代它的、 可用的邮件递送系统就非常重要。 如果您不这样做的话, 类似 man:periodic[8] 这样的系统功能就无法如预期的那样, 通过邮件来传送其执行结果。 您系统中的许多部分可能都假定有可用的 sendmail-兼容 系统。 如果这些应用程序继续使用 sendmail 的执行文件来发送邮件, 而您又禁用了它, 则邮件将进入 sendmail 的非活跃 (inactive) 队列, 而永远不会被送达。
====

要彻底禁用包括邮件送出服务在内的所有 sendmail 功能, 必须将

[.programlisting]
....
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
....

写入 [.filename]#/etc/rc.conf#。

如果只是想要停止 sendmail 的接收邮件服务, 您应该在 [.filename]#/etc/rc.conf# 文件中设置

[.programlisting]
....
sendmail_enable="NO"
....

更多的有关 sendmail 可用的启动选项,参看 man:rc.sendmail[8] 联机手册.

=== 机器引导时运行您的新 MTA

可以向 [.filename]#/etc/rc.conf# 中加入配置项使新的 MTA 在系统启动时运行, 下面是一个 postfix 的例子:

[source,shell]
....
# echo 'postfix_enable=“YES”' >> /etc/rc.conf
....

这样 MTA 就能在系统启动是自动运行了。

=== 替换系统默认的邮寄程序 sendmail

因为 sendmail 程序是一个在 UNIX(R) 系统下普遍存在的一个标准的软件,一些软件就假定它已经被安装并且配置好。 基于这个原因,许多其它的 MTA 提供者都提供了兼容 sendmail 的命令行界面来执行。 这使它们像"混入"sendmail 一样变的很容易掌握。

因此,如果您使用其它的邮寄程序, 您必须确定这个软件是去尝试运行标准的 sendmail 二进制,就象 [.filename]#/usr/bin/sendmail#,还是运行您自己选择的替换邮寄程序。 幸运的是,FreeBSD 提供了一个系统调用 man:mailwrapper[8],它能为您做这件工作。

当 sendmail 安装后被运行,您可以在 [.filename]#/etc/mail/mailer.conf# 中找到如下行:

[.programlisting]
....
sendmail	 /usr/libexec/sendmail/sendmail
send-mail	/usr/libexec/sendmail/sendmail
mailq		/usr/libexec/sendmail/sendmail
newaliases	/usr/libexec/sendmail/sendmail
hoststat	/usr/libexec/sendmail/sendmail
purgestat	/usr/libexec/sendmail/sendmail
....

这个的意思就是当这些公共命令 (例如 [.filename]#sendmail# 它本身) 运行时, 系统实际上调用了一个 [.filename]#sendmail# 指定的 mailwrapper 的副本,它检查 [.filename]#mailer.conf# 并且运行 [.filename]#/usr/libexec/sendmail/sendmail# 做为替代。当默认的 [.filename]#sendmail# 功能被调用, 系统将很容易的改变实际上运行的二进制文件。

因此如果您想要 [.filename]#/usr/local/supermailer/bin/sendmail-compat# 替换 sendmail 被运行,您应该改变 [.filename]#/etc/mail/mailer.conf# 文件为:

[.programlisting]
....
sendmail	 /usr/local/supermailer/bin/sendmail-compat
send-mail	/usr/local/supermailer/bin/sendmail-compat
mailq		/usr/local/supermailer/bin/mailq-compat
newaliases	/usr/local/supermailer/bin/newaliases-compat
hoststat	/usr/local/supermailer/bin/hoststat-compat
purgestat	/usr/local/supermailer/bin/purgestat-compat
....

=== 最后

一旦做完您想要配置的每件事,您应该杀掉 sendmail 进程并且启动属于您的新软件的进程, 或者简单的重启。 重启也将给您提供了确认您的系统已经进行了正确的配置的机会。 在引导的时候自动的运行您新的 MTA。

[[mail-trouble]]
== 疑难解答

=== 为什么必须在我的站点的主机上使用 FQDN?

您可能会发现主机实际上是在另外一个域里面, 例如,如果您是在 `foo.bar.edu` 里,而您要找一台叫 `mumble` 的主机,它在 `bar.edu` 域里,您就必须用完整的域名 `mumble.bar.edu`,而不是用 `mumble`。

传统上,这在 BSD BIND resolvers 中是可行的。 然而目前随 FreeBSD 附带的 BIND 已不为同一域外提供缩写服务。所以,这个不完整的主机名 `mumble` 必须以 `mumble.foo.bar.edu` 这种形式才能被找到, 或者将在根域中搜索它。

这跟以前的处理是不同的,以前版本将会继续寻找 `mumble.bar.edu` 和 `mumble.edu`。 如果您想要了解这种方式是否是好,或者它有什么安全方面的漏洞, 请参阅 RFC 1535 文档。

如果您想要一个好的工作环境,您可以使用如下行: 
[.programlisting]
....
search foo.bar.edu bar.edu
....

替换先前旧的版本: 

[.programlisting]
....
domain foo.bar.edu
....

把这行放在您的 [.filename]#/etc/resolv.conf# 文件中。然而,请一定要确定这样的搜寻顺序不会造成 RFC 1535 里提到的"boundary between local and public administration" 问题。

=== sendmail 提示信息 mail loops back to myself

下面是 sendmail FAQ 中的回答:

[.programlisting]
....
我得到了如下的信息:

553 MX list for domain.net points back to relay.domain.net
554 <[email protected]>... Local configuration error

我如何解决这个问题?

您已经通过 MX 记录指定把发送给特定的域 (例如,domain.net)
的邮件被转寄到指定的主机 (在这个例子中,relay.domain.net),
而这台机器并不认为它自己是 domain.net。请把 domain.net 添加到
/etc/mail/local-host-names 文件中 [在 8.10 版之前是 /etc/sendmail.cw]
(如果您使用 FEATURE(use_cw_file) 的话) 或者在 /etc/mail/sendmail.cf
中添加Cw domain.net。
MX record
....

sendmail 的 FAQ 可以在 http://www.sendmail.org/faq/[http://www.sendmail.org/faq/] 找到, 如果您想要对您的邮件做任何的"调整", 则推荐首先看一看它。

=== 我如何在一个拨号主机上运行一个邮件服务? PPP

您想要把局域网上的 FreeBSD 主机连接到互连网上,而这台 FreeBSD 主机将会成为这个局域网的邮件网关, 这个拨号连接不必一直保持在连接状态。

最少有两种方法可以满足您的要求。一种方法就是使用 UUCP。

另一种方法是找到一个专职的服务器来为您的域提供副 MX 主机服务。 例如,如果您公司的域名是 `example.com`,您的互连网服务提供者把 `example.net` 作为您域的副 MX 服务:

[.programlisting]
....
example.com.          MX        10      example.com.
                      MX        20      example.net.
....

只有一台主机被指定当做您的最终收信主机 (在 `example.com` 主机的 [.filename]#/etc/mail/sendmail.cf# 文件中添加 `Cw example.com`)。

当 `sendmail` 试图分发邮件的时候, 它会尝试通过 modem 连接到您 (`example.com`)。 因为您并不在线,所以总是会得到一个超时的错误。 sendmail 将会把邮件发送到副 MX 主机,也就是说,您的互连网服务提供者 (`example.net`)。副 MX 主机将周期性的尝试连接并发送邮件到您的主机 (`example.com`)。

您也许想要使用下面的这个登录脚本:

[.programlisting]
....
#!/bin/sh
# Put me in /usr/local/bin/pppmyisp
( sleep 60 ; /usr/sbin/sendmail -q ) &
/usr/sbin/ppp -direct pppmyisp
....

如果您想要为一个用户建立一个分开登录的脚本, 您可以使用 `sendmail -qRexample.com` 替换上面的脚本。这样将使所有的邮件按照您的 `example.com` 队列立即被处理。

更深入的方法可以参考下面这段:

这段信息是从 {freebsd-isp} 拿来的。

[.programlisting]
....
> 我们为用户提供副 MX 主机服务。用户每天都会上线好几次
> 并且自动把信件取回主 MX 主机
> (当有他们的邮件时我们并没有通知他们)。
> 我们的 mailqueue 程序每 30 分钟清一次邮件队列。那段时间他们
> 就必须上线 30 分钟以确保他们的信件送达他们的主 MX 主机。
>
> 有任何指令可以用 sendmail 寄出所有邮件么?
> 普通用户在我们的机器上当然没有 root 权限。

在 sendmail.cf 的privacy flags部分,有这样的设定
Opgoaway,restrictqrun

移除 restrictqrun 可以让非 root 用户启动队列处理的程序。
您可能也要重新安排您的 MX 设定。我们是用户的 MX 主机,
而且我们还设定了这个:

# If we are the best MX for a host, try directly instead of generating # local config error.
OwTrue

这样的话远程机器会直接把信送给您,而不会尝试连接您的用户的机器。
然后您就可以把邮件发送到您的用户。这个设定只对
主机有效,所以您必须要让您的用户在 DNS 中把他们的邮件主机设置为
customer.com或者
hostname.customer.com。只要为customer.com在 DNS
里添加一个 A 记录就可以了。
....

=== 为什么当我发送邮件到其它主机总是有 Relaying Denied 出错信息?

默认的 FreeBSD 安装中, sendmail 会配置为只发送来自它所在主机上的邮件。 例如,如果有可用的 POP 服务器,则用户将可以从学校、 公司或其他什么别的地方检查邮件,但他们仍然无法从远程直接发送邮件。 通常,在几次尝试之后, MAILER-DAEMON 将发出一封包含 `5.7 Relaying Denied` 错误信息的邮件。

有很多方法可以避免这种现象。 最直截了当的方法是把您的 ISP 的地址放到 [.filename]#/etc/mail/relay-domains# 文件中。 完成这项工作的简单的方法是:

[source,shell]
....
# echo "your.isp.example.com" > /etc/mail/relay-domains
....

建立或编辑这个文件以后您必须重新启动 sendmail。 如果您是一个管理员并且不希望在本地发送邮件, 或者想要在其它的机器甚至其它的 ISP 上使用一个客户端系统, 这个方法是很方便的。如果您仅有一到两个邮件帐户它也非常的有用。 如果有大量的地址需要添加, 您可以很简单的使用您喜欢的文本编辑器打开这个文件添加域名, 每行一个:

[.programlisting]
....
your.isp.example.com
other.isp.example.net
users-isp.example.org
www.example.org
....

现在邮件可以通过您的系统传送, 这个列表中存在的主机 (前提是用户在您的系统上已经有一个帐户) 将可以成功的发送。这是一个允许正常的远程用户从您的系统发送邮件, 并且阻止其它非法用户通过您系统发送垃圾邮件的好方法。

[[mail-advanced]]
== 高级主题

下面这节将介绍邮件配置和为整个域安装邮件。

[[mail-config]]
=== 基本配置

在邮箱外,只要您设置 [.filename]#/etc/resolv.conf# 或者运行您自己的名字服务器,您就可以发送邮件到外部的主机。 如果您想要您的邮件发送给某个特定的 MTA(例如, sendmail) 在您的 FreeBSD 主机上,有两个方法:

* 运行您自己的域名服务器和您自己的域。例如, `FreeBSD.org`
* 获得直接分发给您主机的邮件。您可以直接使用您当前的 DNS 名称。例如,`example.FreeBSD.org`。

不管您选择上面那种方法,为了直接在您的主机上发送邮件, 必须有一个静态的 IP 地址(不是象 PPP 拨号一样的动态地址)。 如果您在防火墙后面,它必须让 SMTP 协议通过。 如果您想要在您的主机上直接的收取邮件, 您必须确定两件事:

* 确定在您 DNS 中的 MX 记录(最小编号的)指向您的 IP 地址。
* 确定在您 DNS 中的 MX 记录没有禁止您的主机。

上面的每条记录都允许您在您的主机直接接收邮件。

试试这个:

[source,shell]
....
# hostname
example.FreeBSD.org
# host example.FreeBSD.org
example.FreeBSD.org has address 204.216.27.XX
....

如果您看到这些, 则直接发往 mailto:[email protected][[email protected]] 应该已经可以正常工作了 (假设 sendmail 已经在 `example.FreeBSD.org` 上正确启动了)。

如果您看到这些:

[source,shell]
....
# host example.FreeBSD.org
example.FreeBSD.org has address 204.216.27.XX
example.FreeBSD.org mail is handled (pri=10) by hub.FreeBSD.org
....

所有发送到主机 (`example.FreeBSD.org`) 的邮件在相同的用户名下将会被 `hub` 终止的收集,而不是直接发送到您的主机。

上面的信息是通过您的 DNS 服务器来处理的。支持邮件路由信息的 DNS 记录是 __邮件 交换__ 记录。如果 MX 记录不存在,邮件将通过它自己的 IP 地址被直接的发送到主机。

``freefall.FreeBSD.org``的MX记录如下所示:

[.programlisting]
....
freefall		MX	30	mail.crl.net
freefall		MX	40	agora.rdrop.com
freefall		MX	10	freefall.FreeBSD.org
freefall		MX	20	who.cdrom.com
....

正如您说看到的,`freefall` 有很多 MX 记录。 最小编号的 MX 记录是直接接收邮件的主机。如果因为一些原因它不可用,其它 (有时会访问"backup MXes")接收信息将会暂时接替并做临时的排列。

为了有效的使用交换式 MX 站点,应当从您的机器上分离一些 Internet 连接。您的 ISP 或者其它友好的站点可以没有任何问题的为您提供这个服务。

[[mail-domain]]
=== Mail for Your Domain

为了设置一个"邮件主机"(又称邮件服务器) 您必须要把许多邮件发送到与它相连的几个工作站中。 基本上,您想要"要求"在您域的每个主机的所有邮件 (在这个例子里是 `*.FreeBSD.org`) 转向到您的邮件服务器,从而使您的用户可以在主邮件服务器里接收他们的邮件。

要使工作最简单,带有同样 _用户名_ 的帐户应该同时存在于两台机器上。使用 man:adduser[8] 来这样做。

您将使用的邮件主机必须为每个工作站指定一个邮件交换。您可以在 DNS 中这样配置:

[.programlisting]
....
example.FreeBSD.org	A	204.216.27.XX		; Workstation
			MX	10 hub.FreeBSD.org	; Mailhost
....

无论 A 记录指向哪,这将为工作站重新定位到邮件主机。邮件将被发送到 MX 主机。

您不能自己这样做除非您运行着一个 DNS 服务器。 如果不是这样,或者不能运行您自己的 DNS 服务器,告诉您的 ISP 或者给您提供 DNS 服务的人。

如果您正在使用虚拟邮件主机,下面的信息将会对您有用。 在这个例子里,我们假定您有一个客户并且他有自己的域, 这个例子中是 `customer1.org`,您要把 `customer1.org` 所有的邮件发送到您的邮件主机 `mail.myhost.com`。 您的 DNS 记录应该是这样:

[.programlisting]
....
customer1.org		MX	10	mail.myhost.com
....

您 _不_ 需要有个 A 记录, 如果您只为域 `customer1.org` 处理邮件。

[NOTE]
====
必须清楚 `customer1.org` 将不能工作,除非存在一个 A 记录。
====

最后一件您必须要做的事是告诉 sendmail 接受邮件的是什么域和(或)主机名。 这里有好几种方法。下面方法可以任选一种:

* 添加您的主机到 [.filename]#/etc/mail/local-host-names# 文件中,如果您使用的是 `FEATURE(use_cw_file)`。如果您使用 sendmail 8.10 或者更高版本,文件是 [.filename]#/etc/sendmail.cw#。
* 添加一行 `Cwyour.host.com` 到您的 [.filename]#/etc/sendmail.cf# 或 [.filename]#/etc/mail/sendmail.cf# 文件,如果您使用 sendmail 8.10 或者更高版本。

[[SMTP-UUCP]]
== SMTP 与 UUCP

sendmail 的配置,在 FreeBSD 中已经配置好为您的站点直接的连接 Internet。 如果站点希望他们的邮件通过 UUCP 交换,则必须安装其它的 sendmail 配置文件。

手工的配置 [.filename]#/etc/mail/sendmail.cf# 是一个高级主题。sendmail 8 版本通过 man:m4[1] 预处理生成一个配置文件,实际上这个配置发生在一个比较高的抽象层。 man:m4[1] 配置文件可以在 [.filename]#/usr/shared/sendmail/cf# 下找到。 [.filename]#cf# 目录中的 [.filename]#README# 文件是关于 man:m4[1] 配置的基本的介绍。

最好的支持 UUCP 传送的方法是使用 `mailertable` 的特点。建立一个资料库让 sendmail 可以使用它自己的路由决策。

首先,您必须建立您自己的 [.filename]#.mc# 文件。 [.filename]#/usr/shared/sendmail/cf/cf# 目录包含一些例子。 假定您已经命名自己的文件叫做 [.filename]#foo.mc#, 您要做的只是把它转换成一个有效的 [.filename]#sendmail.cf#:

[source,shell]
....
# cd /etc/mail
# make foo.cf
# cp foo.cf /etc/mail/sendmail.cf
....

一个典型的 [.filename]#.mc# 文件看起来可能象这样:

[.programlisting]
....
VERSIONID(`Your version number') OSTYPE(bsd4.4)

FEATURE(accept_unresolvable_domains)
FEATURE(nocanonify)
FEATURE(mailertable, `hash -o /etc/mail/mailertable')

define(`UUCP_RELAY', your.uucp.relay)
define(`UUCP_MAX_SIZE', 200000)
define(`confDONT_PROBE_INTERFACES')

MAILER(local)
MAILER(smtp)
MAILER(uucp)

Cw    your.alias.host.name
Cw    youruucpnodename.UUCP
....

`accept_unresolvable_domains`、 `nocanonify` 和 `confDONT_PROBE_INTERFACES` 特性将避免在传送邮件时使用DNS的机会。`UUCP_RELAY` 项是支持 UUCP 传送所必须的。简单的放入一个 Internet 上可以处理 UUCP 虚拟域地址的主机名。通常,您在这里填入您 ISP 邮件的回复处。

一旦您做完这些,您还需要这个 [.filename]#/etc/mail/mailertable# 文件。 如果您只有一个用来传递所有邮件的对外通道的话, 以下的文件就足够了:

[.programlisting]
....
#
# makemap hash /etc/mail/mailertable.db < /etc/mail/mailertable
.                             uucp-dom:your.uucp.relay
....

一个更复杂点的例子象这样:

[.programlisting]
....
#
# makemap hash /etc/mail/mailertable.db < /etc/mail/mailertable
#
horus.interface-business.de   uucp-dom:horus
.interface-business.de        uucp-dom:if-bus
interface-business.de         uucp-dom:if-bus
.heep.sax.de                  smtp8:%1
horus.UUCP                    uucp-dom:horus
if-bus.UUCP                   uucp-dom:if-bus
.                             uucp-dom:
....

头三行处理域地址邮件,不应该被传送出默认的路由, 而由某些 UUCP 邻居取代的特殊情况,这是为了走"捷径"。 下一行处理本地网的邮件让它可以使用 SMTP 来传送。 最后,UUCP 邻居提起。UUCP 虚拟域的记载, 允许一个 `uucp-neighbor !recipient` 推翻默认规则。最后一行则以一个单独的句点最为结束, 以 UUCP 传送到提供您所有的邮件网关的 UUCP 邻居。 所有在 `uucp-dom:` 关键字里的节点名称必须是有效的 UUCP 邻居,您可以用 `uuname` 去确认。

提醒您这个文件在使用前必须被转换成 DBM 数据库文件。最好在 [.filename]#mailertable# 最上面用注解写出命令行来完成这个工作。 当您每次更换您的 [.filename]#mailertable# 后您总是需要执行这个命令。

最后提示:如果您不确定某个特定的路径可用, 记得把 `-bt` 选项加到 sendmail。这会将 sendmail 启动在 _地址检测模式_。只要按下 `3,0`,接着输入您希望测试的邮件路径位置。 最后一行告诉您使用邮件代理程序, 代理程序会通知目的主机以及 (可能转换) 地址。 要离开此模式请按 kbd:[Ctrl+D]。

[source,shell]
....
% sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
> 3,0 [email protected]
canonify           input: foo @ example . com
...
parse            returns: $# uucp-dom $@ your.uucp.relay $: foo < @ example . com . >
> ^D
....

[[outgoing-only]]
== 只发送邮件的配置

许多时候, 可能只希望通过转发服务器来发送邮件。 典型的情况包括:

* 使用桌面机, 但希望通过类似 man:send-pr[1] 这样的程序发送邮件。 这样就需要使用 ISP 的邮件转发服务器。
* 不在本地处理邮件的服务器, 但它需要把邮件交给转发服务器来进行处理。

几乎任何一个 MTA 都能够胜任这样的工作。 然而不幸的是, 要把一个全功能的 MTA 正确地配置为只把邮件交给其他服务器是一件很困难的事情。 使用 sendmail 以及 postfix 这样的程序, 多少有些杀鸡用牛刀的感觉。

此外, 如果您使用典型的 Internet 访问服务, 您的协议可能会包含禁止运行 "邮件服务器" 的条款。

满足这些需要最简单的办法是安装 package:mail/ssmtp[] port。 以 `root` 身份执行下面的命令:

[source,shell]
....
# cd /usr/ports/mail/ssmtp
# make install replace clean
....

一旦装好, package:mail/ssmtp[] 就可以用四行 [.filename]#/usr/local/etc/ssmtp/ssmtp.conf# 来配置:

[.programlisting]
....
[email protected]
mailhub=mail.example.com
rewriteDomain=example.com
hostname=_HOSTNAME_
....

请确认您为 `root` 使用了真实的电子邮件地址。 用您的 ISP 提供的外发邮件转发服务器名称, 替换掉 `mail.example.com` (某些 ISP 可能将其称为 "外发邮件服务器" 或 "SMTP 服务器")。

接下来需要确认禁用了 sendmail, 包括邮件发出服务在内。 请参见 <<mail-disable-sendmail>> 以了解进一步的细节。

package:mail/ssmtp[] 也提供了一些其他选项。 请参见在 [.filename]#/usr/local/etc/ssmtp# 中的示例配置, 或者 ssmtp 的联机手册来得到一些例子和更多的其他信息。

以这种方式配置 ssmtp, 能够让您计算机上的任何需要发送邮件的软件都正常运转, 而不必冒违反 ISP 的使用政策, 或使您的电脑被劫持用于发送垃圾邮件的风险。

[[SMTP-dialup]]
== 拨号连接时使用邮件传送

如果您有静态的 IP 地址, 就应该不用修改任何默认的配置。 将主机名设置为分配给您的 Internet 名称,其他的事情 sendmail 都会替您做好。

如果您的 IP 地址是动态分配的, 并使用 PPP 连接拨入 Internet, 则您可能会从 ISP 的邮件服务器上得到一个信箱。 这里我们假设您的 ISP 的域名是 `example.net`, 您的用户名是 `user`, 您把自己的机器称作 `bsd.home`, 而您的 ISP 告诉您可以使用 `relay.example.net` 来转发邮件。

为了从邮箱收取邮件, 需要安装一个收信代理。 fetchmail 是一个能够支持许多种不同协议的不错的选择。 这个程序可以通过 package 或 Ports Collection (package:mail/fetchmail[]) 来安装。 通常, 您的 ISP 会提供 POP。 如果您使用用户 PPP,您还可以在 Internet 连接建立时自动地抓取邮件, 这可以通过在 [.filename]#/etc/ppp/ppp.linkup# 中增加如下的项来实现:

[.programlisting]
....
MYADDR:
!bg su user -c fetchmail
....

如果您正使用 sendmail (如下所示) 来为非本地用户传送邮件, 则可能需要让 sendmail 在您的 Internet 连接建立时立即传送邮件队列。 要完成这项工作, 应该把下面的命令放到 [.filename]#/etc/ppp/ppp.linkup# 中的 `fetchmail` 之后

[.programlisting]
....
  !bg su user -c "sendmail -q"
....

假设您在 `bsd.home` 上有一个 `user` 用户。 在 `bsd.home` 上的 `user` 主目录中创建一个 [.filename]#.fetchmailrc# 文件:

[.programlisting]
....
poll example.net protocol pop3 fetchall pass MySecret
....

因为包含了密码 `MySecret`, 这个文件应该只有 `user` 可读。

要使用正确的 `from:` 头来发送文件, 您必须告诉 sendmail 使用 mailto:[email protected][[email protected]] 而不是i mailto:[email protected][[email protected]]。 另外, 您可能也需要要求 sendmail 通过 `relay.example.net` 来发送邮件, 以便更快地传送它们。

以下的 [.filename]#.mc# 文件应该可以满足您的需求:

[.programlisting]
....
VERSIONID(`bsd.home.mc version 1.0')
OSTYPE(bsd4.4)dnl
FEATURE(nouucp)dnl
MAILER(local)dnl
MAILER(smtp)dnl
Cwlocalhost
Cwbsd.home
MASQUERADE_AS(`example.net')dnl
FEATURE(allmasquerade)dnl
FEATURE(masquerade_envelope)dnl
FEATURE(nocanonify)dnl
FEATURE(nodns)dnl
define(`SMART_HOST', `relay.example.net')
Dmbsd.home
define(`confDOMAIN_NAME',`bsd.home')dnl
define(`confDELIVERY_MODE',`deferred')dnl
....

如何转换这个 [.filename]#.mc# 文件到 [.filename]#sendmail.cf# 文件的细节,请参考前面的章节。 另外,在更新 [.filename]#sendmail.cf# 文件后, 不要忘记重启 sendmail。

[[SMTP-Auth]]
== SMTP 验证

在您的邮件服务器上启用 SMTP 验证有很多好处。 SMTP 验证可以让 sendmail 多一重安全保障, 而且也使得使用不同机器的漫游用户能够使用同一个邮件服务器, 而不需要每次都修改它们的邮件客户端配置。

[.procedure]
====

. 从 ports 安装 package:security/cyrus-sasl2[]。 这个 port 位于 package:security/cyrus-sasl2[]。 package:security/cyrus-sasl2[] port 支持很多可以在编译时指定的可选项。 由于我们要使用 SMTP 身份验证, 因此要确认没有禁用 `LOGIN` 选项。
. 安装完 package:security/cyrus-sasl2[] 之后, 编辑 [.filename]#/usr/local/lib/sasl2/Sendmail.conf# (如果不存在则建立一个) 并在其中增加下列配置:
+
[.programlisting]
....
pwcheck_method: saslauthd
....
+
. 接下来, 安装 package:security/cyrus-sasl2-saslauthd[], 编辑 [.filename]#/etc/rc.conf# 并加入下列配置:
+
[.programlisting]
....
saslauthd_enable="YES"
....
+ 
最后启用 saslauthd 服务:
+
[source,shell]
....
# /usr/local/etc/rc.d/saslauthd start
....
+ 
这个服务将充当 sendmail 使用 FreeBSD 的 [.filename]#passwd# 数据库来完成身份验证时的代理人角色。 这避免了为每个需要使用 SMTP 身份验证的用户建立对应的用户名和口令的麻烦, 也确保了登录与邮件的口令一致。
. 现在编辑 [.filename]#/etc/make.conf# 文件,添加如下行:
+
[.programlisting]
....
SENDMAIL_CFLAGS=-I/usr/local/include/sasl -DSASL
SENDMAIL_LDFLAGS=-L/usr/local/lib
SENDMAIL_LDADD=-lsasl2
....
+ 
这些配置将告诉系统在联编 sendmail 时使用适当的配置选项来在编译过程中连入 package:cyrus-sasl2[]. 在重新编译 sendmail 之前, 请确认已经安装了 package:cyrus-sasl2[]。
. 重新编译 sendmail 运行如下命令:
+
[source,shell]
....
# cd /usr/src/lib/libsmutil
# make cleandir && make obj && make
# cd /usr/src/lib/libsm
# make cleandir && make obj && make
# cd /usr/src/usr.sbin/sendmail
# make cleandir && make obj && make && make install
....
+ 
如果 [.filename]#/usr/src# 和共享库没有大的变化并且它们都必须可用,sendmail 编译应该没有任何问题。
. sendmail 被重新编译和安装后, 编辑您的 [.filename]#/etc/mail/freebsd.mc# 文件 (或者无论您选择使用的您的哪个 [.filename]#.mc# 文件。许多管理员选择使用跟 man:hostname[1] 一样的唯一的 [.filename]#.mc# 文件输出)。添加这些行在这个文件:
+
[.programlisting]
....
dnl set SASL options
TRUST_AUTH_MECH(`GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN')dnl
define(`confAUTH_MECHANISMS', `GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN')dnl
....
+ 
这些选项配置有不同的方法,对于 sendmail 验证用户。 如果您想要使用除 pwcheck 之外的方法,请参考相关文档。
. 最后,在 [.filename]##/etc/mail## 运行 man:make[1]。 它将建立您的新 [.filename]##.mc## 文件并建立一个 [.filename]##.cf## 文件命名为 [.filename]##freebsd.cf## (或者您想使用您的其它名字的 [.filename]##.mc##文件)。接着使用命令 `make install restart`,这将复制文件到 [.filename]##sendmail.cf##,并且正确的重新启动 sendmail。 更多有关这个过程的信息,您可以参考 [.filename]##/etc/mail/Makefile## 文件。
====

如果所每个步骤都做对了, 您应该可以通过您的邮件客户端进入您的登录信息并且传送一个测试信息。 更多的分析,设置 sendmail 的 `LogLevel` 到 13 并且查看 [.filename]#/var/log/maillog# 中的信息。

如欲了解更多的信息, 请参看 sendmail 网站上的 http://www.sendmail.org/~ca/email/auth.html[ 关于 SMTP 验证] 的介绍。

[[mail-agents]]
== 邮件用户代理

邮件用户代理 (MUA) 是一个用于收发邮件的应用程序。 更进一步, 随着电子邮件的 "演化" 并愈发复杂, MUA 在和电子邮件相结合方面变得日趋强大; 这为用户提供了更多的功能和灵活性。 FreeBSD 包含了对于众多邮件用户代理的支持, 所有这些都可以通过 crossref:ports[ports,FreeBSD Ports Collection] 来轻松安装。 用户可以选择类似 evolution 以及 balsa 这样的图形界面程序, 也可以选择类似 mutt、 alpine 或 `mail` 这样的控制台程序, 或者某些大型机构使用的 web 界面。

[[mail-command]]
=== mail

man:mail[1] 是 FreeBSD 中默认的邮件用户代理 (MUA)。 它是一个基于控制台的 MUA, 提供了所有用于收发文本形式的电子邮件所需的基本功能, 虽然它处理附件的能力有限, 而且只支持本地的信箱。

虽然 `mail` 没有内建的 POP 或 IMAP 服务器支持, 然而这些信箱可以通过类似 fetchmail 这样的应用程序, 来下载到本地的 [.filename]#mbox# 文件中。 这一应用程序在本章的稍后部分 (<<mail-fetchmail>>) 进行了介绍。

要收发邮件, 只需简单地使用 `mail` 命令, 如下所示:

[source,shell]
....
% mail
....

用户保存在 [.filename]#/var/mail# 中的信箱的内容会被 `mail` 程序自动地读取。 如果信箱是空的, 程序会退出并给出一个消息表示没有邮件。 一旦读完了信箱, 将启动应用程序的界面, 并列出邮件。 所有的邮件会被自动编号, 类似下面的样子:

[source,shell]
....
Mail version 8.1 6/6/93.  Type ? for help.
"/var/mail/marcs": 3 messages 3 new
>N  1 root@localhost        Mon Mar  8 14:05  14/510   "test"
 N  2 root@localhost        Mon Mar  8 14:05  14/509   "user account"
 N  3 root@localhost        Mon Mar  8 14:05  14/509   "sample"
....

现在, 您通过使用 `mail` 的 kbd:[t] 命令, 并给出邮件的编号, 就可以看到邮件了。 在这个例子中, 我们将阅读第一封邮件:

[source,shell]
....
& t 1
Message 1:
From root@localhost  Mon Mar  8 14:05:52 2004
X-Original-To: marcs@localhost
Delivered-To: marcs@localhost
To: marcs@localhost
Subject: test
Date: Mon,  8 Mar 2004 14:05:52 +0200 (SAST)
From: root@localhost (Charlie Root)

This is a test message, please reply if you receive it.
....

正如在上面的例子中所看到的, kbd:[t] 键将显示完整的邮件头。 要再次查看邮件的列表, 可以使用 kbd:[h] 键。

如果需要回复邮件, 也可以使用 ``mail`` 来完成, 方法是使用 kbd:[R] 或 kbd:[r] 这两个 ``mail``键。 kbd:[R] 键会要求 ``mail`` 只回复发送邮件的人, 而 kbd:[r] 不仅回复发送邮件的人, 而且也会将回复抄送给原来邮件的其他接收者。 如果需要, 也可以在这些命令后面指定邮件的编号。 做完这些之后, 就可以输入回复了, 在邮件的最后应该有一个只有一个 kbd:[.] 的行, 例如:

[source,shell]
....
& R 1
To: root@localhost
Subject: Re: test

Thank you, I did get your email.
.
EOT
....

要发出新邮件, 可以使用 kbd:[m], 后面接收件人的邮件地址。 多个收件人之间, 应该使用 kbd:[,] 隔开。 接下来需要输入邮件的主题, 然后是正文。 同样的, 在邮件最后需要一个只有 kbd:[.] 的空行表示结束。

[source,shell]
....
& mail root@localhost
Subject: I mastered mail

Now I can send and receive email using mail ... :)
.
EOT
....

在 `mail` 工具中, 可以用 kbd:[?] 来显示帮助, 而参考 man:mail[1] 联机手册则可以获得更多关于 `mail` 的帮助信息。

[NOTE]
====
正如前面所提到的那样, man:mail[1] 命令在设计时没有考虑到要处理附件, 因而在这方面他的功能很弱。 新的 MUA, 如 mutt, 能够更好地处理附件。 但如果您仍然希望使用 `mail` 命令, 那么 package:converters/mpack[] port 则是一个值得考虑的附加工具。
====

[[mutt-command]]
=== mutt

mutt 是一个短小精悍的邮件用户代理, 它提供了许多卓越的功能, 包括:

* 能够按线索阅读邮件;
* 支持使用 PGP 对邮件进行数字签名和加密;
* 支持 MIME;
* 支持 Maildir;
* 高度可定制。

所有这些特性, 都使得 mutt 得以跻身于目前最先进的邮件用户代理的行列。 请参考 http://www.mutt.org[http://www.mutt.org] 以了解更多关于 mutt 的资料。

稳定版本的 mutt 可以通过 package:mail/mutt[] port 来安装, 而开发版本, 则可以通过使用 package:mail/mutt-devel[] port 安装。 通过 port 安装之后,可以通过下面的命令来启动 mutt:

[source,shell]
....
% mutt
....

mutt 会自动读取 [.filename]#/var/mail# 中的用户信箱, 并显示其内容。 如果用户信箱中没有邮件, 则 mutt 将等待来自用户的命令。 下面的例子展示了 mutt 列出邮件的情形:

image::mutt1.png[]

要阅读邮件, 只需用光标键选择它, 然后按 kbd:[Enter] 键。 以下是 mutt 显示邮件的例子:

image::mutt2.png[]

和 man:mail[1] 类似, mutt 允许用户只回复发件人, 或者回复所有人。 如果只想回复发信人, 使用 kbd:[r] 快捷键。 要回复所有人 (group reply), 可以用 kbd:[g] 快捷键。

[NOTE]
====
mutt 会使用 man:vi[1] 命令作为编辑器, 用于创建和回复邮件。 这一行为可以通过建立用户自己的 [.filename]#.muttrc# 文件来订制, 方法是修改 `editor` 变量或配置 `EDITOR` 环境变量。 请参见 http://www.mutt.org/[http://www.mutt.org/] 以了解配置 mutt 的进一步信息。
====

要撰写新邮件, 需要首先按 kbd:[m]。 在输入了有效的邮件主题之后, mutt 将启动 man:vi[1], 您可以在其中撰写邮件。 写好邮件的内容之后, 存盘并退出 `vi`, 则 mutt 将继续, 并显示一些关于将发出的邮件的摘要信息。 要发送邮件, 只需按 kbd:[y]。 下面给出了摘要信息的一个例子:

image::mutt3.png[]

mutt 也提供了相当详尽的帮助, 在绝大多数菜单中, 都可以使用 kbd:[?] 键将其呼出。 屏幕顶行中也会给出常用的快捷键。

[[alpine-command]]
=== alpine

alpine 主要是针对初学者设计的, 但也提供了一些高级功能。

[WARNING]
====

过去, alpine 软件被发现有许多远程漏洞, 这些漏洞会允许远程的攻击者在用户的本地系统上, 通过发送精心炮制的邮件来执行任意的代码。 所有的 _已知_ 问题都已经被修正了, 但 alpine 的代码是以很不安全的风格编写的, 并且 FreeBSD 安全官相信仍然有一些尚未被发现的安全漏洞。 您应当考虑并承担安装 alpine 可能带来的风险。
====

最新版本的 alpine 可以通过使用 package:mail/alpine[] port 来安装。 装好之后, alpine 可以通过下面的命令启动:

[source,shell]
....
% alpine
....

第一次启动 alpine 时, 它会显示出一个欢迎页, 并给出简要的介绍, 以及 alpine 开发小组要求用户匿名发送一封邮件, 以便帮助他们了解有多少用户在使用他们开发的客户程序的请求。 要发送这封匿名的邮件, 请按 kbd:[Enter], 您也可以按 kbd:[E] 退出, 而不发送匿名邮件。 下面是欢迎页的一个例子:

image::pine1.png[]

接下来展现给用户的将是主菜单, 可以很容易地通过光标键在上面进行选择。 这个主菜单提供了用于撰写新邮件、 浏览邮件目录, 甚至管理地址簿等等的快捷方式。 主菜单下面是完成各种功能的快捷键说明。

由 alpine 打开的默认目录是 [.filename]#inbox#。 要查看邮件索引, 应按 kbd:[I], 或选择下面所示的 [.guimenuitem]#MESSAGE INDEX# 选项:

image::pine2.png[]

邮件索引展示了当前目录下的邮件, 可以使用光标键翻阅。 按 kbd:[Enter] 键阅读高亮选定的邮件。

image::pine3.png[]

在上面的截屏中, 使用 alpine 显示了一封示例邮件。 在屏幕底部也显示了快捷键供参考。 其中的一个例子是 kbd:[r] 键, 它告诉 MUA 回复正显示的邮件。

image::pine4.png[]

在 alpine 中回复邮件, 是通过 pico 编辑器完成的, 后者默认情况下会随 alpine 一起安装。 而 pico 工具使得浏览邮件变得更加简单, 并且要比 man:vi[1] 或 man:mail[1] 更能容忍误操作。 回复写好之后, 可以用 kbd:[Ctrl+X] 来发出它。 此前, alpine 程序会要求确认。

image::pine5.png[]

alpine 程序可以通过使用主菜单中的 [.guimenuitem]#SETUP# 选项来进行定制。 请参考 http://www.washington.edu/alpine/[http://www.washington.edu/alpine/] 来了解更多信息。

[[mail-fetchmail]]
== 使用 fetchmail

fetchmail 是一个全功能的 IMAP 和 POP 客户程序, 它允许用户自动地从远程的 IMAP 和 POP 服务器上下载邮件, 并保存到本地的信箱中; 这样, 访问这些邮件就变得更方便了。 fetchmail 可以通过 package:mail/fetchmail[] port 安装, 它提供了许多有用的功能, 其中包括:

* 支持 POP3、 APOP、 KPOP、 IMAP、 ETRN 以及 ODMR 协议。
* 通过 SMTP 转发邮件, 这使得过滤、 转发, 以及邮件别名能够正常工作。
* 能够以服务程序的方式运行, 并周期性地检查邮件。
* 能够从多个信箱收取邮件, 并根据配置, 将这些邮件转发给不同的本地用户。

尽管介绍全部 fetchmail 的功能超出了本书的范围, 但这里仍然介绍了其基本的功能。 fetchmail 工具需要一个名为 [.filename]#.fetchmailrc# 的配置文件才能正常工作。 这个文件中包含了服务器信息, 以及登录使用的凭据。 由于这个文件包含敏感内容, 建议将其设置为只有属主所有, 使用下面的命令:

[source,shell]
....
% chmod 600 .fetchmailrc
....

下面的 [.filename]#.fetchmailrc# 提供了一个将某一用户的信箱通过 POP 下载到本地的例子。 它告诉 fetchmail 连接到 `example.com`, 并使用用户名 `joesoap` 和口令 `XXX`。 这个例子假定 `joesoap` 同时也是本地的系统用户。

[.programlisting]
....
poll example.com protocol pop3 username "joesoap" password "XXX"
....

下一个例子将连接多个 POP 和 IMAP 服务器, 并根据需要转到不同的本地用户:

[.programlisting]
....
poll example.com proto pop3:
user "joesoap", with password "XXX", is "jsoap" here;
user "andrea", with password "XXXX";
poll example2.net proto imap:
user "john", with password "XXXXX", is "myth" here;
....

另外, fetchmail 也可以通过指定 `-d` 参数, 并给出 fetchmail 在轮询 [.filename]#.fetchmailrc# 文件中列出的服务器的时间间隔, 来以服务程序的方式运行。 下面的例子会让 fetchmail 每 600 秒轮询一次:

[source,shell]
....
% fetchmail -d 600
....

更多关于 fetchmail 的资料, 可以在 http://fetchmail.berlios.de/[http://fetchmail.berlios.de/] 找到。

[[mail-procmail]]
== 使用 procmail

procmail 是一个强大得惊人的过滤进入邮件的应用程序。 它允许用户定义 "规则", 并用这些规则来匹配进入的邮件, 进而执行某些特定的功能, 或将这些邮件转发到其他信箱和/或邮件地址。 procmail 可以通过 package:mail/procmail[] port 来安装。 装好之后, 可以直接把它集成到绝大多数 MTA 中; 请参考您使用的 MTA 的文档了解具体的作法。 另外, procmail 可允许通过把下面的设置加入到用户主目录中的 [.filename]#.forward# 文件中, 来启用 procmail 功能:

[.programlisting]
....
"|exec /usr/local/bin/procmail || exit 75"
....

接下来我们将介绍一些基本的 procmail 规则, 以及它们都是做什么的。 各种各样的规则, 都应该写到 [.filename]#.procmailrc# 文件中, 而这个文件则必须放在用户的主目录下。

主要的规则, 也可以在 man:procmailex[5] 联机手册中找到。

将所有来自 mailto:[email protected][[email protected]] 的邮件, 转发到外部地址 mailto:[email protected][[email protected]]:

[.programlisting]
....
:0
* ^From.*[email protected]
! [email protected]
....

转发所有不超过 1000 字节的邮件到外部地址 mailto:[email protected][[email protected]]:

[.programlisting]
....
:0
* < 1000
! [email protected]
....

把所有发送到 mailto:[email protected][[email protected]] 的邮件放到信箱 [.filename]#alternate# 中:

[.programlisting]
....
:0
* ^[email protected]
alternate
....

将所有标题为 "Spam" 的邮件发到 [.filename]#/dev/null#:

[.programlisting]
....
:0
^Subject:.*Spam
/dev/null
....

将收到的所有 `FreeBSD.org` 邮件列表的邮件, 转发到各自的信箱:

[.programlisting]
....
:0
* ^Sender:.owner-freebsd-\/[^@][email protected]
{
	LISTNAME=${MATCH}
	:0
	* LISTNAME??^\/[^@]+
	FreeBSD-${MATCH}
}
....