Chapter 11. 邮件和新闻群组

Table of Contents
11.1. sendmail
11.2. fetchmail
11.3. 使用 mutt 读取及撰写邮件
11.4. 接收邮件的策略
11.5. 寄送邮件的策略
11.6. 进阶的邮件工具
11.7. 新闻和 tin

这一章解释了如何设定 NetBSD 来使用邮件和新闻。只描述一个简单 且非常共通的设定:一台主机利用调制解调器,经由网络服务的提供者,连接到 Internet 的相关设定:可以把这一章当成 Chapter 9 的 延伸,假设为一个相似的网络设定。 如果你不知道从何处着手或者你只有读过导论或技术性的文件,这个 "简单的"设定甚至是有些困难的;事实上,你将注意到一些详细的 说明将会是一个挑战(例如,将你的内部网络名称对映到"真实的" 名称需要 sendmail 的相关知识。) 关于一般邮件和新闻的叙述已经超过这本指导手册的范围;请去找一本 不错的 Unix 管理书籍(一些非常好的书目被列在 NetBSD 网站上。) 这个问题在实际上是非常复杂的,因为有许多种可能的设定和联机方式,所以 问题的造成并不只是在单一方面:你需要正确地检查数个相互合作组件的设定。

这一章也摘要地描述两个常用的应用程序的设定(并不包括使用方法), mutt 适用在邮件上而 tin 则用于新闻。没有描述使用方法是 因为它们易于使用并有完整的文件说明。 很明显地,mutt 和 tin 并不是最主要的选择:仍存在许多其它相似的应用 程序,但我认为它们是一个好的起始点,因为它们被广泛地使用,简单, 运作得不错而并不使用太大的硬盘空间和内存。 两者皆是终端机模式的程序;如果你喜欢图形化的应用程序,也有许多关于 X 的选择。

简单来说,在这一章里,关于设定所需提及的程序为:

在此当中,只有 sendmail 和 m4 被依附在基本系统里安装了;你可以 从 package 集合中,安装其它的程序。

在继续以前,请记得不是在这章提到的程序都是必要的:有许多其它的应用 程序能执行相似的工作,而其它人也比较偏好它们。你可以参阅 mailing lists 以发现其它不同的选择。 你也可以使用其它不同的方式来寄送和接收邮件:在此所解释的只是一个 起始点;当你了解它是如何运作时,你可能会想要修改它以符合你的需求, 或是采用不同的方式。

也有与此章范例非常不同的方法,就是使用像是 Netscape Communicator 的应用程序,可以为你做任何事而不需要 设定许多组件:利用 Communicator,你可以浏览 Internet,寄送和接收 邮件并阅读新闻群组。此外,它的设定也是非常的简单。 必须付出的代价是:Communicator 是一个"封闭"的程序而不能 和其它标准的 Unix 工具相配合。

另一个方式是使用 emacs 来读取邮件和 新闻群组。Emacs 不需要介绍给 Unix 的使用者,但在此假设你并不知道, 它是一个具有弹性的编辑器(虽然称 emacs 为编辑器会有些贬抑的意谓)并 可以成为一个完整的工作环境,而可以被用以读取邮件,新闻群组和执行 许多的作业。对许多人而言,emacs 是他们唯一需要的环境,并用它来完成 工作。关于如何设定 emacs 来阅读邮件和新闻群组,在 emacs 的手册中 有详细的描述。

在这一章剩余的部份,我们将处理一台主机藉由调制解调器利用 PPP 连接 到 Internet。

一些基本的术语:

MUA (mail user agent)

用来阅读和撰写邮件的程序。 例如:muttelmpine 而简单如被安装在基本系统上的 mail 程序也是。

MTA (mail transfer agent)

在两台主机之间或同一台主机上,用来传送邮件的程序。 MTA 决定了邮件到达目的地的路径。 在 BSD 系统上(并不只是),标准的 MTA 是 sendmail

MDA (mail delivery agent)

通常和 MTA 一起使用,用来递送邮件的程序;例如,实际地 将邮件放入收件者的信箱中。例如,sendmail 使用一个或多个 MDA 来递送邮件。

