跳转到内容

LPI Linux 认证/LPIC2 考试 202/邮件和新闻

来自 Wikibooks,开放世界中的开放书籍
 
LPI logo

章节概述

[编辑 | 编辑源代码]
  • 配置邮件列表
  • 使用 sendmail
  • 使用 Postfix
  • 管理邮件流量
  • 提供新闻
  • 配置邮件列表

配置邮件列表

[编辑 | 编辑源代码]

Majordomo 是一个邮件列表管理程序。它的目标是处理发送到特定电子邮件地址的所有邮件,并将它们重新分发到一个电子邮件地址列表。Majordomo 还处理向列表添加和删除电子邮件地址。

由于 Majordomo 负责管理电子邮件列表,因此它严重依赖于 MTA,例如 Sendmail、Smail、Qmail 或 Postfix。

aliases 文件(通常为 /etc/aliases)用于为电子邮件地址创建别名。例如,一旦 Majordomo 安装完成,aliases 文件中通常会有一个条目:

majordomo-owner: jarchie

此条目表示所有发送到 [email protected] 的邮件实际上将发送到 [email protected]。注意,没有必要在 jarchie 后添加 @host.com,因为两个用户都在同一个主机上。如果需要将邮件重定向到不同主机上的不同用户,则需要添加 @host.com 部分。

aliases 文件中的另一种类型的条目允许将电子邮件重定向到文件中列出的多个地址:

testlist: :include:/usr/local/majordomo-1.94.5/lists/testlist

此条目指出,发送到 [email protected] 的任何邮件将被重定向到 /usr/local/majordomo-1.94.5/lists/testlist 文件中列出的所有地址。testlist 文件可能类似于以下内容:

[email protected]
[email protected]
[email protected]

Majordomo 能够通过利用此功能来添加或删除列表中的地址。当处理订阅请求时,用户的电子邮件地址将被附加到 testlist 文件;当处理取消订阅请求时,用户的电子邮件地址将从 testlist 文件中删除。还可以通过使用文本编辑器(如 vi)编辑文件来手动添加或删除地址。

由于 Majordomo 需要能够处理通过电子邮件发送给它的命令,因此 Sendmail 必须能够执行 Majordomo 程序并将邮件传递给它。这是通过在 aliases 文件中添加另一种类型的条目来完成的:

majordomo:  "|/usr/local/majordomo-1.94.5/wrapper majordomo"

/usr/local/majordomo-1.94.5/wrapper "majordomo" |

程序 /usr/local/majordomo-1.94.5/wrapper 是一个包装器(根据配置,是 SUID 和 SGID majordomo 或守护进程),它运行 Majordomo 程序。别名条目第二部分周围的引号用于告诉 Sendmail 此条目的这部分是一个语句;如果包装器和 majordomo 之间没有空格,引号将是不必要的。| 被称为“管道”;它用于告诉 Sendmail 通过标准输入将电子邮件发送给包装器。(由于包装器在这里只调用 majordomo,因此电子邮件实际上是发送给 Majordomo 的。)包装器接受一个参数——它要执行的程序的参数。(第一个参数之后的任何参数都将被传递给包装器正在执行的程序。)出于安全原因,包装器只执行位于 Majordomo 目录 /usr/local/majordomo-1.94.5/ 中的程序。此限制防止程序员使用包装器运行不应该具有 Majordomo 权限的程序。(例如,wrapper /bin/vi 将允许任何用户编辑任何 Majordomo 配置文件。)当邮件发送到 [email protected] 时,Sendmail 启动包装器,包装器又启动 majordomo,然后 Sendmail 通过标准输入将邮件发送到 majordomo 脚本。然后,Majordomo 从邮件中提取命令并做出相应的响应。

Majordomo 当然是我们文档的主题代码;它由一系列 Perl 脚本组成,其唯一目的是管理邮件列表。

Majordomo 必须在特定的 UID 和 GID 下运行,以便在运行任何脚本时,它们都将在 Majordomo 的 UID 下运行。因此,有必要确定 Majordomo 应该在哪个 UID 和 GID 下运行。此外,Majordomo 必须是 Sendmail 可信用户。

majordomo:x:16:16:Majordomo List Manager:/usr/local/majordomo-1.94.5:

检查 /etc/passwd 和 /etc/group 文件以找到未被使用的 UID 和 GID。在本示例中,选择了 UID 16 和 GID 16。您必须决定 Majordomo 脚本将驻留在哪个位置。如果您使用的是阴影密码文件,请添加类似于以下内容的条目:

majordomo:*:10883:0:88888:7:::

到您的 /etc/passwd 文件中,并在 /etc/shadow 中添加相应的条目。

以这些文件中的其他条目为指导,了解应该添加的确切内容。这些仅仅是我系统的值。如果您没有使用阴影密码,则只需要在 /etc/passwd 文件中添加一个条目。

majordomo:x:16:jarchie

要创建 Majordomo 组,请添加类似于以下内容的行:

到您的 /etc/group 文件中。在行末添加您的用户名将使您能够访问 Majordomo 文件,这些文件是组可写的。

PERL = /bin/perl
CC = cc
W_HOME = /usr/test/majordomo-$(VERSION)
MAN = $(W_HOME)/man
W_USER = 123
W_GROUP = 45

Makefile 包含安装 Majordomo 所需的所有信息;通常有必要编辑 Makefile 中引用系统特定设置的行,以便 Majordomo 能够在您的系统上干净地安装。大多数默认设置是正确的;但是,以下设置几乎总是需要根据系统进行更改。

PERL = /usr/bin/perl
CC = gcc
W_HOME = /usr/local/majordomo-1.94.5
MAN = /usr/man
W_USER = 16
W_GROUP = 16

应更改为更适合您的系统的内容。例如,在我的设置中,这些值已更改为:

此外,必须创建 majordomo.cf 文件。创建此文件的一种简单方法是将提供的 sample.cf 文件复制到 majordomo.cf 并对其进行编辑。

$whereami = "example.com";
$whoami = "Majordomo\@$whereami";
$whoami_owner = "Majordomo-Owner\@$whereami";
$homedir = "/usr/test/majordomo";
$digest_work_dir = "/usr/local/mail/digest";
$sendmail_command = "/usr/lib/sendmail";

同样,大多数设置默认情况下是正确的,但是以下行可能需要根据您的系统进行更改,从:

$whereami = "kes.emeraldis.com";
$whoami = "majordomo\@$whereami";
$whoami_owner = "majordomo-owner\@$whereami";
$homedir = "/usr/local/majordomo-1.94.5";
$digest_work_dir = "/usr/local/majordomo-1.94.5/digest";
$sendmail_command = "/usr/sbin/sendmail";

更改为更适合您的系统的内容,例如:

$whoami 和 $whoami_owner 不需要更改即可使 Majordomo 工作;但是,我更改了它们,因为我喜欢避免输入大写字母。$digest_work_dir 是一个临时目录,应该将摘要文件放置在该目录中;此目录应分配到您希望存储摘要的位置。如果您不打算使用摘要列表,则不必担心此选项。$whereami、$homedir 和 $sendmail_command 应更改为适合您的系统的值。与 Makefile 不同,这些选项始终可以在 Majordomo 安装后通过编辑 Majordomo 安装目录中的 majordomo.cf 来更改。(配置文件在安装过程中只是被复制了。)

