使用 Sendmail 作为多平台邮件路由器

作者:Tom Lowery

电子邮件是未来的趋势吗?绝不可能。它在今天是一项任务关键型、必不可少的应用程序。看看您最近从同事那里收集的名片。很可能大多数名片上都印有 Internet 电子邮件地址。《微软杂志》1996 年 4 月刊中,比尔·盖茨说:“[电子邮件] 可能是微软在公司运营方面最关键的任务应用程序。如果我们必须选择一个无论如何都要保持运行的应用程序,那绝对是电子邮件。”人们希望与自己公司内部以及整个网络中的其他人进行快速、可靠的书面沟通。

我的工作是保持公司电子邮件的顺利运行。最近一位用户向我抱怨,因为她的电子邮件信息花了整整 12 分钟才送达。人们对电子邮件应该为他们做什么的期望越来越高。

在同构环境中提供电子邮件很简单。如果一家商店完全由 Linux 工作站组成,那么电子邮件几乎是自动的。所有其他主要 Unix 变体也是如此。由于所说的电子邮件协议 SMTP 在所有平台上都是相同的,因此无需特殊的网关即可连接到 Internet。SMTP 代表简单邮件传输协议,多年来一直是 Internet 邮件传输的事实标准。只要公司中的每个人都使用相同的非 SMTP 商业软件包,交换邮件也几乎一样简单。当使用多个不兼容的系统时,情况会变得更加复杂。使邮件在它们之间以及 Internet 之间无缝流动可能会带来很多问题。在本文中,我将解释 Caliber Technology 如何通过 Linux 和 sendmail 快速且经济地解决这些问题。

Caliber System 通过其运营部门 RPS、Viking Freight、Caliber Logistics、Roberts Express 和 Caliber Technology,是一家提供运输、物流和信息服务的增值供应商。Caliber Technology 为客户、Caliber 公司和其他感兴趣的用户提供集成信息服务。

问题

Caliber 公司在截然不同的计算环境中运营:IBM 大型机、AS/400、HP/UX 中型系统、Novell 和 NT LAN、Tandem 小型计算机等等。使用的电子邮件平台包括 Microsoft Mail、Lotus cc:Mail、Tandem PS Mail、IBM OV/400、TAO/Emc2 和 Microsoft Exchange。不幸的是,这些邮件系统通常彼此不兼容。我们计划将所有 Caliber 公司迁移到兼容的电子邮件平台,但迁移工作至少需要两年时间。好消息是所有这些系统都有网关可用。邮件网关的功能是将消息从一种格式转换为另一种格式。一些网关将消息从一种专有格式转换为另一种专有格式:例如,从 Lotus cc:Mail 到 Microsoft Mail,反之亦然。其他网关在专有格式和标准格式之间转换消息。这里的一个例子是从 cc:Mail 到 SMTP 以及从 SMTP 到 cc:Mail。两种最常见的标准格式是 SMTP 和 X.400。X.400 是 CCITT/ISO 标准,受到许多商业网络的支持。由于 Caliber 的目标是使其所有内部邮件系统相互通信并与 Internet 通信,因此 SMTP 是 通用语言 的明显选择。

这就是事情变得复杂的地方。像许多公司一样,Caliber Technology 为其大型机和 LAN 系统使用非显而易见的登录名。在典型的 Unix 环境中,我的登录名可能是 tlowery

但在 Caliber 的多平台环境中,我的登录名是 xyz123。这是一个为了提供更好安全性的遗留决策。ID 太多了,而且它们在我们的系统中根深蒂固,即使我们想更改它们也无法更改。问题是,我们使用的大多数网关不允许 SMTP 电子邮件名称与本地登录 ID 不同。根本无法在配置中指定这一点。换句话说,我的 Internet 邮件地址必须是 xyz123@calibersys.com。出于显而易见的原因,我们发现这令人反感;实际上,情况更糟。网关将它们的网络主机名添加到出站邮件的地址中。我的地址实际上是 xyz123@gateway1.calibersys.com。因此,要解决的第一个问题是将出站邮件的 私有 基于网关的地址转换为 公共 Internet 地址,例如从 xyz123@gateway1.calibersys.com 转换为 tlowery@calibersys.com