Figure 11-1 描述我们想要设定的邮件系统。 在局域网络之间(或单一主机上)和 ISP 与调制解调器的 PPP 联机。 具有粗边的"泡泡"是使用者手动执行的程序;其余的 泡泡则是被自动执行的程序。 整个循环中的号码是关于邮件循环的逻辑步骤:

  1. 在步骤 (1) 中,使用 fetchmail 从 ISP 的 POP 服务器上下载邮件,并使用 sendmail 将这些邮件放入 使用者的信箱中。

  2. 在步骤 (2) 中,使用者执行 mutt(或另一个 MUA)来读取邮件, 回复或撰写新邮件。

  3. 在步骤 (3) 中,使用者在 mutt 中"寄送"邮件。 邮件被存放在队列区。

  4. 在步骤 (4) 中,使用者利用 sendmail 将将邮件传送至 SMTP 服务器上,而它将会递送这些邮件到 最终的目的地(可能会经由其它的邮件服务器。) ISP 的 SMTP 服务器扮演中继的角色。

联机到 ISP 的话,最多只需要步骤 (1) 到步骤 (4);其余的步骤是不需 要的。

Figure 11-1. 邮件系统的架构

11.1. sendmail

当一个 MTA,即在预设安装中的 sendmail,在递送邮件时,如果它是 区域的邮件,便会被直接地递送。如果邮件要送往不同的网域,MTA 必须找出该网域中,邮件服务器的位置。Sendmail 使用 DNS 服务 (描述在 linkend="chap-dns">中)来寻找需要的位置(被 DNS 服务器 纪录在 MX 中)并递送邮件到目的邮件服务器。

BSD 的世界里,最常使用的 MTA 可能是 sendmail。Sendmail 是由一群 设定文件和数据库所控制的,其中以 /etc/mail/sendmail.cf 最为重要。一般来说, 如果你不是专家,那最好不要去直接地修改 /etc/mail/sendmail.cf 檔;取而代之的是, 使用一群预先定义好的宏和 m4 预处理器, 可以大大地(几乎是完善的)简化我们的设定。

Note: 在 NetBSD 1.5 之前的版本,邮件的设定档在 /etc 中,而不是在 /etc/mail

在使用宏时,sendmail 的设定将是易于了解的,而下一段只描述了 一个可以被修改以适合不同需求和不同设定的范例。如果你经由调制解调器 连接到 Internet,则此设定文件的样本将可适合你的需求:只要置换一些 相关的数据即可。

首先要解决的问题是区域的网络,我们要处理的是内部的网络,例如, 不能从 Internet 上直接存取的。这表示在内部所使用的名称在 Internet 上是没有意义的;简单来说,"ape.insetti.net" 不能被任何外部的 主机连上:没有人可以回复邮件到这个地址(一些邮件系统甚至会拒绝这些 邮件,因为来自一台未知的主机。) 真实的地址,即可被任何人连得上的,是被 ISP 所指派的,因此,我们必须 将区域的地址 "[email protected]" 转换成实际的地址 "[email protected]"。 如果设定正确的话,Sendmail 将会在传送邮件时,注意这项信息。

为了将 e-mail 寄到 ISP 的邮件服务器,你可能想要设定 sendmail,使它成为一个 中继站。在此章描写的设定中,sendmail 不能 直接地接触收件者的邮件服务器(像先前所提到的),而中继所有邮件到 ISP 的邮件服务器。

Note: ISP 的邮件服务器扮演一台中继站,这表示 它不会直接地送到邮件所在的网域,而是另一台邮件服务器。它是两台 服务器之间的媒介。

因为我们并不会与 ISP 一直保持联机,所以没有必要启动 sendmail 成为 常驻程序:在 /etc/rc.conf 中,你可以使用这一 行来关掉它。因此,当我们想要传送邮件到邮件服务器时,必须手动地 执行 sendmail。区域的邮件仍会正常运作,甚至 sendmail 没有被启动 为常驻程序。

让我们开始设定 sendmail。

11.1.1. 使用 genericstable

这一类的设定是使用 /etc/mail/genericstable 档,被 sendmail 用来对映并重写内部的主机名称。

第一步即是撰写 genericstable 档。例如:

carlo:         [email protected]
root:          [email protected]
news:          [email protected]
      

为了使其生效,genericstable 必须用以下的指令翻译:

# /usr/sbin/sendmail -bi -oA/etc/mail/genericstable
      

现在可以建立设定档的雏型了,可以用来建立 sendmail 的设定档。

# cd /usr/share/sendmail/m4
      

我们称新的 sendmail 设定档为 mycf.mc, 其内容为:

divert(-1)dnl
include(`../m4/cf.m4')dnl
VERSIONID(`mycf.mc created by [email protected] May 18 2001')dnl
OSTYPE(bsd4.4)dnl

dnl # Settings for masquerading.  Addresses of the following types
dnl # are rewritten
dnl #     [email protected]
dnl #     carlo@ape
GENERICS_DOMAIN(ape.insetti.net ape)dnl
FEATURE(genericstable)dnl
FEATURE(masquerade_envelope)dnl

define(`SMART_HOST',`mail.bignet.it')dnl

FEATURE(redirect)dnl
FEATURE(nocanonify)dnl

dnl # The following feature is useful if sendmail is called by
dnl # fetchmail (which is usually the case.)  If sendmail cannot
dnl # resolve the name of the sender, the mail will not be delivered.
dnl # For example:
dnl #	MAIL FROM:<[email protected]> SIZE=2718
dnl #	501 <[email protected]>... Sender domain must exist
FEATURE(`accept_unresolvable_domains')dnl

dnl # accept_unqualified_senders is useful with some MUA, which send
dnl # mail as, for example:
dnl #	MAIL FROM:<carlo>
FEATURE(`accept_unqualified_senders')dnl

dnl # Mail for `smtp' mailer is marked `expensive' (`e' flag):
dnl # instead of connecting with the relay, sendmail puts it in
dnl # a queue for delayed processing.
dnl # Sendmail starts complaining about undelivered messages after
dnl # 16 hours.
define(`SMTP_MAILER_FLAGS',`e')dnl
define(`confCON_EXPENSIVE',`True')dnl
define(`confTO_QUEUEWARN', `16h')dnl

dnl # For european users
define(`confDEF_CHAR_SET',`ISO-8859-1')dnl

dnl # Enable the following three lines to use procmail as a local
dnl # delivery agent.  The third line is optional, only the first
dnl # two are required.
dnl # define(`PROCMAIL_MAILER_PATH', /usr/pkg/bin/procmail)dnl
dnl # FEATURE(local_procmail)dnl
dnl # MAILER(procmail)dnl

dnl # The following two mailers must always be defined
MAILER(local)dnl
MAILER(smtp)dnl
      

Note: 在前例中,在 "dnl" 之后的叙述被认为是批注而 将会被 m4 预处理器舍弃。

这个设定告诉 sendmail 去重写 "ape.insetti.net" 的地址, 使用存在于 /etc/mail/genericstable 档中 的真实名称。我们也可以说,邮件必须被寄往 "mail.bignet.it" 服务器。各选项的详细意义,在 /usr/share/sendmail/README 有所描述。

为了建立你所需的设定文件范例,你只必须置换这两行成实际的数据:

GENERICS_DOMAIN(ape.insetti.net ape)dnl
define(`SMART_HOST',`mail.bignet.it')dnl
      

最后,在储存先前的版本后,必须产生新的设定档:

# cp /etc/mail/sendmail.cf /etc/mail/sendmail.cf.bak
# m4 mycf.mc > /etc/mail/sendmail.cf
      

Note: /usr/share/sendmail/cf 目录中, netbsd-proto.mc 是被用做建立预设的 /etc/mail/sendmail.cf,此档是与 NetBSD 一齐发行的。可使用 make 指令重建它。

另一个重要的档案是 /etc/mail/aliases,它可以 保持原先的设定,但仍必须执行以下指令:

# newaliases
      

现在一切准备就绪,可以开始寄送邮件了。

11.1.2. 测试设定

在完成 Sendmail 最后的设定之后,可以开始运作了,但在寄送实际 的邮件以前,最好执行一些简单的测试。 首先,让我们试着寄送区域的邮件:

$ sendmail -v carlo
Subject: test

Prova
.
carlo... Connecting to local...
carlo... Sent
      

请严格地遵从上述的范例:在 Subject 之后保留一个空格符: 在邮件的最后则包含只有一点的一行。 现在你应该可以使用 mail 程序读取邮件并确认 From: 部份被 正确地改写。

From: [email protected]
      

接着,你可以直接使用 sendmail 确认地址的改写,使用 -bt 选项进行测试。 这个模式会显示 sendmail 对于一个地址的运作过程,并解析它 如何根据设定文件中的规则改写地址。 也可以执行其它的测试并观看一些信息。

$ sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
>
      

可以使用 '?' 命令展示求助讯息。

首先,让我们确认 generictable 对映档可以正确地工作:

/map generics carlo
map_lookup: generics (carlo) returns [email protected]      

一切正常;sendmail 找到区域的名称,并实际地符合在对映档中的部份。

现在我们可以测试寄信者地址的改写,使用以下指令:

/tryflags ES
/try smtp [email protected]
      

结果应该类似这样:

Trying envelope sender address [email protected] for mailer smtp
rewrite: ruleset   3   input: carlo @ ape . insetti . net
rewrite: ruleset  96   input: carlo < @ ape . insetti . net >
rewrite: ruleset  96 returns: carlo < @ ape . insetti . net . >
rewrite: ruleset   3 returns: carlo < @ ape . insetti . net . >
rewrite: ruleset   1   input: carlo < @ ape . insetti . net . >
rewrite: ruleset   1 returns: carlo < @ ape . insetti . net . >
rewrite: ruleset  11   input: carlo < @ ape . insetti . net . >
rewrite: ruleset  51   input: carlo < @ ape . insetti . net . >
rewrite: ruleset  51 returns: carlo < @ ape . insetti . net . >
rewrite: ruleset  61   input: carlo < @ ape . insetti . net . >
rewrite: ruleset  61 returns: carlo < @ ape . insetti . net . >
rewrite: ruleset  94   input: carlo < @ ape . insetti . net . >
rewrite: ruleset  93   input: carlo < @ ape . insetti . net . >
rewrite: ruleset   3   input: alan @ bignet . it
rewrite: ruleset  96   input: alan < @ bignet . it >
rewrite: ruleset  96 returns: alan < @ bignet . it >
rewrite: ruleset   3 returns: alan < @ bignet . it >
rewrite: ruleset  93 returns: alan < @ bignet . it >
rewrite: ruleset  94 returns: alan < @ bignet . it >
rewrite: ruleset  11 returns: alan < @ bignet . it >
rewrite: ruleset   4   input: alan < @ bignet . it >
rewrite: ruleset   4 returns: alan @ bignet . it
Rcode = 0, addr = [email protected]
>
      

如你所见,当你的 e-mail 离开系统时,区域的地址已经被改写为 真实的地址了。

你可以使用以下指令获得相似的结果:

/try smtp carlo
      

我们可以使用以下指令确认寄信者的改写:

/tryflags HS
/try smtp [email protected]
      

11.1.3. 使用其它的 MTA

自 NetBSD 1.4 以后,sendmail 不会被自动地执行:

$ ls -l /usr/sbin/sendmail
lrwxr-xr-x  1 root  wheel  21 Nov  1 01:14 /usr/sbin/sendmail@ -> /usr/sbin/mailwrapper
      

mailwrapper 的目的是允许使用其它的 MTA(例如,postfix)取代 sendmail。如果你计划使用不同的寄送程序,我建议你参阅 mailwrapper(8) 和 mailer.conf(5) 在线手册,可以帮助了解。

11.2. fetchmail

邮件被 ISP 所接收而不能被自动地传送到区域的主机上;因此,我们必须 下载它。 Fetchmail 是一个受欢迎的程序,它可以从 远程的服务器上下载邮件并导入区域的递送系统(通常使用 sendmail。) 它是强大且易于使用和设定的:在安装之后, ~/.fetchmailrc 档必须被建立 (~/.fetchmailrc 包含了一个密码,所以它需要 适当的权限。)

这是 .fetchmailrc 的范例:

poll mail.bignet.it
protocol POP3
username alan there with password pZY9o is carlo here
flush
mda "/usr/sbin/sendmail -oem %T"
    

Note: 最后一行 ("mda ...") 只有在 sendmail 不是常驻的时候 被使用。 请注意,邮件服务器 (mail.bignet.it) 并不需要和 sendmail 所 使用的中继站相同。

现在使用以下指令下载并递送邮件到区域的系统:

$ fetchmail
    

可以使用 mutt 读取邮件了。

11.3. 使用 mutt 读取及撰写邮件

Mutt 是一个最受欢迎的邮件程序:它是 一个"轻量级的",易于使用的程序,并具有许多特征。 mutt 的在线手册非常的简略;实际的文件 为 manual.txt,位于 /usr/pkg/share/doc/mutt/ 中。

Mutt 的设定被定义在 ~/.muttrc 檔。最简单的 建立方法是复制一份 mutt 的 muttrc 样本文件(通常是 /usr/pkg/etc/Muttrc)到家目录中并修改它。 以下的范例指示如何使用一些功能:

set copy=yes
set edit_headers
set folder="~/Mail"
unset force_name
set mbox="~/Mail/incoming"
set record="~/Mail/outgoing"
unset save_name

bind pager <up> previous-page
bind pager <down> next-page

color normal white black
color hdrdefault blue black
color indicator white blue
color markers red black
color quoted cyan black
color status white blue
color error red white
color underline yellow black

mono quoted standout
mono hdrdefault underline
mono indicator underline
mono status bold

alias pippo Pippo Verdi <[email protected]>
    

启动 mutt:

$ mutt
    

Note: Mutt 是支持彩色的,但它依赖终端机的设定。在 X 下,你可以使用 xterm-color;例如:

TERM=xterm-color mutt
	

11.4. 接收邮件的策略

这一段描述一个简单的方法来接收和读取邮件。 只有在下载邮件时,才需要连接到 ISP;邮件可以离线阅读。

  1. 连接到 ISP。

  2. 执行 fetchmail

  3. 中断联机。

  4. 使用 mutt 读取邮件。

11.5. 寄送邮件的策略

当使用 mutt 撰写完邮件并"寄出"后, 邮件必须使用 sendmail 传送到邮件服务器。 在 mutt 中使用 y 命令 寄出邮件,但它并不会被真的寄出;邮件被存放在队列区中;如果 sendmail 没有常驻,我们需要手动地启动它, 否则,邮件仍会被存放在硬盘上。 必要的步骤如下:

  1. 使用 mutt 撰写邮件,寄出它并离开 mutt。

  2. 联机到 ISP。

  3. 使用 /usr/sbin/sendmail -q -v 指令 来传送队列的邮件到服务器上。

  4. 中断联机。

11.6. 进阶的邮件工具

当你开始使用邮件以后,而你没有一些复杂的需求,则上述的标准 设定将可以满足你。但是,对许多每天会收到邮件的使用者而言,则需要 更有组织地储存邮件,例如,将邮件依主题分类存放在不同的信箱中。 举例来说,你订阅了一个 mailing list,每天都可能收到许多的邮件, 而你希望将它们和目前的邮件分开。很快地,你将会发现每天都花许多 时间重复同样的人工操作,来整理你的信箱。

如果有程序能自动地为你服务,为什么还要重复同样的人工操作呢? 有好几种工具可以附加到你的邮件系统以增进它的弹性和自动地处理 你的邮件。最箸名且常被使用的有:

在此段其余的部份,我们将针对 procmail,提出一个一般的设定范例: 自动地递送由 mailing list 接收的邮件,到使用者定义的信箱中。 为了直接地呼叫 procmail,我们将修改 sendmail 的设定(procmail 将会被 sendmail 用做为区域的寄送工具)而 且会建立个人化的 procmail 设定档。

首先,procmail 必须使用 package 系统安装。 (mail/procmail.)

接着,为了使用 procmail 成为区域的寄送工具,必须修改 sendmail 的设定档。在 mycf.mc 档中,解除底下三行 的标注,并建立 sendmail 设定档。

define(`PROCMAIL_MAILER_PATH', /usr/pkg/bin/procmail)dnl
FEATURE(local_procmail)dnl
MAILER(procmail)dnl
    

第一行定义了 procmail 程序的路径(你可以使用 which procmail 查看 procmail 被安装在那里)。 第二行是告诉 sendmail 使用 procmail 来做区域的递送,并将 procmail 附加到 sendmail 的寄送工具列表中。第三行是附加 procmail 到 sendmail 的寄送工具列表中(此行是选择性的。)

最后一步是建立 procmail 的设定档,包含了邮件的接收。

让我们稍做说明,例如,你在 roses 账号订阅了一个 mailing list, 其地址是 而每一封收到的邮件 都会包含如此的一行档头:

Delivered-To: [email protected]
    

procmail 的设定档 (.procmailrc) 看起来 像这样:

PATH=/bin:/usr/bin:/usr/pkg/bin
MAILDIR=$HOME/mail
LOGFILE=$MAILDIR/from

:0
* ^Delivered-To: [email protected]
roses_list
    

先前的档案只包含了一项规则,即以 ":0" 为开头的那一行。 该行定义了所有包含 "Delivered-To: [email protected]" 字符串的邮件,而最后一行则表示,所选择的邮件必须送到 roses_list 信箱中(你应该已经建立在 $MAILDIR 中。)其余的邮件将会被递送到预设的信箱。 要注意的是,$MAILDIR 是和你在 mutt 中设定的目录相同:

set folder="~/Mail"
    

当然,mailing list 只是一个范例;procmail 是多用途的工具, 可依照不同的规则来过滤邮件。通常,参考在线手册可以获得更详细 的说明:procmail(1),procmailrc(5) 和 procmailex(5)(最后一个 包含了许多设定文件的范例。)

使用以下指令,可以检查 procmail 是否被 sendmail 用作 区域的递送程序:

$ /usr/sbin/sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
>
    

以下的指令展示了 sendmail 所承认的递送程序的列表:

> =M
    

你应该找出如此的一行:

mailer 3 (local): P=/usr/pkg/bin/procmail S=EnvFromL/HdrFromL ...
    

11.7. 新闻和 tin

新闻是表示在 USENET 新闻群组上,所有文章的 集合。每一个新闻群组上的文章都有相关的主题。读取新闻群组和读取 mailing list 是不相同的:当你订阅了 mailing list,你经由邮件 收到了文章,并使用像 mutt 的邮件程序来读取它们,而你也可以寄出 回信。关于新闻,取而代之的是,利用被称为 newsreader 的特定程序,直接地在新闻服务器上阅读,例如使用 tin。利用 tin,你可以订阅你有兴趣的 新闻群组并排入 threads 中。

thread: thread 是由我们可称之为"开头的"文章,所衍生出来的一序列 的文章。简单来说,寄一封邮件到群祖上,某些人予以回复,而另一些人 则响应这些回复,等等,而建立了一个由邮件和回复组成的树状结构: 不使用 newsreader 则无法了解正确的邮件顺序。

在安装 tin 后(由 package 集合), 唯一要做的事是将 NNTP 服务器的名称写入 /usr/pkg/etc/nntp/server 档案中。 例如:

news.bignet.it
    

完成之后,执行 rtin。在屏幕上会出显类似底下 所展示的讯息:

$ rtin
Connecting to news.bignet.it...
news.bignet.it InterNetNews NNRP server INN 1.7.2 08-Dec-1997 ready (posting ok).
Reading groups from active file...
Checking for new groups...
Reading attributes file...
Reading newsgroups file...
Creating newsrc file...
Autosubscribing groups...
Reading newsrc file...
    

当你第一次联机时,请耐心等待,因为 tin 会下载你可以订阅的群组列表, 而这将花费数分钟。 在完成下载以后,将会展示程序的主画面;通常不会展示群组,按下 y 来观看群组。 将光标移至群组名称上,按下 y 来订阅该群组。

在订阅了一些新闻群组之后,你可以使用 rtin -Q 以更快地启动 tin。停止搜寻新的群组 (-q), 只有特定的群组被搜寻 (-n) 且不载入新闻群组 的描述 (-d):如此将不能使用 y (yank) 命令。当 tin 使用这些选项启动时,我们无法知道新闻群组是否 有所变动。

Note: 如果你从内部网络上联机(如同我们的范例),当你寄出邮件时, 开头的邮件地址将会是错误的(因为它是内部的地址。) 要解决这个问题,在 tin 设定档 (~/.tin/tinrc) 中使用此选项 "mail_address" 或是设定 REPLYTO 环境 变量。