$ make wrapper

下一步是编译 Majordomo 包装器。包装器是唯一需要编译的 Majordomo 组件,因为所有其他组件都是一系列 perl 脚本,因此不需要编译。

# make install
# make install-wrapper

要安装 Majordomo 文件,请执行以下命令:

第一个命令可以以 Majordomo 用户身份执行(假设 majordomo 可以创建或访问 $home_dir),但第二个命令需要以 root 身份执行,以便安装脚本可以将 Majordomo 包装器设置为 SUID root。(由于 majordomo 在创建时没有登录 shell 或密码,因此如果您想以 majordomo 身份执行第一个命令,则需要以 root 身份使用 su majordomo 来成为 majordomo。)

majordomo:       "|/usr/local/majordomo-1.94.5/wrapper majordomo"
owner-majordomo: jarchie
majordomo-owner: jarchie

必须为 Majordomo 创建 Sendmail 别名,以便发送到 Majordomo 的命令可以由 majordomo 处理,并且必须为 Majordomo 所有者创建一个别名,以便人们可以通过标准的 owner-majordomo 地址发送电子邮件给您。在 aliases 文件中添加以下条目:

$ /usr/local/majordomo-1.94.5/wrapper config-test

然后测试您的配置,以普通用户(不是 majordomo 或 root)身份运行:

此程序可以检测 Majordomo 安装中的大多数问题。

[root@kes /]# su majordomo
[majordomo@kes /]$ touch /usr/local/majordomo-1.94.5/lists/test

要创建列表,请在 Majordomo 列表目录中创建一个与列表同名的文件。例如,要创建一个名为 test 的列表,请以 Majordomo 身份创建一个 test 文件:

test:        :include:/usr/local/majordomo-1.94.5/lists/test
owner-test:    jarchie
test-request:  "|/usr/local/majordomo-1.94.5/wrapper request-answer test"
test-approval: jarchie

并添加相关的别名:

[jarchie@kes jarchie]$ echo lists | mail majordomo

现在通过向 Majordomo 发送 lists 命令来测试列表的操作:

[jarchie@kes jarchie]$ echo help | mail majordomo

majordomo 应该只需要一秒钟就能回复一条消息,其中包含当前设置的所有列表。接下来,尝试发出 help 命令。

Majordomo 应该回复所有 Majordomo 接受的命令列表。保存此消息以供将来参考可能是一个好主意。

[jarchie@kes jarchie]$ echo subscribe test | mail majordomo

要查看别名是否正常工作,请尝试订阅和取消订阅您自己到列表中:

您将收到一封包含有关如何确认您的订阅的说明以及确认您的命令已成功的邮件。在发送回您的确认信息后,Majordomo 应该发送回两封邮件——一封邮件说明您的订阅请求已成功,另一封邮件欢迎您加入 test 列表。列表所有者也将收到一封邮件,说明您已订阅该列表。

[jarchie@kes jarchie]$ echo unsubscribe test | mail majordomo

要取消订阅列表,请发送取消订阅命令:

您应该收到一封邮件,说明您的命令已成功。

test:        "|/usr/local/majordomo-1.94.5/wrapper resend -l test test-list"
test-list:   :include:/usr/local/majordomo-1.94.5/lists/test
owner-test:  jarchie
test-owner:  jarchie
test-request:  "|/usr/local/majordomo-1.94.5/wrapper majordomo -l test"

对于某些列表,可能希望 Majordomo 在消息到达列表之前对其进行处理。例如,Majordomo 具有 resend 脚本,可以根据内容(例如禁忌词)自动过滤消息,以防止人们向列表发送 Majordomo 命令,以及其他功能。要使用这些选项,有必要使用一组更好的别名,例如:

Majordomo 权限设置错误很常见,会导致 Majordomo 无法正常工作。幸运的是,Sendmail 和 Majordomo 通常会给出比较清晰的错误信息,提示出现问题。例如,lists 目录必须对 sendmail 设置的 UID 用户可执行,通常是 mail 或 daemon。如果 sendmail 无法执行 lists,则需要放宽权限。

[root@kes root]# chmod +x /usr/local/majordomo-1.94.5/lists

另一个常见问题是 lists 目录具有组可写权限。要解决这个问题,可以清除组可写位,或者使用 sendmail 选项 IncludeFileInGroupWritableDirPath。

Majordomo 旨在运行在隔离的系统上;脚本中存在几个众所周知的安全漏洞,允许任何能够执行 wrapper 的本地用户以 majordomo 用户身份执行代码。如果必须在提供用户 shell 访问权限的系统上运行 Majordomo,建议收紧 wrapper 的权限。这可以通过清除世界可执行位并将 wrapper 的所有者更改为需要运行 Majordomo 脚本的用户来实现。例如,如果 Sendmail 和 MajorCool 都用来执行 wrapper,可以使用以下命令:

[root@kes root]# cp /usr/local/majordomo-1.94.5/wrapper /etc/smrsh/wrapper
[root@kes root]# chmod 4750 /usr/local/majordomo-1.94.5/wrapper
[root@kes root]# chown root:nobody /usr/local/majordomo-1.94.5/wrapper
[root@kes root]# chmod 4750 /etc/smrsh/wrapper
[root@kes root]# chown root:mail /etc/smrsh/wrapper

来保护系统。这将允许 sendmail(在 mail 身份下运行)执行 /etc/smrsh/wrapper,同时允许 web 服务器的 MajorCool(在 nobody 身份下运行)执行 /usr/local/majordomo-1.94.5/wrapper。但是,这种解决方案将允许任何拥有 mail 或 nobody 的 UID 或 GID 的用户访问 majordomo 帐户。为了保护 nobody 帐户,重要的是不允许普通用户使用服务器端包含或 cgi 脚本,除非这些服务不在 nobody 身份下运行。

关键词、文件和工具:Majordomo MTA

=== 练习 ===.

使用 Sendmail

[编辑 | 编辑源代码]

使用 Postfix

[编辑 | 编辑源代码]

Postfix 由 Wietse Venema 编写和维护,他也是 tcp_wrappers 和 Satan 的作者。Postfix 最初是 VMailer,但 Wietse 在 IBM GPL 下发布了该软件,IBM 的律师发现 VMailer 与现有的商标过于相似,因此必须更改名称。Postfix 被编写为 sendmail 的直接替代品,并且它非常接近于达到目标。有一些“陷阱”可能会让你陷入困境,但并不严重。Wietse 通过 postfix-users 邮件列表积极支持 Postfix,并且还有一个开发人员邮件列表。您可以通过以下方式订阅 postfix-users 邮件列表

echo subscribe postfix-users | mail [email protected].

您可以通过以下方式订阅开发人员列表

echo subscribe postfix-testers | mail [email protected].

我们应该提到的最后一个列表是 announce 列表。您可以通过以下方式加入 announce 列表:echo subscribe postfix-announce | mail [email protected]。Postfix 开发正在进行中,截至本文撰写时,这些邮件列表非常活跃。邮件列表的存档可以在以下位置找到:http://www.egroups.com/group/postfix-users/ 和:http://msgs.SecurePoint.com/postfix/.

当邮件进入 Postfix 邮件系统时,内部的第一站是传入队列。下图显示了与新邮件相关的主要组件。