解决这个问题又会产生另一个问题。calibersys.com 电子邮件域由多个邮件系统组成。如果邮件从 Internet 入站到 tlowery@calibersys.com,那么如何决定将其发送到 gateway1(例如,Microsoft Mail)而不是 gateway2 (TAO/Emc2)?沿途的某个系统必须查找 tlowery 并决定将消息发送到 gateway1。在 Caliber,我们接受发往 calibersys.comlogistics.calibersys.comshiprps.comvikingfreight.comroberts.com 的邮件,并对所有这些邮件执行名称查找。

像许多公司一样,我们的内部 TCP/IP 网络通过商业防火墙连接到 Internet。我们在决定为所有 Caliber 公司提供 Internet 邮件服务之前很久就购买了防火墙。在某种程度上,它可以被认为是一个遗留系统,它本身有一些缺点。虽然我们的防火墙可以解决第一个或第二个问题,但它不能同时解决这两个问题。根据我们的防火墙供应商的说法,我们是他们的第一个客户,需要同时为多个域进行名称映射和网关隐藏。可以购买基于商业 X.500 的目录系统来优雅地将所有内容联系在一起;问题是成本。花 20 万美元来购买一个我们希望两年后不需要的解决方案没有多大意义。由于防火墙供应商没有快速修复方案,并且成群的用户涌到我的办公室要求公司间和 Internet 邮件服务,我坐下来研究了 sendmail,看看它是否提供了任何答案。幸运的是,它确实提供了。

我们今天实施的解决方案如图 1 所示。任何邮件消息,包括那些往返于 Internet 的消息,在从一个系统传输到另一个系统时,都会通过一个中央枢纽传输。为了增加可靠性,实际上有两个枢纽。一个充当主枢纽;另一个在主枢纽发生故障时充当备份。这些枢纽的唯一目的是向用户隐藏电子邮件寻址详细信息。让我们看一个例子。

首先,假设我在 tlowery@calibersys.com 想给 Jane 发送一条消息,她的地址是 jdoe@vikingfreight.com。发送者和接收者的地址都存在于 Caliber 防火墙内部,因此消息不会发送到 Internet。我在 Microsoft Mail 上的邮箱名称是 xyz123,Microsoft Mail 的 SMTP 网关称为 gateway1。当消息离开我的邮件系统时,它看起来像这样

From: xyz123@gateway1.calibersys.com
To: jdoe@vikingfreight.com

消息被路由到 mhub,我们的主要地址映射枢纽。首先,它查找 xyz123@gateway1.calibersys.com。当它找到匹配项时,该地址将更改为 tlowery@calibersys.com。然后它查看 jdoe@vikingfreight.comvikingfreight.com 有三个可能的网关,gateway1gateway2gateway3,分别对应于 Tandem PS Mail、Microsoft Exchange 和 TAO/Emc2。枢纽查找地址,看到 Jane 的邮箱 (jdoe) 在 PS Mail 上,称为 vft1100。因此 mhubjdoe@vikingfreight.com 更改为 vft1100@gateway1.vikingfreight.com。消息头现在看起来像这样

From: tlowery@calibersys.com
To: vft1100@gateway1.vikingfreight.com

然后,枢纽将消息交给 gateway1.vikingfreight.com 以传递到 Jane 的邮箱。现在让我们仔细看看枢纽。

