铸造车间 - 集成电子邮件

作者:Reuven M. Lerner

我已经使用电脑与他人交流超过 20 年了。最初只是偶尔参与本地公告栏上的论坛,现在已经成为我个人和职业生活中不可分割的一部分。我每天从朋友、亲戚和同事那里收到的如潮水般的电子邮件,常常让人感到不堪重负——直到我有一段时间无法访问电子邮件,这时我才意识到它究竟有多么重要和有用。

本月,当我继续在芝加哥的新家整理东西,并与那些让我难以继续讨论 Bricolage 的漏洞和故障作斗争时,我将关注现代电子邮件时代的一些不同问题——Web/邮件集成、邮件/数据库集成,甚至是在 SMTP 级别对抗垃圾邮件。

集成 Web 和电子邮件

在过去的两年里,至少有十几位客户要求我建立基于 Web 的论坛。事实上,在大型现代网站中,没有用户反馈或参与版块的情况很少见。问题是,如何将论坛融入到您的网站中?在许多情况下,答案取决于您运行的网站类型。

如果您使用的是大型工具包,例如 OpenACS、Zope 或 PHPNuke,则至少有一个论坛包可用于轻松安装到您的网站中。它不仅在外观和感觉上与静态页面和其他应用程序紧密集成,而且这些工具包还允许您在网站其余部分设置的相同用户和权限访问论坛。换句话说,您不必分别让某人成为网站管理员和论坛管理员;任何拥有网站管理权限的人都能够运行论坛或任何其他应用程序,而无需进一步配置。

或者,您可以使用服务器端技术在您的服务器上安装一个单独的 Web 论坛包。例如,如果可以使用 PHP,您可以安装 Phorum 包。它不会完全集成到您网站的其余部分,但 Phorum 是一个强大而稳定的包,可以与 MySQL 和 PostgreSQL 一起使用。有很多选项可供选择,底层技术从 PHP 和 JSP 到用 Perl 编写的普通 CGI 程序不等。

您也可以走专有路线,并许可诸如 WebCrossing 之类的软件包。我曾为一些客户使用过 WebCrossing,虽然这个软件包提供的功能比 Phorum 等开源产品多得多,但在大多数情况下,这些差异还不足以证明花钱是值得的,更不用说学习一个无法修改或改进的软件包了。

最后,您可以像我在几年前的专栏中所做的那样,自己开发论坛包。编写一组实现基于 Web 的论坛的程序并不困难,但开发和调试所花费的时间和精力最好用于学习现有的软件包。但是对于任何有 Web 和数据库经验的人来说,制作 Web 论坛包意味着只需创建几个表(用于用户、消息和主题),然后让人们能够将新记录(帖子)插入到每个主题中。

对于典型的中小型网站来说,所有这些系统都绰绰有余。即使您的网站规模扩大,有成千上万的用户发布了数千条消息,它也不太可能对这些系统造成负担。这是因为这些系统都使用关系数据库来存储消息,即使是最小和最简单的现代数据库服务器也可以处理每天数千次的事务。

然而,在越来越多的情况下,一个简单的基于 Web 的论坛是不够的。虽然人们可能愿意浏览基于 Web 的论坛,但他们可能不会日复一日地返回论坛以跟踪讨论。电子邮件是一种推送媒介,信息会发送给您,而论坛是一种拉取媒介,新消息等待您去请求它们。

推送和拉取并不是一个新问题;我们这些记得 Web 之前互联网的人都知道,讨论过去是在邮件列表和 Usenet 新闻组之间划分的。解决方案是创建各种邮件到 Usenet 的网关,其中许多网关至今仍在使用。事实上,您可以通过订阅 bug-gnu-emacs 邮件列表或阅读 Usenet 上的 gnu.emacs.bug 新闻组来跟踪 GNU Emacs 中的最新错误。两者是等效的,通过网关软件促进,该软件在两个系统之间传输消息,而不会产生不必要的重复。

对于基于 Web 的论坛,是否存在任何此类系统?答案是暂时的肯定。毕竟,当发布新消息时,Web/数据库系统很容易向电子邮件地址列表发送邮件。创建一个复杂的通知系统并不难,OpenACS 论坛包中提供了这种通知系统,它允许用户订阅特定的论坛或论坛中的主题——然后选择立即或按日或按月接收更新。换句话说,论坛软件能够创建电子邮件摘要,就像列表软件一样。

发布邮件

然而,当您想让论坛参与者使用他们自己的电子邮件软件向列表发布新消息时,事情变得有点棘手。特别是,必须解决以下几个问题:

  • 安全性和权限——应该允许任何人发布或回复论坛,还是只允许会员?如果对论坛的访问受到某种限制,则有必要跟踪允许的电子邮件地址。当然,伪造电子邮件标头非常容易,这意味着不可能完全验证帖子是否真的来自订阅者,而不是来自冒充订阅者的蠕虫或病毒。

  • MIME——大多数流行的电子邮件程序,尤其是 Microsoft Outlook,默认情况下会发送带有一个或多个附件的邮件。论坛软件必须足够智能,能够处理以这种格式发送的帖子,剥离 HTML 和附件。

  • 大小——如果邮件到论坛的网关不够智能,无法过滤掉超大的帖子,那么有人可能会通过提交超大的帖子来对您的网站发起拒绝服务攻击。该软件需要足够智能,能够过滤掉这些邮件,并允许网站管理员限制用户帖子的大小。

  • 主题串联——大多数论坛软件将相关的帖子放在一起,要么按主题标题,要么通过跟踪哪个帖子是对另一个帖子的回复。在结合 Web 和电子邮件时,要跟踪这一点是困难但又有些可能的,因为每种媒介都使用不同的机制来跟踪此类事情。