该图显示了主要的 Postfix 系统组件,以及它们之间主要的信息流。黄色椭圆形是邮件程序,黄色方框是邮件队列或文件,蓝色方框是查找表。

大框中的程序在 Postfix 常驻主守护进程的控制下运行。大框中的数据是 Postfix 邮件系统的财产。

邮件在本地发布。Postfix sendmail 程序调用特权 postdrop 程序,将邮件存入 maildrop 目录,然后由 pickup 守护进程获取。此守护进程会进行一些完整性检查,以保护其余的 Postfix 系统。

邮件通过网络进入。Postfix SMTP 服务器接收邮件并进行一些完整性检查,以保护其余的 Postfix 系统。SMTP 服务器可以配置为基于本地或网络黑名单、DNS 查找和其他客户端请求信息来实施 UCE 控制。邮件是由 Postfix 系统本身内部生成的,用于将无法投递的邮件退回给发件人。bounce 或 defer 守护进程会带来坏消息。

邮件由本地投递代理转发,要么通过系统范围别名数据库中的条目转发,要么通过每个用户的 .forward 文件中的条目转发。这用无标签箭头表示。

邮件是由 Postfix 系统本身内部生成的,用于通知邮政管理员出现问题(此路径也用无标签箭头表示)。Postfix 系统可以配置为将 SMTP 协议问题、UCE 策略违规等通知邮政管理员。

cleanup 守护进程实现了新邮件的最终处理阶段。它添加缺失的 From: 和其他邮件头,安排将地址重写为标准 [email protected] 格式,并可选地从邮件头中提取收件人地址。cleanup 守护进程将结果作为单个队列文件插入传入队列,并通知队列管理器新邮件的到达。cleanup 守护进程可以配置为基于规范和虚拟表查找来转换地址。

根据 cleanup 守护进程的请求,trivial-rewrite 守护进程将地址重写为标准 [email protected] 格式。最初的 Postfix 版本没有实现重写语言。实现一个需要很多工作量,而且大多数站点不需要它。相反,Postfix 大量使用表查找。

Postfix 的主要配置文件(相当于 /etc/sendmail.cf 的工作副本)是 main.cf。install.cf 文件包含 Postfix 在 RPM 安装期间设置的初始设置。master.cf 文件是 Postfix 的主进程配置文件。master 文件中的每一行都描述了如何运行邮件器组件程序。在调试部分,我们将更多地讨论这个文件。postfix-script 是 Postfix 用于安全地执行 Postfix 命令的包装器,用于 Linux 环境。让我们仔细看看 install.cf 文件,因为它包含一些数据,我们将在使用 main.cf 配置 Postfix 时需要这些数据。

install.cf 文件实际上只是 RPM 中内置的安装程序使用的默认设置列表。

以下是 main.cf 文件,其中包含 Wietse Venema 的注释以及我们建议的更改穿插其中

  # Global Postfix configuration file. This file lists only a subset
  # of all 100+ parameters. See the sample-xxx.cf files for a full list.
  # 
  # The sample files mentioned above are located in /usr/doc/postfix-19990906_pl06/
  # The general format is lines with parameter = value pairs. Lines
  # that begin with whitespace continue the previous line. A value can
  # contain references to other $names or ${name}s.
  # LOCAL PATHNAME INFORMATION
  #
  # The queue_directory specifies the location of the Postfix queue.
  # This is also the root directory of Postfix daemons that run chrooted.
  # See the files in examples/chroot-setup for setting up Postfix chroot
  # environments on different UNIX systems.
  #
  queue_directory = /var/spool/postfix

这与 sendmail 用于传入邮件队列的目录相同。

  # The program_directory parameter specifies the default location of
  # Postfix support programs and daemons. This setting can be overruled
  # with the command_directory and daemon_directory parameters.
  #
  program_directory = /some/where/postfix/bin

上面的行必须更正。RPM 默认将 Postfix 二进制文件安装到 /usr/libexec/postfix 中。

  # The command_directory parameter specifies the location of all
  # postXXX commands.  The default value is $program_directory.
  #
  command_directory = /usr/sbin

上面的行是正确的,可以保留。

  # The daemon_directory parameter specifies the location of all Postfix
  # daemon programs (i.e. programs listed in the master.cf file). The
  # default value is $program_directory. This directory must be owned
  # by root.
  #
  daemon_directory = /usr/libexec/postfix

上面的行是正确的,可以保留。

  # QUEUE AND PROCESS OWNERSHIP
  #
  # The mail_owner parameter specifies the owner of the Postfix queue
  # and of most Postfix daemon processes.  Specify the name of a user
  # account THAT DOES NOT SHARE A GROUP WITH OTHER ACCOUNTS AND THAT
  # OWNS NO OTHER FILES OR PROCESSES ON THE SYSTEM.  In particular,
  # don't specify nobody or daemon. PLEASE USE A DEDICATED USER.
  #
  mail_owner = postfix

上面的行是正确的,可以保留。

  # The default_privs parameter specifies the default rights used by
  # the local delivery agent for delivery to external file or command.
  # These rights are used in the absence of a recipient user context.
  # DO NOT SPECIFY A PRIVILEGED USER OR THE POSTFIX OWNER.
  #
  #default_privs = nobody

上面的行是正确的,可以保留,但应该取消注释(例如,删除开头的井号)。

  # INTERNET HOST AND DOMAIN NAMES
  # 
  # The myhostname parameter specifies the Internet hostname of this
  # mail system. The default is to use the fully-qualified domain name
  # from gethostname(). $myhostname is used as a default value for many
  # other configuration parameters.
  #
  #myhostname = host.domain.name

将上面的行中的值设置为你的机器的完全限定域名 (FQDN)。例如,如果你的主机名为 turkey 且你的域名是 trot.com,那么你的 FQDN 将是“turkey.trot.com”。你还要取消注释此行。

  #myhostname = virtual.domain.name

上面的行对于大多数配置来说是多余的,通常可以保留注释。

  # The mydomain parameter specifies the local Internet domain name.
  # The default is to use $myhostname minus the first component.
  # $mydomain is used as a default value for many other configuration
  # parameters.
  #
  #mydomain = domain.name

上面的行应该是你的域名,不包括前面添加的主机名。如我们上面给出的示例,这里正确的 value 应该是 trot.com。不要忘记取消注释此行。

  # SENDING MAIL
  # 
  # The myorigin parameter specifies the domain that locally-posted
  # mail appears to come from. The default is to append $myhostname,
  # which is fine for small sites.  If you run a domain with multiple
  # machines, you should (1) change this to $mydomain and (2) set up
  # a domain-wide alias database that aliases each user to
  # [email protected].
  #
  #myorigin = $myhostname
  #myorigin = $mydomain

这里的说明相当不错。通常,这里所做的是让它默认设置为 $mydomain。确保取消注释你的选择。

  # RECEIVING MAIL
  # The inet_interfaces parameter specifies the network interface
  # addresses that this mail system receives mail on.  By default,
  # the software claims all active interfaces on the machine. The
  # parameter also controls delivery of mail to user@[ip.address].
  #
  #inet_interfaces = all