主邮件枢纽是一台配备 133 MHz Pentium 处理器的 Compaq Proliant 1500。备份枢纽是一台配备 75 MHz Pentium 的 Dell OptiPlex。两者都运行 Linux Slackware 3.0 版。运行 Linux 的决定很容易做出。我想要一个可靠、可靠的解决方案,并且成本尽可能低——这意味着基于 Intel 的硬件和 Linux。在过去的三年里,我在各种项目中使用过 Linux,从未遇到过内核崩溃。对于我使用过的所有商业操作系统,我不能这么说。该项目的关键软件是 sendmail,它几乎适用于所有 Unix 变体。我知道如果 Linux 不起作用,我可以换成 Sun、IBM 或 HP 工作站,而无需进行软件更改。将 Linux 用作初始平台的风险非常小。自该项目上线以来的四个月里,我很高兴地说我们没有遇到任何问题。现在是讨论具体细节的时候了。使枢纽工作的两个主要部分是:DNS 和 sendmail。我将依次讨论每个部分。

进入 DNS

以下是 DNS 的简要介绍。如果您已经熟悉它,请随意跳过接下来的几段。

DNS 代表域名系统。它的工作是跟踪网络上每台计算机的名称。与另一台计算机通信的程序需要该计算机的数字地址。如果程序只有名称,它会将该名称提供给 DNS 并请求相应的地址。例如,邮件枢纽必须先获取 gateway1.calibersys.com 的地址,然后才能将邮件传递给它。枢纽向 DNS 请求地址,并被告知类似于 11.22.33.44 的地址。一旦枢纽有了该地址,它就可以联系 gateway1 以传递邮件。DNS 配置文件中充满了如下行

mhub.calibersys.com.        IN A 12.34.56.78
mhub2.calibersys.com.       IN A 12.34.66.88
gateway1.vikingfreight.com. IN A 12.12.12.12

第一列是机器使用的名称。第二列 IN,对于我们的讨论并不重要。第三列 A,表示这是一个地址记录。它只是表示此行将名称映射到地址。第四列包含第一列中命名的机器的地址。除了查找名称并返回地址外,DNS 还可以指示一台计算机接受另一台计算机的邮件。当计算机 A 接受计算机 B 的邮件时,A 被称为 B 的邮件交换器。每当 sendmail 尝试将邮件传递到给定的机器时,它首先查找邮件交换器。如果找不到邮件交换器,则查找常规地址。让我们看一个例子

calibersys.com.    IN MX 10 mhub.calibersys.com.
vikingfreight.com. IN MX 10 mhub.calibersys.com.
shiprps.com.       IN MX 10 mhub.calibersys.com.
roberts.com.       IN MX 10 mhub.calibersys.com.

这些行告诉 sendmail,任何寻址到 calibersys.comvikingfreight.comshiprps.comroberts.com 的邮件都应发送到 mhub.calibersys.com。这就是寻址到 jdoe@vikingfreight.com 的邮件如何路由到枢纽的。第一列可以被认为是机器名称。不必有实际的计算机使用此名称;将其视为用于电子邮件目的的伪机器。它就是您在电子邮件地址中看到的 @ 符号右侧的内容。同样,对于本次讨论,我们不关心 IN。第三列中的 MX 告诉 DNS 这是一个邮件交换器记录。接下来是优先级。一台机器可以有多个邮件交换器,每个邮件交换器具有不同的优先级。我稍后会讨论这个问题。最后,最后一列是充当邮件交换器的机器的名称。任何充当邮件交换器的机器都必须是真正的机器,并且必须具有相应的地址记录。现在让我们谈谈多个交换器。请记住,该项目涉及两个枢纽,一个主枢纽和一个辅助枢纽。主机器是 mhub.calibersys.com,辅助机器是 mhub2.calibersys.com。两者都在 DNS 中列出。请记住,上面的数字 10 指的是优先级。数字越小,优先级越高。假设除了上面的行之外,我们在 DNS 配置文件中还看到了以下行