我已经看到许多不同的方法来处理这些和其他问题。到目前为止,我还没有看到任何让我完全满意的。

Phorum 提供了一个名为 phorummail 的脚本,该脚本旨在从命令行调用,大概是从 .forward 或 .qmail 文件或包含邮件别名定义的文件中调用。基本上,系统管理员在系统上创建一个别名(例如,apartments-forum),并将 .forward 文件设置为指向 phorummail,传递强制的 FORUM_ID 参数和可选的 PATH_TO_FORUM 参数。完成此操作后,任何向 apartments-forum@your.site 发送邮件的人都可以发布到论坛。显然,必须正确设置权限才能使 phorummail 工作。

问题在于帖子的安全性不高;虽然,如果论坛是经过审核的,则通过邮件发起的帖子将被标记为未批准,直到版主审核它们为止。主题串联以多种巧妙的方式处理,但似乎没有任何处理 MIME 或邮件炸弹攻击的规定。换句话说,Phorum 以您可能期望的方式处理邮件到论坛,但没有花哨的功能。

OpenACS 论坛软件包含一个更复杂的基于 qmail 的系统,其中每个传出的通知消息都从唯一的标识符发送。这意味着对电子邮件消息的回复将提交到相关的论坛。OpenACS 使用电子邮件地址作为登录名这一事实增加了一点安全性,但事实仍然是,很难阻止人们伪造消息。

邮件列表和数据库

我可以提供的最佳解决方案是将事情颠倒过来,将基于 Web 的论坛变成现有电子邮件列表的分支。ezmlm,由 qmail 作者 Dan Bernstein 编写的邮件列表包,有一组称为 ezmlm-idx 的扩展,除其他外,它允许将订阅者列表存储在 MySQL 或 PostgreSQL 中。配置列表时,管理员还会配置一些数据库表,然后将 ezmlm 指向这些表。

这意味着一位优秀的 Web 开发人员可以创建一个电子邮件列表,然后将该列表镜像到 Web。来自 Web 的任何内容都似乎来自当前登录的用户,该用户大概必须登录到基于 Web 的论坛应用程序。来自实际用户的任何内容都将通过 ezmlm 通常应用的相同检查。

Mailman,一个与所有 MTA(包括 qmail、Sendmail、Postfix 和 Exim)一起工作的邮件列表程序,并且正在进行持续且令人印象深刻的开发,似乎还没有任何用于将其用户存储在关系数据库中的钩子。但是,它确实将它们存储在相对安全、易于使用的 Berkeley DB 文件中,这使得基于 Web 的论坛包可以轻松地从那里读取它们。

将论坛视为电子邮件列表来处理会产生一些问题,首先是上面提到的主题串联问题,这在电子邮件和 Web 中是不同的。此外,许多论坛允许用户添加高亮显示和附件,甚至编辑自己的帖子,并且很快就会变得明显,这种婚姻将是困难的——如果您愿意,可以说这两种媒介之间存在阻抗不匹配。

然而,对于大量愿意忽略边缘问题的人来说,该功能足够有用。相反,他们专注于增加论坛的参与者数量,并为用户提供关于他们如何参与这些论坛的选择。

qpsmtpd

和你们中的许多人一样,我每天都受到大量垃圾邮件的困扰。SpamAssassin,用于分析和分类传入电子邮件的开源工具,已被证明是我对抗垃圾邮件的优秀盟友。如果您曾经运行过电子邮件列表,您无疑会发现电子邮件蠕虫不会区别对待;它们像向个人发送邮件一样容易地发布到列表。

虽然系统管理和 SMTP 服务器对于本专栏来说有点离题,但我还是忍不住要赞扬一下 qpsmtpd,这是由 Ask Bjoern Hansen 开发的开源 SMTP 服务器。qpsmtpd 最初是为与 qmail 一起使用而设计的,但现在显然能够与其他 MTA 一起工作,包括 Sendmail 和 Postfix。

为什么要插入 qpsmtpd 而不是默认的 qmail-smtpd?如果您是 Perl 黑客,那么切换的原因是 qpsmtpd 是用 Perl 编写的。但如果您不是语言偏执狂,您仍然可以找到很多值得喜爱的地方。这是因为 qpsmtpd 将 SMTP 的邮件发送例程划分为多个阶段,并允许您向每个阶段添加自己的钩子和功能。