同样,这里的说明也不错。只需取消注释上面列出的行,你应该没问题。除非你有特殊需求,否则接下来的两个条目可以保留注释。你应该不需要它们。

  #inet_interfaces = $myhostname
  #inet_interfaces = $myhostname, localhost
  # The mydestination parameter specifies the list of domains that this
  # machine considers itself the final destination for.
  # The default is $myhostname + localhost.$mydomain.  On a mail domain
  # gateway, you should also include $mydomain. Do not specify the
  # names of domains that this machine is backup MX host for. Specify
  # those names via the relay_domains or permit_mx_backup settings for
  # the SMTP server (see sample-smtpd.cf.
  # The local machine is always the final destination for mail addressed
  # to user@[the.net.work.address] of an interface that the mail system
  # receives mail on (see the inet_interfaces parameter).
  # Specify a list of host or domain names, /file/name or type:table
  # patterns, separated by commas and/or whitespace. A /file/name
  # pattern is replaced by its contents; a type:table is matched when
  # a name matches a lookup key.  Continue long lines by starting the
  # next line with whitespace.
  #
  #mydestination = $myhostname, localhost.$mydomain
  #mydestination = $myhostname, localhost.$mydomain $mydomain

最常见的做法是选择上面紧挨着的那一行作为你在这里的选择。确保取消注释它,并在最后两个条目之间添加一个逗号,因为似乎遗漏了逗号。

  #mydestination = $myhostname, localhost.$mydomain, $mydomain,
  #       mail.$mydomain, www.$mydomain, ftp.$mydomain
  # INTERNET VERSUS INTRANET
  # The relayhost parameter specifies the default host to send mail to
  # when no entry is matched in the optional transport(5) table. When
  # no relayhost is given, mail is routed directly to the destination.
  # 
  # On an intranet, specify the organizational domain name. If your
  # internal DNS uses no MX records, specify the name of the intranet
  # gateway host instead.
  #
  # Specify a domain, host, host:port, [address] or [address:port].
  # Use the form [destination] to turn off MX lookups. See also the
  # default_transport parameter if you're connected via UUCP.
  #
  #relayhost = $mydomain
  #relayhost = gateway.my.domain
  #relayhost = uucphost
  #relayhost = [mail.$mydomain:9999]

如果你在某种防火墙后面,或者需要伪造信封(将在本文档的后面介绍),则将“relayhost”值设置为你的域名的 MTA。如果此主机将成为域名的 *the* MTA,则保留所有这些注释。

  # DEFAULT TRANSPORT
  #
  # The default_transport parameter specifies the default message
  # delivery transport to use when no transport is explicitly given in
  # the optional transport(5) table.
  #
  #default_transport = smtp

在大多数情况下,上面的行应该取消注释并保留原样。

  #default_transport = uucp
  # ADDRESS REWRITING
  #
  # Insert text from sample-rewrite.cf if you need to do address
  # masquerading.
  #
  # Insert text from sample-canonical.cf if you need to do address
  # rewriting, or if you need username->Firstname.Lastname mapping.
  # ADDRESS REDIRECTION (VIRTUAL DOMAIN)
  #
  # Insert text from sample-virtual.cf if you need virtual domain support.
  # "USER HAS MOVED" BOUNCE MESSAGES
  #
  # Insert text from sample-relocated.cf if you need "user has moved"
  # style bounce messages. Alternatively, you can bounce recipients
  # with an SMTP server access table. See sample-smtpd.cf.
  # TRANSPORT MAP
  #
  # Insert text from sample-transport.cf if you need explicit routing.
  # ALIAS DATABASE
  #
  # The alias_maps parameter specifies the list of alias databases used
  # by the local delivery agent. The default list is system dependent.
  # On systems with NIS, the default is to search the local alias
  # database, then the NIS alias database. See aliases(5) for syntax
  # details.
  # 
  # If you change the alias database, run "postalias /etc/aliases" (or
  # wherever your system stores the mail alias file), or simply run
  # "newaliases" to build the necessary DBM or DB file.
  #
  # It will take a minute or so before changes become visible.  Use
  # "postfix reload" to eliminate the delay.
  #
  #alias_maps = dbm:/etc/aliases
  alias_maps = hash:/etc/aliases

alias_maps 行指向 /etc/aliases 文件,我们在删除 sendmail 之前保留了该文件。最佳实践(推荐)通常更倾向于将所有 Postfix 配置文件放在一起,因此将此行更改为

  alias_maps = hash:/etc/postfix/aliases

可能是个好主意,并且确保你将 aliases 文件放在 /etc/postfix 中。否则,Postfix 会在启动时报错并无法运行。Red Hat Linux 上的默认 db 类型是 hash,因此请确保使用它,就像我们这里使用的一样。人们遇到的一个常见错误是他们使用 dbm 而不是 hash。不要陷入这个陷阱。

  #alias_maps = hash:/etc/aliases, nis:mail.aliases
  #alias_maps = netinfo:/aliases
  # The alias_database parameter specifies the alias database(s) that
  # are built with "newaliases" or "sendmail -bi".  This is a separate
  # configuration parameter, because alias_maps (see above) may specify
  # tables that are not necessarily all under control by Postfix.
  #
  #alias_database = dbm:/etc/aliases
  #alias_database = dbm:/etc/mail/aliases
  #alias_database = hash:/etc/aliases

正如说明中所说,如果你想使用 newaliases 命令来处理 aliases 文件(推荐),你应该取消注释上面的行,但确保(如果你进行了我们推荐的 alias_maps 部分中的路径更改)并将其更改为

  alias_database = hash:/etc/postfix/aliases

然后确保取消注释此行,并在启动 Postfix 之前运行 newaliases 命令。

   #alias_database = hash:/etc/aliases, hash:/opt/majordomo/aliases

如果你恰好运行了 majordomo,那么你应该使用上面的行,而不是仅仅使用 aliases 行。确保 majordomo 文件的路径正确。最佳实践约定是将其放在 /etc/postfix 中。大多数 Red Hat Linux sendmail 安装都将它放在 /etc/mail/ 中。当我们进入本文档的 listserv 部分时,我们将对此进行更详细的讨论。

  # DELIVERED-TO
  #
  # The prepend_delivered_header controls when Postfix should prepend
  # a Delivered-To: message header.
  #
  # By default, Postfix prepends a Delivered-To: header when forwarding
  # mail and when delivering to file (mailbox) or command.  Turning off
  # the Delivered-To: header when forwarding mail is not recommended.
  #
  # prepend_delivered_header = command, file, forward
  # prepend_delivered_header = forward

默认设置可以正常工作,因此你可以保留此部分注释,除非你有特殊需求或偏好。

  # ADDRESS EXTENSIONS (e.g., user+foo)
  #
  # The recipient_delimiter parameter specifies the separator between
  # user names and address extensions (user+foo). See canonical(5),
  # local(8), relocated(5) and virtual(5) for the effects this has on
  # aliases, canonical, virtual, relocated and .forward file lookups.
  # Basically, the software tries user+foo and .forward+foo before
  # trying user and .forward.
  #
  # recipient_delimiter = +

这个也可以保留注释,除非你有特殊需求或偏好。

  # DELIVERY TO MAILBOX
  #
  # The home_mailbox parameter specifies the optional pathname of a
  # mailbox relative to a user's home directory. The default is to
  # deliver to the UNIX-style /var/spool/mail/user or /var/mail/user.
  # Specify "Maildir/" for qmail-style delivery (the / is required).
  #
  #home_mailbox = Mailbox
  #home_mailbox = Maildir/