calibersys.com.   IN MX 20 mhub2.calibersys.com.
vikingfreight.com IN MX 20 mhub2.calibersys.com.
shiprps.com.      IN MX 20 mhub2.calibersys.com.
roberts.com.      IN MX 20 mhub2.calibersys.com.

sendmail 将首先尝试将任何发往 vikingfreight.com 的邮件发送到 mhub,因为 10 表示比 20 更高的优先级。如果失败,它将尝试将邮件发送到备份枢纽 mhub2。在任一枢纽收到消息后,它会查找 jdoe@vikingfreight.com 并将该地址转换为 vft1100@gateway1.vikingfreight.com。然后它将查找 gateway1.vikingfreight.com。它没有为其列出邮件交换器记录,但它确实有地址记录。这意味着 gateway1 接受自己的邮件。以这种方式使用 DNS 将域(例如,mycompany.com)的邮件路由到实际存储邮件的计算机(例如,mail.mycompany.com)是很常见的。这里不同的是地址映射。要了解如何完成地址映射,我们需要查看 sendmail.cf。

关于 sendmail

sendmail.cf 是 sendmail 的配置文件。那么 sendmail 到底是什么?sendmail 是邮件系统的 瑞士军刀。官方名称是消息传输代理 (MTA)。有几种不同的风格;Linux Slackware 3.0 附带的风格称为 Berkeley V8。用户通常不直接与它交互。(该任务留给邮件用户代理或 MUA,如 elm 或 pine。)sendmail 在后台运行,静默地将邮件从一台计算机路由到另一台计算机。它由 Eric Allman 在加州大学伯克利分校于 20 世纪 70 年代和 80 年代编写。由于 Eric 的灵活设计,sendmail 仍然是 Internet 上使用最广泛的 MTA。它是几乎所有基于 Unix 的操作系统的标准发行软件。所有这些灵活性都以复杂性为代价。sendmail 可能是所有 Unix 实用程序中最复杂的。我将介绍 sendmail 的一些功能以及如何使用它们来解决我们的地址映射问题,但对 sendmail 的完整讨论超出了本文的范围。有关更多信息,请参阅资源框。Caliber 邮件枢纽大量使用了三种 sendmail 机制:宏、类和数据库查找。所有这些都在配置文件 sendmail.cf 中指定。sendmail 宏类似于 C 语言宏。主要区别在于宏名称只能是一个字符长。例如,

DG gateway1.vikingfreight.com

将宏 G 定义为 gateway1.vikingfreight.com。其 C 语言等效项为

 #define G gateway1.vikingfreight.com

宏稍后通过指定美元符号后跟宏名称来调用,例如 $G。符号 $G 出现的任何地方,都将被替换为 gateway1.vikingfreight.com。类与宏非常相似。不同之处在于它们可以扩展为多个不同的值之一。例如,

CU xyz123 abc789 def444

定义具有三个值的类 U。或者,sendmail 可以从外部文本文件中读取值

FU /etc/mail/users

如果您想定义具有大量值的类,此功能非常方便。通过指定美元符号,然后是等号,然后是类名称来调用类,例如 $=U。稍后我将解释类是如何有用的。邮件枢纽利用的第三种机制是数据库查找。sendmail 可以查询外部数据库,并将查找键与数据库中找到的值交换。支持几种不同的数据库格式;我们使用 GNU dbm 数据库。这些数据库中的记录只有两个字段。查找键是第一个字段。之后的所有内容都被视为值字段。具有四个记录的 dbm 数据库可能如下所示

xyz123  tlowery
ft1100  jdoe
bc789   asmith
def444  bjones

如果 sendmail 查询数据库以查找 abc789,它将找到值 asmith,并将该值替换电子邮件地址中的 abc789

以上介绍了基本机制。现在让我们看一下配置文件本身。sendmail.cf 中充满了如下行

R$=U@$G  $:$(mapdb $1 $)@$K

