电子邮件无法发送到500英里以外

这个故事最早出现于2002年11月24日,而且每过若干年,它就会在不同的系统管理技术社区中再次出现,并且引发人们的热议和关注。有人对这个故事给出了这样的评价:

这个故事大约每过三年或四年就会在系统管理社区出现,每次我读到它,都觉得很值得一读。即便在正常环境下已经做过检查,甚或经过片刻思考之后,我还是高度怀疑这种事情是否会发生在自己身上。

这是一个真实的故事。如果你想要进一步了解它的相关信息,可以访问这个FAQ - 一个关于本故事的常见问题列表,由本故事作者 Trey Harris 编写。

这个故事听起来有点儿天方夜谭的感觉... 我已经有些后悔把这个故事分享给大家了,因为它很可能会沦为众人茶余饭后的谈资。:-) 为了保护自己的内疚感,我对故事做了稍许改动,省略了无关紧要以及无聊的细节,总之让故事变得更加生动有趣了。

几年以前,我在一家运营校园邮件系统的公司工作。有一天,我接到了来自统计部主任给我的电话。

“我们的邮件系统存在一个问题。”

“什么问题?” 我问道。

“我们不能发送超过500英里距离的邮件,” 主任解释说。

我被手中的拿铁咖啡呛着了。“再说一遍?”

“我们不能把邮件发送到超过500英里距离的地方,” 他重复道。“真的,哪怕再远一点点。只能到达520英里,不能再远了。”

“嗯...通常来说,邮件真的不是按照这种方式来发送的,” 我说道,并尽力让自己的声音平静下来。一个人与部门主任谈话时通常不会带有恐慌情绪,即使是一个相对无实权的部门如统计部。“是什么让你认为邮件不能发送超过500英里之外的?”

“并非我这么认为,” 主任不耐烦地回答道。“你瞧,几天之前我们就发现了这一现象...”

“你等了好几天了?” 我打断他的话,声音有些颤抖地问道,“这段时间你都不能发送邮件吗?”

“我们能发邮件,只要不超过...”

“500英里,是吧,” 我替他补充道,“我知道了。但是为什么你不早点给我电话呢?”

“好吧,问题是直到刚才,我们才收集到足够的证据确定这一现象的发生。” 也对,他是统计部主任。“总之,我让一名地理统计人员去调查了这件事情...”

“地理统计人员...”

“是的,她制作了一张地图,地图上显示我们能发送邮件的区域半径比500英里多那么一点点。即便如此,这个半径区域之内的有些地方也不能发送,或者偶发性地能发送,但是在半径区域之外从来没有发送成功过。”

“我明白了,” 我说道,“何时开始的?你说几天之前,那么这段时间内系统发生什么改变了吗?”

“是的,技术服务人员来过,给服务器打了补丁然后重启了系统。但是我给他去过电话,他说他没碰邮件系统。”

“好的,我先看看吧,然后再给你打过去,” 我说,几乎不相信我也会来虚与委蛇这一套。今天不是愚人节啊。我试着去回忆,是不是有人欠我一个恶作剧。

我登进他们部门的服务器,发了一封测试邮件。这是发送到北卡罗莱纳州的三角研究实验,测试邮件很顺利地到达我的邮箱。同前面一样,我又发送到里士满、亚特兰大、华盛顿,还有普林斯顿(400英里),都能顺利到达。

但是当我尝试发送邮件到孟菲斯(600英里)时,却失败了。发往波士顿,失败了。发往底特律,同样是失败。我拿出我的地址薄,开始试图缩小范围。纽约(420英里)可以发送,但是普罗维登斯(580英里)就失败了。

我开始困惑,是不是我失去了理智。我试着给我一位居住在北卡罗来纳州的朋友发送邮件,他的 ISP(网络服务提供商)在西雅图。谢天谢地,发送失败了。如果这个问题只和收件人的居住位置有关,而不是和他(她)的邮件服务器有关的话,我想我真该泪奔了。

问题得以确认,尽管令人难以置信,但问题确实存在而且可以重现。我查看了 sendmail.cf 文件,它看起来很正常,没有任何问题。事实上,它看起来很熟悉。

我将这个文件和我本机 home 目录下的 sendmail.cf 文件进行了比对。二者没有什么不同,这个文件就是我自己写的。我也确信没有启用 “FAIL_MAIL_OVER_500_MILES” 这一选项。带着满腹困惑,我远程登录到 SMTP 端口。服务器使用一个 SunOS sendmail 标识愉快地做出了响应。

等等... 一个 SunOS sendmail 标识?在那时,Sun 仍然随同操作系统捆绑发布 Sendmail 5 版本,尽管 Sendmail 8 已经相当成熟了。作为一名优秀的系统管理员,我已经把 Sendmail 8 作为一个标配了。同时,作为一名优秀系统管理员,我写了一个 sendmail.cf 配置文件,使用了 Sendmail 8 中优雅详细且自我描述的选项和变量名,而不是 Sendmail 5 中含义模糊的标点符号标记的代码。

一切都水落石出了,突然间,我被那杯现已冷的掉渣的拿铁咖啡再次被呛到了。当那名技服给服务器打补丁的时候,很显然他也升级了 SunOS 的版本,如此一来自然把 Sendmail 的版本“降级”了。升级程序将 sendmail.cf 配置文件单独保留了下来,即使它现在对应的是错误的版本。

碰巧的是 Sendmail 5(至少 Sun 发布的版本,或许做过一些调整)可以处理 Sendmail 8 的 sendmail.cf 配置文件,因为大多数的规则在那时并没有改变。但是对于那些在 Sendmail 8 中新增的长配置项,Sendmail 5 将之视为垃圾而忽略掉了。sendmail 的二进制安装包对大多数选项没有提供默认值,因此,如果在 sendmail.cf 中找不到合适的设置,它们就会被设为0。

这些被设为0的选项之一就是连接远程 SMTP 服务器的超时时间。一些试验已经证实,在一个具有典型负载的特定机器上,零超时意味着如果连接时间稍微超过3毫秒,服务器就会终止连接。

当时我们的校园网络有一个很奇怪的特点,它是百分之百交换型网络。发送出去的数据包,在遇到 POP 服务器和远端路由器之前,不会出现路由器延迟。因此,连接到临近网络上负载较轻的服务器所花的时间,很大程度上是由光速决定的,而不是偶发的路由器延迟。

这可真是让人有点儿眼花缭乱啊,我在 shell 里敲入如下代码:

$ units
1311 units, 63 prefixes
You have: 3 millilightseconds
You want: miles  
        * 558.84719
        / 0.0017893979
“500 miles, or a little bit more.”

作者:Trey Harris,高级系统工程师,拥有丰富的 UNIX/Linux、Perl、系统架构以及软件集成经验。

原文:The case of the 500-mile email

感谢:Jodoo帮助审阅并完成校对。

来源:http://blog.fujiji.com/the-case-of-the-500-mile-email