在 Red Hat Linux 系统上,除非你知道自己在做什么,否则不要修改它。如果你正在从 qmail 转换到 Postfix(不太可能),那么它可能会有用。

  # The mail_spool_directory parameter specifies the directory where
  # UNIX-style mailboxes are kept. The default setting depends on the
  # system type.
  #
  # mail_spool_directory = /var/mail
  # mail_spool_directory = /var/spool/mail

前一行对于 Red Hat Linux 默认值是正确的,因此应该取消注释并保持原样。

  # The mailbox_command parameter specifies the optional external
  # command to use instead of mailbox delivery. The command is run as
  # the recipient with proper HOME, SHELL and LOGNAME environment settings.
  # Exception:  delivery for root is done as $default_user.
  #
  # Other environment variables of interest: USER (recipient username),
  # EXTENSION (address extension), DOMAIN (domain part of address),
  # and LOCAL (the address localpart).
  #
  # Unlike other Postfix configuration parameters, the mailbox_command
  # parameter is not subjected to $parameter substitutions. This is to
  # make it easier to specify shell syntax (see example below).
  #
  # Avoid shell meta characters because they will force Postfix to run
  # an expensive shell process. Procmail alone is expensive enough.
  #
  #mailbox_command = /some/where/procmail

Red Hat Linux 系统上的默认 MDA 是 procmail。你可以使用命令“which procmail”来验证路径,但除非你更改了 procmail 的位置,否则它位于“/usr/bin/procmail”中。不要忘记取消注释该行。

  #mailbox_command = /some/where/procmail -a "$EXTENSION"
  # The mailbox_transport specifies the optional transport in master.cf
  # to use after processing aliases and .forward files. This parameter
  # has precedence over the mailbox_command, fallback_transport and
  # luser_relay parameters.
  #
  #mailbox_transport = cyrus

在默认的 Red Hat Linux 系统上,你应该保持上面的行不变。

  # The fallback_transport specifies the optional transport in master.cf
  # to use for recipients that are not found in the UNIX passwd database.
  # This parameter has precedence over the luser_relay parameter.
  #
  #fallback_transport =

在默认的 Red Hat Linux 系统上,你应该保持上面的行不变。

  # The luser_relay parameter specifies an optional destination address
  # for unknown recipients.  By default, mail for unknown local recipients
  # is bounced.
  #
  # The following expansions are done on luser_relay: $user (recipient
  # username), $shell (recipient shell), $home (recipient home directory),
  # $recipient (full recipient address), $extension (recipient address
  # extension), $domain (recipient domain), $local (entire recipient
  # localpart), $recipient_delimiter. Specify ${name?value} or
  # ${name:value} to expand value only when $name does (does not) exist.
  #
  # luser_relay = [email protected]
  # luser_relay = [email protected]
  # luser_relay = admin+$local

你可以选择在这里做什么,但每天收到数百万封退信可能会很烦人。保持不变(推荐)。

  # JUNK MAIL CONTROLS
  # 
  # The controls listed here are only a very small subset. See the file
  # sample-smtpd.cf for an elaborate list of anti-UCE controls.
  # The header_checks parameter restricts what may appear in message
  # headers. This requires that POSIX or PCRE regular expression support
  # is built-in. Specify "/^header-name: stuff you do not want/ REJECT"
  # in the pattern file. Patterns are case-insensitive by default. Note:
  # specify only patterns ending in REJECT. Patterns ending in OK are
  # mostly a waste of cycles.
  #
  #header_checks = regexp:/etc/postfix/filename
  #header_checks = pcre:/etc/postfix/filename

以上部分启用了一个过滤器,你可以使用它来检测和“退回”与特定正则表达式(REGEXP)匹配的邮件。使用 procmail 和 regexp 或 PCRE 之间的区别在于,这两个在邮件传递之前捕获邮件,并可以在 SMTP 端口有效地阻止不需要的邮件。

  # The relay_domains parameter restricts what domains (and subdomains
  # thereof) this mail system will relay mail from or to.  See the
  # smtpd_recipient_restrictions restriction in the file sample-smtpd.cf.
  #
  # By default, Postfix relays mail only from or to sites in or below
  # $mydestination, or in the optional virtual domain list.
  # 
  # Specify a list of hosts or domains, /file/name patterns or type:name
  # lookup tables, separated by commas and/or whitespace.  Continue
  # long lines by starting the next line with whitespace. A file name
  # is replaced by its contents; a type:name table is matched when a
  # (parent) domain appears as lookup key.
  #
  # NOTE: Postfix will not automatically forward mail for domains that
  # list this system as their primary or backup MX host. See the
  # permit_mx_backup restriction in the file sample-smtpd.cf.
  #
  #relay_domains = $mydestination, $virtual_maps

对于任何已经了解 MX 记录工作原理的人来说,这是 Postfix 配置中的一个关键组件。家庭用户可能不需要这一行,但任何处理多个域邮件的人都会需要。

以下是一个示例说明它的用法

   relay_domains = $mydestination, /etc/postfix/relay-domains

在这个示例中,你想要为其中继的域将被放置在 /etc/postfix/relay-domains 文件中。一行一个,如下所示

  here.com 
  mail.here.com 
  there.org 
  mail.there.org 

注意:此文件*不*被哈希或映射。它是一个简单的文本文件。你也可以使用 IP 地址而不是名称。

  # The mynetworks parameter specifies the list of networks that are
  # local to this machine.  The list is used by the anti-UCE software
  # to distinguish local clients from strangers. See permit_mynetworks
  # and smtpd_recipient_restrictions in the file sample-smtpd.cf file.
  #
  # The default is a list of all networks attached to the machine:  a
  # complete class A network (X.0.0.0/8), a complete class B network
  # (X.X.0.0/16), and so on. If you want stricter control, specify a
  # list of network/mask patterns, where the mask specifies the number
  # of bits in the network part of a host address. You can also specify
  # the absolute pathname of a pattern file instead of listing the
  # patterns here.
  #
  #mynetworks = 168.100.189.0/28, 127.0.0.0/8

上面的行是 Postfix 配置中的另一个关键组件。正如说明中所说,它指定了此主机本地的网络列表。对于不熟悉所用语法的用户,它被称为无类别域间路由 (CIDR) 或超级网络。对于熟悉网络类别(A、B、C 等)的用户,它是一种无需参考类别即可划分 IP 地址的方法。

  #mynetworks = $config_directory/mynetworks
  # SHOW SOFTWARE VERSION OR NOT
  #
  # The smtpd_banner parameter specifies the text that follows the 220
  # status code in the SMTP greeting banner. Some people like to see
  # the mail version advertised. By default, Postfix shows no version.
  #
  # You MUST specify the $myhostname at the start of the text. When
  # the SMTP client sees its own hostname at the start of an SMTP
  # greeting banner it will report a mailer loop. That's better than
  # having a machine meltdown.
  #
  #smtpd_banner = $myhostname ESMTP $mail_name
  #smtpd_banner = $myhostname ESMTP $mail_name ($mail_version)

上面的配置条目是个人偏好的问题。它不是必需的,管理员可以选择。

  # PARALLEL DELIVERY TO THE SAME DESTINATION
  #
  # How many parallel deliveries to the same user or domain? With local
  # delivery, it does not make sense to do massively parallel delivery
  # to the same user, because mailbox updates must happen sequentially,
  # and expensive pipelines in .forward files can cause disasters when
  # too many are run at the same time. With SMTP deliveries, 10
  # simultaneous connections to the same domain could be sufficient to
  # raise eyebrows.
  # 
  # Each message delivery transport has its XXX_destination_concurrency_limit
  # parameter.  The default is $default_destination_concurrency_limit.
  local_destination_concurrency_limit = 2
  default_destination_concurrency_limit = 10