这些行被称为 规则。规则分组在一起形成子例程,每个子例程都由 sendmail 调用以执行特定任务。这些子例程称为 集合。它是一种基于正则表达式模式匹配的简洁编程语言。每个规则检查一个电子邮件地址,并可能更改它。规则分为两部分,左侧 (LHS) 和右侧 (RHS),用一个或多个制表符分隔。LHS 是一个模式;sendmail 尝试将当前地址与此模式匹配。如果地址与模式匹配,sendmail 将根据 RHS 的说明重写地址。如果没有匹配,则 RHS 将被忽略。现在让我们从左到右查看我们的示例规则的 LHS

R$=U@$G

R 只是声明这是一个规则。所有规则都以字母 R 开头。接下来的三个字符 $=U,是对类的引用。给定上面的类定义,$=U 将成功匹配 xyz123abc789def444。如果地址以任何其他字符串开头,则匹配将失败。下一个字符是文字 @。该字符必须出现在地址中才能发生匹配。接下来的两个字符 $G, 是宏引用。宏扩展为

gateway1.calibersys.com

地址 xyz123@gateway1.calibersys.com 将与模式匹配,并且将调用 RHS。tza555@gateway1.calibersys.com 将不匹配,因为 tza555 不是 U 类的成员。同样,xyz123@gateway2.calibersys.com 将不匹配,因为 gateway2.calibersys.com 不是 G 宏的值。现在让我们继续 RHS,看看如何重写地址。我们的示例规则的 RHS 是这样的

$:$(mapdb $1 $)@$K

前两个字符 $: 告诉 sendmail 仅调用此 RHS 一次。默认情况下,只要结果仍然与 LHS 匹配,sendmail 将重复调用 RHS。接下来是字符串,

$(mapdb $1 $)

它执行数据库查找,告诉 sendmail 查找名为 mapdb 的数据库并搜索 LHS 中的第一项。$2 将搜索第二项,依此类推。我们 LHS 的第一个匹配项是 xyz123。然后 sendmail 搜索该字符串并找到 tlowery,因此它在地址中将 xyz123 替换为 tlowery。RHS 中的下一个字符 @ 是文字。它在 tlowery 之后写入新地址。接下来是 $K,宏引用。假设宏 K 的定义如下

DK calibersys.com

sendmail 将在新地址中的 @ 之后放置 calibersys.com,完成重写过程。

由此我们可以看到如何将 xyz123@gateway1.calibersys.com 的私有地址转换为 tlowery@calibersys.com 的公共地址。消息的接收者永远不会知道原始发送者地址不是公共地址。从公共地址切换到私有地址也可以通过类似的方式完成。对地址映射的讨论只是冰山一角;sendmail 的灵活性可以帮助电子邮件管理员解决几乎任何邮件路由任务。

结果

邮件路由枢纽已在 Caliber 运行约三个月,在此期间,它路由了超过 48,000 条消息。根据当前的流量统计数据,我预计它在第一年将处理约 600,000 条消息。幸运的是,我们遇到的一些问题是由于配置问题造成的。很容易在这里遗漏一个句点或在那里遗漏一个美元符号。Linux 和 sendmail 运行完美无缺。

在理想的世界中,不需要这种解决方案。如果 Caliber 公司仅使用一个通用的电子邮件平台,则无需查找邮箱名称并将消息路由到正确的网关。但是,许多大型公司都有许多遗留系统,这些系统在短期内不会消失。这些正是 sendmail 等工具发挥最佳作用的环境类型。由于网络物流和地理位置的原因,我们将继续使用一些遗留邮件系统,直到 1998 年。与此同时,我们的 Linux 电子邮件枢纽将继续处理消息,在不同的平台之间路由它们,并帮助我们满足用户日益增长的期望。

边栏:DNS 和 Sendmail 资源

Tom Lowery (tlowery@calibersys.com) 是 Caliber Technology 的电子邮件和群件开发项目经理。

加载 Disqus 评论