我从 www.develooper.com(是的,连续两个 O 字符)的家下载了 qpsmtpd,按照安装说明进行操作,大约 20 分钟后就启动并运行了。请记住,qpsmtpd 是一个功能齐全的 SMTP 服务器,这意味着如果您有另一个 SMTP 服务器在端口 25 上侦听,它将拒绝运行。如果您一直使用 daemontools 来确保 SMTP 服务器在启动时启动并在之后保持运行,您应该仔细检查从 /service 到旧 SMTP 服务器是否不存在链接。否则,当您的机器下次重新启动时,您可能会最终得到两个竞争的 SMTP 守护进程。

qpsmtpd 的关键在于其插件,这些插件位于插件子目录中。您可以通过修改 config/plugins 文件来添加或删除插件,每行列出一个插件。例如,我的 config/plugins 文件的一部分如下所示:

# quit_fortune

check_earlytalker
count_unrecognized_commands 4

require_resolvable_fromhost

换句话说,我注释掉了 quit_fortune 插件,但激活了 check_earlytalker、count_unrecognized_commands 和 require_resolvable_fromhost 插件。count_unrecognized_commands 接受一个数字参数,我们在此处提供了该参数。

要查看这些插件或添加您自己的插件,请进入插件目录本身。每个插件都包含一个 register 子例程,该子例程将插件附加到 qpsmtpd 的各种钩子之一,以及另一个由钩子调用的子例程。例如,require_resolvable_fromhost 插件以以下内容开头:

use Net::DNS qw(mx);

sub register {
  my ($self, $qp) = @_;
  $self->register_hook("mail", "mail_handler");
}

换句话说,register 子例程告诉 qpsmtpd,每当 SMTP 客户端调用 mail 命令时,也应该调用 mail_handler 子例程。该子例程执行以下操作:

sub mail_handler {
  my ($self, $transaction, $sender) = @_;

  $sender->format ne "<>"
    and $self->qp->config
       ("require_resolvable_fromhost")
    and !check_dns($sender->host)
    and return (DENYSOFT,
       ($sender->host
        ? "Could not resolve ". $sender->host
        : "FQDN required in the envelope sender"));
   return DECLINED;
}

如果您在 mod_perl 中做过任何 Web 开发,那么这应该对您来说有点熟悉。mail_handler 可以返回 DECLINED,这表明一切正常,邮件可以正常发送。或者,它可以返回 DENYSOFT,这允许发送者稍后重试。发生这种情况是因为我们不想在 DNS 服务器宕机时开始拒绝邮件;我们只对惩罚垃圾邮件发送者和其他不应该直接发送邮件的人感兴趣。我们也可以返回 DENY,这将完全拒绝邮件。

尽管缺乏良好的文档,但我还是在下载 qpsmtpd 后的几个小时内编写了一个新的、可工作的插件,我相信许多其他读者也会有类似的经历。qpsmtpd 是用 Perl 编写的这一事实意味着您可以快速、轻松地访问常用 Perl 程序可以访问的所有内容,以及任何可以使开发更容易的 CPAN 模块。

您可以将插件附加到许多不同的钩子,包括 helo、ehlo、connect 甚至 rcpt——每个钩子都可以执行各种类型的测试。甚至还有一个用于 qpsmtpd 的 SpamAssassin 插件,它会在邮件到达您的邮箱之前调用著名的垃圾邮件检查软件。

我已经使用 qpsmtpd 大约一个月了,我邮箱中的垃圾邮件数量已经非常显着地下降了,甚至比 SpamAssassin 放过的少量垃圾邮件还要低。如果您运行自己的机器,我强烈建议您查看 qpsmtpd。它是如何编写软件以接受任意插件的一个很好的例子,作为奖励,您将只收到您应该收到的邮件。

结论

电子邮件是互联网的重要组成部分,任何阅读本专栏的人无疑都知道这一点。但随着互联网的不断扩展,电子邮件正朝着许多不同的方向发展。本月,我们研究了基于 Web 的论坛以及我们可以将它们连接到电子邮件列表的一些方法。我们还简要介绍了 qpsmtpd,这是一种旨在高度可扩展和可配置的替代 SMTP 服务器。下个月,我希望回到 Bricolage 和其他开源内容管理系统,重点是如何将 CMS 整合到您现有的网站中。

资源

您可以在以下各自的网站上了解更多关于本月讨论的各种开源软件包的信息:www.OpenACS.orgwww.Zope.orgwww.Phorum.org。本月提到的开源数据库可在 www.mysql.comwww.postgresql.org 上获得。

有关 qmail 和 ezmlm 的信息,请查看 www.qmail.orgwww.ezmlm.org。后一个站点包含有关 ezmlm-idx 的信息,该扩展允许您将 ezmlm 连接到关系数据库,以及其他内容。

qpsmtpd 可从 www.develooper.com 获得。有关 qpsmtpd 问题和黑客技术的邮件列表可在 nntp.x.perl.org/group/perl.qpsmtpd 上获得。

最后,您可以从 www.spamassassin.org 下载 SpamAssassin。

Reuven M. Lerner,一位在 Web/数据库编程领域长期从事咨询工作的顾问,现在是芝加哥西北大学学习科学专业的研究生。当他在九月份写这篇文章时,他仍然希望芝加哥的冬天不会与以色列的冬天有太大不同。

加载 Disqus 评论