正如上面的文字所说,这一部分实际上是关于速率限制的。本质上,它是 Postfix 的油门。除非你有充分的理由更改这些默认值,否则应该保持不变。在运行 Postfix 一段时间后(特别是那些在专业环境中使用它的人),你可能会更好地了解如何在你的环境中设置它。

  # DEBUGGING CONTROL
  #
  # The debug_peer_level parameter specifies the increment in verbose
  # logging level when an SMTP client or server host name or address
  # matches a pattern in the debug_peer_list parameter.
  #
  debug_peer_level = 2

我们建议使用这里的默认值,除非有充分的理由进行更改。调试将在本文档的后面章节中介绍。值得一提的是,除非启用下一部分,否则这一部分没有实际意义。

  # The debug_peer_list parameter specifies an optional list of domain
  # or network patterns, /file/name patterns or type:name tables. When
  # an SMTP client or server host name or address matches a pattern,
  # increase the verbose logging level by the amount specified in the
  # debug_peer_level parameter.
  #
  # debug_peer_list = 127.0.0.1
  # debug_peer_list = some.domain

此部分与 debug_peer_level 结合使用,因此如果未启用它,则此部分毫无意义。这实际上是 Postfix 的一个非常巧妙的功能。想一分钟。如果一切正常,但有一个主机似乎在接收或发送邮件到或从你的主机时遇到问题,那么你可以使用此功能来提高仅针对该主机的日志级别。

  # The debugger_command specifies the external command that is executed
  # when a Postfix daemon program is run with the -D option.
  #
  # Use "command .. & sleep 5" so that the debugger can attach before
  # the process marches on. If you use an X-based debugger, be sure to
  # set up your XAUTHORITY environment variable before starting Postfix.
  #
  debugger_command =
           PATH=/usr/bin:/usr/X11R6/bin
           xxgdb $daemon_directory/$process_name $process_id & sleep 5

现在保持此部分不变。我们将在本文档的后面部分详细介绍调试。就是这样。我们已经完成了 main.cf 文件,并且几乎可以开始启动它了。

master.cf

[编辑 | 编辑源代码]

主守护进程是一个监督应用程序,它控制和监视所有其他 Postfix 进程。master.cf 文件是主守护进程的配置文件。master.cf 文件是 Postfix 的节流阀。在这里,你可以设置所有守护进程进程计数限制。一个有用的限制的例子是设置可以同时执行的 SMTP 进程数量的限制,毕竟,你可能不希望同时接收 50 条入站消息。这里要理解的关键是,任何没有明确限制的进程默认限制为 50 个进程。

一般来说,master.cf 文件的默认值就很好,所以你可以保持不变。

这仅仅是默认的别名文件,它可以与你在 sendmail 中使用的文件完全相同(推荐),并且它与使用 newaliases 命令时的工作方式相同。如果你使用 majordomo,你的 majordomo 别名将以与以前相同的方式工作,并且它们也将与 newaliases 命令一起工作。

postfix 服务器的控制通过 init.d 脚本完成。更改配置后,不要忘记发出 postfix reload 命令!如果你修改了别名数据库 (/etc/aliases),不要忘记通过发出 newaliases 命令(如 sendmail 中一样)激活更改。

关键术语、文件和实用程序:/etc/aliases /etc/postfix/main.cf /etc/postfix/master.cf /var/spool/postfix

管理邮件流量

[编辑 | 编辑源代码]

procmail 是由德国的 Stephen van den Berg 编写的邮件处理实用程序语言。本文为中级 Unix 用户提供了有关如何使用 procmail 的一些背景信息。作为一个“小型”语言(使用学术术语),procmail 缺乏许多传统通用语言的功能和结构。它没有“while”或“for”循环。但是它“了解”许多有关 Unix 邮件传递约定和文件/目录权限的信息——尤其是关于文件锁的信息。虽然可以使用大多数 Unix 系统上安装的工具,用任何编程语言编写自定义邮件过滤脚本是可能的——我们将证明 procmail 是系统管理员和高级 Unix 用户的首选工具。

Unix 邮件系统由 MTA(邮件传输代理,如 sendmail、smail、qmail mmdf 等)、MDA(交付代理,如 sendmail、deliver 和 procmail)和 MUA(用户代理,如 elm、pine、/bin/mail、mh、Eudora 和 Pegasus)组成。

在互联网上的大多数 Unix 系统上,sendmail 被用作集成传输和交付代理。sendmail 和兼容的 MTA 具有通过两种机制中的任何一种,通过自定义过滤器或程序调度邮件的能力:别名和 .forwards。

别名机制使用单个文件(通常为 /etc/aliases 或 /usr/lib/aliases)来重定向邮件。此文件由系统管理员拥有和维护。因此你(作为用户)无法修改它。“.forward”机制是分散的。系统上的每个用户都可以在其主目录中创建一个名为 .forward 的文件,其中包含地址、文件名或程序(过滤器)。通常,该文件*必须*由用户或 root 拥有,并且*不能*被其他用户“写入”(出于安全原因,sendmail 的良好版本会检查这些因素)。

使用 sendmail 的某些版本,你还可以通过逗号分隔指定多个地址、程序或文件。但是,我们将跳过这方面的细节。管理邮件流量

你可以通过 .forward 中包含的任何任意程序转发你的邮件,该程序包含一行,例如

"|$HOME/bin/your.program -and some arguments"

注意引号和“管道”字符。它们是必需的。“Your.program”可以是 Bourne shell 脚本、awk 或 perl 脚本、编译的 C 程序或你想要编写的任何其他类型的过滤器。

但是,必须编写“your.program”来处理有关 sendmail 如何将消息(标题和正文)传递给它的许多细节,如何将返回值返回给 sendmail,如何处理文件锁定(如果邮件在“your.program”仍在处理一个邮件时到达,等等)。这就是 procmail 给我们的东西。

到目前为止,我们所看到的是适用于所有与 sendmail 兼容的 MTA/MDA 的一般信息。管理邮件流量

因此,为了确保邮件被传递到 procmail 以供处理,第一步是创建 .forward 文件。(这在配置 procmail 本身之前进行是安全的——假设该软件包的二进制文件已安装)。以下是 procmail 手册页中粘贴的规范示例

"|IFS=' '&&exec /usr/local/bin/procmail -f-||exit 75 #YOUR_USERNAME"

如果你这样做了,并且什么都没做,你的邮件基本上不会受到影响。procmail 只会查找其默认的配方文件(.procmailrc),如果没有找到——它会对每条消息执行其默认操作。换句话说,它会将新消息追加到你的正常 spool 文件中。

你可以在 sendmail/postfix 中将 procmail 设置为系统范围的本地交付代理。完成此操作后,你可以跳过有关使用 .forward 文件的整个部分——或者你可以照常使用它。例如,在 sendmail 中,可以通过使用以下内容更改 sendmail.mc 来实现

MAILER_DEFINITIONS
dnl # MAILER(`local')dnl <- comment this one out with dnl
MAILER(`procmail')dnl
MAILER(`smtp')dnl

在 postfix 中,可以根据postfix 常见问题解答来完成。基本上,只需编辑 /etc/postfix/main.cf,并使用以下内容并重新加载 postfix 即可。

/etc/postfix/mail.cf:
mailbox_command = /path/to/procmail

无论哪种情况,自动处理邮件的下一步是在你的主目录中创建一个 .procmailrc 文件。你实际上可以将此文件命名为任何你想要的名称——但你需要将该名称显式地插入 .forward 文件中(在“||”运算符之前)。几乎每个人都使用默认名称。

到目前为止,我们只讨论了如何将所有内容路由到 procmail——这主要涉及 sendmail 和 Bourne shell 的语法。几乎所有 sendmail 都配置为使用 /bin/sh(Bourne shell)来解释别名和 .forward“管道”。

因此,以下是一个非常简单的 .procmailrc 文件

:0c:
$HOME/mail.backup

这只是将所有传入邮件的额外副本追加到你的主目录中的名为“mail.backup”的文件中。请注意,为你预设了许多环境变量。有人建议你应该显式地设置 SHELL=/bin/sh(或你系统上可用的最接近 Bourne Shell 的衍生版本)。我一直没有为此担心,因为我在大多数系统上使用的 shell 已经是 Bourne 兼容的。

但是,csh 和其他 shell 用户应该注意,我见过的所有 procmail 食谱示例都使用 Bourne 语法。

:0 行标志着“食谱”(过程、子句,无论什么)的开始。:0 后面可以是许多“标志”中的任何一个。组合这些标志的方法数不胜数。我们在本示例中使用的唯一标志是“c”,表示“复制”。

这行中的第二个冒号标志着标志的结束以及锁文件名称的开始。由于没有给出名称,procmail 将自动选择一个。

这一部分有点复杂。邮件可能会成批到达。如果在您的脚本仍在处理上一封邮件时收到了一封新邮件,您将拥有多个 sendmail 进程。每个进程都会处理一封邮件。这本身不是问题。但是,如果这两个进程试图同时写入同一个文件,它们很可能会以不可预测的方式混乱(结果将不是格式正确的邮件文件夹)。

因此,我们提示 procmail 它需要检查并创建锁文件。在这个特定情况下,我们不关心锁文件的名称是什么(因为我们不会让其他程序写入备份文件)。因此,我们保留最后一个字段(冒号之后)为空。然后 procmail 将选择它自己的锁文件名。

如果我们从配方标题行中删除 :(完全省略最后一个字段),则不使用锁文件。当我们只打算从配方中的文件读取时,或者当我们只打算以非特定顺序向文件写入短的单行条目时(例如日志文件条目),这很合适。procmail 的工作方式是

它从 sendmail(或某个与 sendmail 兼容的 MTA/MDA)接收一条邮件。由于新邮件可能比处理速度快,因此可能有多个 procmail 正在运行。它打开其配方文件(默认情况下为 .procmailrc 或在其命令行上指定)并从第一个配方到最后一个配方解析每个配方,直到邮件被“传递”(或“处置”,具体情况而定)。

任何配方都可以是邮件的“处置”或“传递”。一旦邮件被“传递”,procmail 就会关闭其文件,删除其锁并退出。

如果 procmail 到了其 rc 文件的末尾(以及所有 INCLUDE 的文件),但没有“处置”邮件,则邮件将被附加到您的 spool 文件(这对您和所有“邮件用户代理”来说看起来像是一次正常的传递,比如 Eudora、elm 等)。

这解释了为什么 procmail 对您没有 *no* .procmailrc 如此宽容。它只是将您的邮件传递到 spool,因为它已经到达了所有配方的末尾(没有配方)。'c' 标志使配方在邮件的“副本”上工作,这意味着该配方采取的任何操作都不会被视为邮件的“处置”。

没有 'c' 标志,此配方将捕获所有传入邮件,并且所有邮件最终都会进入 mail.backup。没有邮件会进入您的 spool 文件,并且不会解析其他任何配方。

此示例配方中的下一行只是一个文件名。与 sendmail 的别名和 .forward 文件一样,procmail 识别三种类型的邮件处置。您可以将其附加到文件、将其转发到其他邮件地址,或将其通过程序过滤。

实际上,procmail 处理了一种特殊形式的“传递”或“处置”。如果您提供一个目录名称(而不是文件名),它会将邮件作为单独的文件添加到该目录中。该文件的名称将基于几个相当复杂的因素,除非您使用 Rand MH 系统或其他相对模糊和“奇特”的邮件代理,否则您不必担心这些因素。

一个 procmail配方通常由三部分组成——开始行(:0 带有一些标志)、一些条件(以 * 开头的行 - 星号 - 字符)和一个“传递”行,可以是文件/目录名称,也可以是以 ! 开头的行 - 叹号 - 字符,或者是以 | 开头的行 - 管道字符。

以下是一个示例

:0
* ^From.*[email protected]
/dev/null

这是一个简单的示例,没有标志,一个条件和一个简单的文件传递。它只是丢弃来自“我不喜欢的人”的所有邮件。(Unix 下的 /dev/null 是一个“位桶”——一个无底的井,用于丢弃不需要的输出。DOS 也有类似的概念,但并不那么方便)。

以下是一个更复杂的示例

:0
* !^FROM_DAEMON
* !^FROM_MAILER
* !^X-Loop: [email protected]
| $HOME/bin/my.script

它由一组否定条件组成(请注意,所有条件都以 ! 字符开头)。这意味着:对于任何没有来自“daemon”(某些自动化进程)并且没有来自“mailer”(某些其他自动化进程)并且不包含以下形式的标题行的邮件:“X-Loop: myadd...” 将其通过我的 bin 目录中的脚本。

我可以将脚本直接放在 rc 文件中(大多数 procmail 用户大多数时候都这样做)。这个脚本可以对邮件做任何事情。在这种情况下,无论它做什么都必须是好的,因为 procmail 方式将认为所有此类邮件都被传递了,而此后的任何配方都将只由来自 DAEMON、MAILER 的邮件以及标题中包含特定 X-Loop: 行的邮件访问。

这两个特殊的 FROM_ 条件实际上是“特殊的”。它们由 procmail 预设,实际上指的是一些相当复杂的正则表达式,这些正则表达式专门匹配大多数来自守护程序和邮件程序的邮件头中发现的东西。

X-Loop: 行是正常的 procmail 条件。在 RFC822 文档(定义了互联网上电子邮件头应该是什么样子)中,任何以 X- 开头的行都是“自定义”头。这意味着任何想要添加电子邮件程序都可以添加几乎任何它想要的 X- 行。

一个常见的 procmail 习惯用法是,在发送出去的任何邮件的标题中添加一个 X-Loop: 行,并在发送任何东西之前检查我们自己的 X-Loop: 行。这是为了防止“邮件循环”——我们的邮件被转发或“反弹”回我们,我们无休止地回复它。

因此,以下是如何使用 procmail 自动回复来自特定人的邮件的详细示例。我们从配方标题开始。

:0

...然后我们添加一个条件(邮件似乎来自此人)

* ^[email protected]

FROM 是 procmail 的一个“神奇”值——它检查 from、resent-by 和类似的标题行。您也可以使用 ^From:——它将只匹配以字符串“From:”开头的标题行。

^(打嗝或更准确地说“插入符号”)是一个“正则表达式锚点”(一个技术术语,意思是“它指定了模式必须出现在哪里才能匹配”。有一整本书都是关于正则表达式(O'Reilly & Associates)。“正则表达式”遍布许多 Unix 实用程序、脚本语言和其他程序。每个应用程序的“正则表达式”语法略有不同。但是,'grep' 或 'egrep' 的手册页是学习更多内容的绝佳场所。

在这种情况下,打嗝表示模式必须出现在行的开头(这是它在 grep、ed/sed、awk 和其他上下文中通常的含义)。

...然后我们添加几个条件来避免循环并避免回复自动系统

* !^FROM_DAEMON
* !^FROM_MAILER

(这些是几个更“神奇”的值。手册页显示了分配给这些关键字的确切正则表达式——如果您好奇或需要调整与其中一个或两个类似的特殊条件)。

...再加一个来防止一些棘手的循环

* !^X-Loop: [email protected]

(所有这些模式都以“叹号”(惊叹号)开头,因为条件是标题中的*没有*行以这些模式中的任何一个开头。在这种情况下(以及大多数其他正则表达式上下文中),'叹号'“否定”或“反转”了模式的含义)。

...现在我们添加一个“处置”——自动回复。

| (formail -rk \
-A "X-Loop: [email protected]" \
-A "Precendence: junk"; \
echo "Please don't send me any more mail";\
echo "This is an automated response";\
echo "I'll never see your message";\
echo "So, GO AWAY" ) | $SENDMAIL -t -oi 

这非常复杂,但以下是它的工作原理:| 字符告诉 procmail 它应该启动一个程序并将其输入到该程序。左括号是一个 Bourne shell 结构,它以这样一种方式对一组命令进行分组,将所有命令的输出合并成一个“流”。

formail 命令是一个随 procmail 包附带的便捷程序。它根据其命令行开关及其输入“格式化”邮件头。-rk 告诉 formail 格式化“回复”并“保留”邮件正文。使用这些开关,formail 期待一个标题和一个正文作为输入。

-A 参数告诉 formail 将下一个参数添加为标题行。提供给 -A 开关的参数必须用引号括起来,以便 shell 将整个字符串(包括空格)视为单个参数。每一行末尾的斜杠告诉 procmail 邮件将下一行视为此行的一部分。因此,所有以斜杠结尾的行都作为一行传递给 shell。

此“尾随反斜杠”或“行延续”字符是一个常见的 Unix 习惯用法,在许多编程语言和配置文件格式中都有发现。分号告诉 shell 执行另一个命令——它们允许在同一个命令行上发出多个命令。

每个 echo 命令都应该相当容易理解。如果我们想使用 'cat' 命令并将我们的文本放入文件,我们也可以这样做。我们也可以在这里调用其他程序,例如 'fortune' 或 'date',它们的输出将与其他内容合并)。

现在我们到了右括号。它标志着我们组合的命令块的结束。所有这些命令的输出都输入到下一个管道中——它启动 sendmail 的本地副本(请注意,这是一个 procmail 为我们细心地预设的另一个变量)。

sendmail 上的 -t 开关告诉它从其输入的标题(formail -r 将其放在那里)中获取“To:”地址,而 -oi 开关使 sendmail “选项”能够“忽略”只包含一个点(不必担心其中的细节)的行。

理解 procmail 的大多数困难与 procmail 本身无关。正则表达式的复杂性(那些在 * 上的奇怪东西——条件行)以及 shell 引号和命令语法,以及如何格式化一个 sendmail 可以接受的回复标题(formail 和 sendmail 的东西)是需要如此多解释的部分。

有关 procmail 的更多信息,请参阅 Era Eriksson 的“迷你常见问题解答”。在 http://www.iki.fi/~era/procmail/mini-faq.html 或几个镜像之一,例如 http://www.zer0.org/procmail/mini-faq.html http://www.dcs.ed.ac.uk/home/procmail/faq/mini-faq.html

关键术语、文件和实用程序:Procmail .procmailrc

=== 练习 ===.

提供新闻

[edit | edit source]

INND 守护进程是最常用的新闻服务器程序之一,它提供网络新闻传输协议 (NNTP) 服务。主要的新闻组包括:alt、comp、gnu、misc、news、rec、sci、soc 和 talk。新闻组以分层方式配置。默认情况下,INND 使用 NNTP 端口 TCP 119。

配置

配置文件的位置为 /etc/news/。最小的叶节点设置需要修改以下文件。

inn.conf

设置以下选项。其余选项的默认值应该没问题。

organization:   MyOrganization
domain:         mydomain.com
server:         news.mydomain.com
incoming.conf :

将您的 ISP 的新闻服务器信息放在这里。

# Peer definition
# MyISP.com  (800) 555-1212 [email protected]
peer myisp.com {
   hostname:  news.myisp.com
}

新闻源

[编辑 | 编辑源代码]

如果您想发布文章,您需要修改新闻源。 news.myisp.com:comp.*,!comp.sources.*,comp.sources.unix/!foo:Tf,Wnm:news.myisp.com 上面的冒号是使用的字段分隔符。上面这一行的格式是:sitename[/exclude,exclude,...]:pattern,pattern,...[/distrib,distrib,..]:flag,flag,...:param

选项

sitename
命名与该新闻源相关的站点。可以随意命名,不必是站点的域名。
pattern
指示哪些新闻组要发送到该站点。默认情况下,发送所有组(如果需要,留空)。上面的例子将导致所有“comp”组被接收,但不包括“comp.sources”下的任何组,除了“comp.sources.unix”。
distribution
如果指定,并且文章有“Distribution”标题,则会检查该值。如果指定的分布与文章中的分布标题匹配,则会发送。但是,如果指定的分布以感叹号开头,并且文章中的分布标题匹配,则不会发送。在上面的示例中,任何包含“foo”的分布标题的文章都不会被发送。
flag
指定关于新闻源的各种选项。上面的选项指定这是一个文件新闻源类型 (Tf),并且只应该写入“message-id”和“token” (Wmn) 文章。

param - 含义根据新闻源类型而变化。当新闻源类型为“file”时,如上面的示例所示,它指定在接收文章时写入条目的文件。如果路径不是绝对路径,则相对于 inn.conf 中的“pathoutgoing”选项。

readers.conf:如果您想允许其他计算机上的用户阅读,请编辑此文件。motd.news:如果您允许用户阅读,建议在这个文件中放置一个横幅,将您的使用策略传达给您的读者。

运行 inncheck 来更正任何权限问题并捕获任何配置文件错误。运行 makehistory 来初始化 INN 历史数据库。运行 makedbz 来重建 dbz 数据库文件。运行 innd 并使用新闻客户端进行测试。

故障排除

[编辑 | 编辑源代码]

innd 无法启动 使用 inncheck。检查 /var/log/news 下的日志。读者无法阅读:验证读者是否被允许访问,方法是检查 nnrp.access。确保 innd 正在运行。检查 /var/log/news 下的日志。telnet 到端口 119 并查看是否出现了横幅。发布者无法发布:确认发布者被允许发布,方法是检查 nnrp.access。检查 /var/log/news 下的日志。telnet 到端口 119 并查看是否出现了包含(允许发布)的横幅。

关键词、文件和工具:Innd

华夏公益教科书