第十三章:用筛子过滤

第十三章:用筛子过滤配置 PigeonholeManageSieve 客户端使用 SieveSieve 规则集邮件列表地址主题拒绝更难拒绝隐式保留调试和测试规则服务器范围规则

如果你运行自己的邮件系统,你可能会收到大量的邮件。有些客户端会为你过滤。例如,Thunderbird允许您定义规则,以便在连接到服务器时,它将新邮件重新排列到文件夹中。然而,IMAP允许客户端从任意数量的机器连接,在手机、平板电脑和台式机上保持相同的规则很烦人。过滤邮件的最佳位置是当本地传递代理将邮件发送到邮件存储时。

Sieve 是一种服务器端邮件过滤语言,在RFC 5228中定义,并记录在http://sieve.info。Sieve可以将收到的邮件列表消息分类到自己的文件夹中,转移垃圾邮件,发送度假回复等等。Sieve是一种强大的过滤语言,虽然不像完整的编程语言那么复杂,但它确实需要技能。您编写Sieve规则并将其上传到邮件系统,邮件系统会编译并应用它们。一个单独的协议 ManageSieve 允许客户端添加、编辑和删除Sieve规则。ManageSieve客户端可以集成到邮件客户端中,也可以独立使用。您甚至可以将Manageieve与 openssl s_client 一起使用。Sieve支持特定用例的许多复杂功能。我们将重点介绍根据邮件头和地址将邮件分类到文件夹中的常见情况。

使用Sieve需要安装Sieve引擎并将其与您的本地交付代理集成,启用ManageSieve服务器,并为用户提供客户端。Dovecot通过鸽子洞(Pigeonhole)支持Sieve和ManageSieve(https://pigeonhole.dovecot.org/)。Roundcube包括一个ManageSieve客户端。一旦你有了这些,你就可以写Sieve规则了。

配置 Pigeonhole

几乎所有具有Dovecot包的Unix都提供Pigeonhole。安装后,在 doveco.conf 中配置Pigeonhole。首先在dovecot的 protocols 列表中添加 sieve

现在配置Sieve协议:

managesieve_max_line_length 选项告诉Dovecot要在Sieve脚本上设置哪些限制。编写单行长度超过65536个字符的Sieve脚本的用户需要休息一段时间来考虑他们糟糕的生活选择。

ManageSieve服务器通常支持特定于实现的扩展。告诉ManageSieve客户他们正在与Dovecot交谈,以便他们可以使用正确的扩展。Pigeonhole使用扩展来实现度假回复和处理重复项等功能。一旦你有了一个功能性的基本系统,你就可以调查这些。

我们正在传递身份验证字符串,因此将 ssl 设置为 yes 以要求STARTTLS。

启用筛选协议后,我们可以将ManageSieve服务连接到网络。TCP端口4190是标准端口:

现在配置Pigeonhole存储Sieve规则的位置:

sive 选项告诉Pigeonghole在哪里查找包含用户的Sive规则的文本文件。波浪号(~)代表用户的主目录。如果此文件不存在,则用户没有使用Sieve。这显示了两个值。 ~/sieve 设置意味着所有用户的脚本都存储在他们的 sieve 目录中。在这些规则中,有一个脚本文件处于活动状态。文件 ~/.dovecot.sieve 是活动脚本的符号链接。更改筛选规则只需要更改符号链接。要禁用用户的过滤规则,请删除符号链接。

sieve_default 定义了默认的Sieve规则。Pigeonhole仅在用户没有个人筛选规则时使用默认规则。

sieve_before 选项允许您在处理默认或个人规则之前设置Pigeonhole应用于所有用户的Sieve规则。在这里,您可以放置适用于所有用户的垃圾邮件和病毒隔离规则。我们将对此进行讨论。

最后,告诉LMTP使用Sieve:

重新加载Dovecot。确认 dovecot 正在监听端口4190,日志显示sieve已启用。现在,您可以连接到客户端。

ManageSieve 客户端

Sieve网站列出了许多适用于Unix、MacOS和Windows的ManageSieve客户端。Emacs有一个客户端,所以你可以在任何现代平台上管理你的规则,也可以在大多数被遗忘的平台上管理。你可以把空闲时间花在探索客户端上,但现在我们将使用Roundcube客户端。通过Roundcube登录您的测试帐户,然后转到Settings -> Filters。 Actions按钮将允许您编辑默认的Roundcube过滤器,或添加新的过滤器并对其进行编辑。无论哪种方式,您都会得到一个带有文本编辑器的面板。在文本编辑器中编写规则并保存。您可以有多组规则,但一次只能有一组处于活动状态。使用 Action 按钮启用或禁用规则集。

无论您最终使用哪个客户端,Sieve规则的基础知识都适用。

使用 Sieve

Sieve是一种用于编写邮件过滤规则的模块化语言。它支持简单的 if-then 决策、标题检查和将邮件分类到文件夹中。但是,为了在复杂的电子邮件系统上安全使用,它不能访问系统调用或运行任意命令。

规则集(rule sets)是Sieve的关键部分。你可能有一套工作时间规则和另一套下班时间规则。一次只能有一个规则集处于活动状态。规则集保存在用户的 sieve 目录中。Pigeonhole将所有规则集放置在以规则集命名的文件中,扩展名为 .sieve 。当前活动的规则由用户主目录中的 .doveco.sieve 符号链接标识。

Sieve是一种编译语言。当Dovecot向用户传递消息时,它会检查用户的主目录,查看 .dovecot.sieve 是否存在。如果该文件存在,它会将文件的修改日期与编译后的规则文件( .dovecot.svbin )上的时间戳进行比较。如果文本文件比编译的规则新,或者没有编译的规则,Pigeonhole会编译规则并使用它们对新邮件进行排序。如果没有 .dovecot.sieve 文件,Dovecot会将所有收到的邮件转储到用户的收件箱中。

不要就地编辑Sieve规则文件。是的,您有shell访问权限,可以在文本编辑器中调用该文件。经验丰富的系统管理员经常保存他们的工作。未编译的半编辑规则文件会产生错误,但缺少重要功能的半编辑的规则文件会更糟。在客户端或单独的文件中编辑规则,并将文件交换到位。如果你想通过命令行管理Sieve规则,比如自动化,可以研究 doveadm-sieve(1)

Sieve 规则集

Sieve规则集有两部分:能力声明和为使用这些能力而编写的规则。

Sieve本身只包含基本逻辑。用户可能想要过滤的所有内容都通过功能得到支持。将邮件归档到文件夹中?这是一种能力。创建新邮箱?另一种能力。您的规则必须从规则所需的功能列表开始。功能(capabilities )有时被称为扩展(extensions),尽管“扩展”一词也用于描述添加到语言中的新功能。IANA在其“Sieve Extensions”文档中维护了一个Sieve能力的中央目录(https://www.iana.org/assignments/sieve-extensions/sieve-extensions.xhtml)。然而,这里有一些常见的功能。

下面示例中,我声明此规则集使用 fileintomailbox 功能:

如果编写的规则使用了require语句中未列出的功能,则这些规则将无法编译。

在此之后,我们有了实际的规则。Sieve允许您构建处理无数边缘情况的复杂规则,但我们大多数人永远不会使用它们。Pigeonhole包括几个示例Sieve规则集,如果你感兴趣,应该复习一下。Sieve网站包括该语言的正式定义。我将讨论常见的用法。

邮件列表

我最常用的服务器端过滤是邮件列表。我订阅了相当多的列表,我希望每个邮件列表都能被整理到自己的文件夹中。最佳实践要求邮件列表在发送的每条消息中添加一个 List-Id 标头,以标识列表。您可以使用此标头将这些邮件排序到文件夹中:

第一行声明我们正在查看消息头。:contains 给出了我们正在执行的测试类型。所有筛选测试和选项都以冒号开头。我们正在测试内容 freebsd-arch.freebsd.org 的头部 List-ID 。这些检查不区分大小写。如果此标头存在并包含该字符串,则测试成功,Sieve将执行大括号中的说明。

大括号内的第二行使用 fileinto 功能将消息发送到文件夹 arch:create 选项告诉Sieve在文件夹不存在的情况下创建文件夹。

冒号仅用于Sieve说明。永远不要在标题名称中包含冒号。由于冒号,对标题 List-Id: 的测试将始终失败。

您可能会遇到文档中说,上面说所有文件夹都应该是收件箱(inbox)的子文件夹,比如 INBOX.arch 。这是Cyrus IMAP的一部分,与Dovecot无关。

地址

您可能希望将某些人的电子邮件放在他们自己的文件夹中。也许你想把你妈妈的所有邮件都放进一个文件夹里。或者,也许有一些你永远不想听到的烦人的推特。

address 关键字声明我们正在检查地址。我们想要一个精确的匹配,所以我们使用 :is 。此规则测试来自的电子邮件是否与 mwl@mwl.io 匹配。如果测试成功,也就是说,如果它们匹配,我们使用 fileinto 将消息发送到 Trash 文件夹。

Sieve支持使用 :localpart:domain:all 参数进行更细粒度的地址匹配。 :localpart 参数匹配 @ 符号左侧的所有内容,而 :domain 匹配右侧的所有内容。假设你发现我有一大堆域名,但我在所有域名上都使用了用户名 mwl

与此同时,亚马逊一直在给你发邮件。你需要收据和订单确认,但不需要它们弄乱你的收件箱。它们使用许多不同的电子邮件地址,因此您希望将该域中的所有内容都放入自己的文件夹中。

你也可以扭转这种局面。假设您有来自另一个帐户的电子邮件转发到您的主帐户。你希望这些电子邮件进入他们自己的文件夹。测试 to 域而不是 from 域:

通过比较发件人和收件人地址以及标题字段,您可以在任何您喜欢的地方对电子邮件进行排序。

主题

某些话题会让最善意的人考虑加入坏人的行列。您可能希望根据主题筛选邮件。使用类似于邮件列表的规则来执行此操作,但要测试Subject标头。在这里,我测试任何包含 “nagios” 的主题字段:

我无法自动删除这些消息,因为管理层偶尔会问我是否收到了它们。我必须手动输入文件夹并将其全部删除。

拒绝

假设将某人的电子邮件发送到垃圾箱是不够的。你想让他们知道你在拒绝他们。Sieve具有拒绝能力。匹配地址,然后使用带有引号的消息的 reject 操作:

这将生成一封包含您的邮件的新电子邮件,附加原始邮件,并将其发送回发件人。新邮件来自您域名的 postmaster@ 帐户,而不是您的个人帐户,因此看起来很正式。

切勿对垃圾邮件使用reject。Sieve是在Postfix接受邮件后进行的。大多数垃圾邮件的源地址要么被伪造为不存在的帐户,要么被伪造成垃圾邮件发送者不拥有的真实帐户,要么是一次性帐户。如果你的规则拒绝了一千条垃圾邮件,那就是你的MTA发送的一千条消息。如果垃圾邮件源是伪造的,Postfix将花费数天时间尝试传递所有无法传递的邮件。如果垃圾邮件源是一次性帐户,您的服务器将把这数千封邮件转储到另一个提供商上。如果垃圾邮件来源是一个伪造的真实账户,那么你就是在把邮件扔给一个无辜的旁观者。第一种方法为系统管理员带来了更多的工作。最后两个增加了阻止列表维护者将您的服务器添加到其列表中的机会。

更难拒绝

你确定你不想要那条信息吗?你甚至不想把它扔进垃圾桶?使用 discard 而不是 fileinto

一定要。用户将不会收到此消息的通知。

隐式保留

Sieve假设你想要你的电子邮件。每个规则集都以 implicit keep 结尾。如果Sieve没有过滤、折叠或损坏电子邮件,它就会进入用户的收件箱。

如果您认为应该过滤的邮件开始出现在您的收件箱中,则发件人更改了发送邮件的方式。

调试和测试规则

如果在 dovecot.conf 中将 mail_debug 设置为 yes ,Pigeonhole将记录它发送消息的位置。这对系统管理员来说是件好事,但普通用户会发现,当邮件进入inbox而不是文件夹时,他们的Sieve规则就被打破了。如果Sieve脚本无法编译,Pigeonhole会记录“编译脚本失败”消息,其中包括用户Sieve调试日志的位置。查看Sieve编译器错误日志。

正如你所看到的,Sieve坚持了历史悠久的编译器传统,不告诉你任何有用的东西。所有这一切都表明,你在第11行或之前犯了错误。

调试Sieve规则的最佳方法是在服务器上安装之前。您可以在网上找到Sieve规则验证器。libsieve-php项目包括一个Sieve验证器,您可以在自己的网站上安装。但是,您可以在命令行中使用Sieve编译器 sievec(1)

这将创建 test.svbin 二进制文件或编译器错误。如果您希望明确声明编译已成功,请为调试输出添加 -D 标志:

编写Sieve规则只是问题的一半。你怎么知道规则是按照你想要的方式运作的?使用 sieve-test(1) 。Maildir格式将所有邮件保存为单独的文件。将要筛选的邮件复制到方便的位置。将您的Sieve规则集也复制到那里。作为无特权用户,运行:

sieve-test 命令编译规则集并通过过滤器运行消息。在这里,我尝试了我的测试规则,看看Sieve会把最初发送到我的一个邮件列表的消息放在哪里:

此命令用于调试,因此它会打印几行内部详细信息。Performed Actions 行显示了过滤器对消息的处理方式。此邮件将被路由到 f-arch 文件夹。 Implicit keep 部分告诉我们邮件是否进入了用户的收件箱。

我将要筛选的每种邮件的一份副本存储在一个文件夹中。每当我需要更改我的筛选规则时,我都会编辑本地副本,并根据这些消息测试更改。如果它有效,我会通过ManageSive上传修改后的规则集。

服务器范围规则

有时,您希望对所有用户应用筛选规则。您可能希望将某些邮件发送到垃圾邮件文件夹,或将CEO的邮件路由到垃圾箱。使用 dovecot.conf 插件部分中的 sieve_before 选项设置一个影响所有人的脚本。Dovecot必须有权限将编译后的规则写入筛选器目录。

如果要运行多个筛选器,请在 sieve_before 选项中添加排序。

您还可以将 sieve_before 设置为目录。该目录中以 .sieve 结尾的文件将按名称顺序编译和执行。

Dovecot还支持 sieve_after 选项。 sieve_after 中的过滤器在用户脚本之后运行,并且只影响用户过滤器通过隐式保留发送到收件箱的消息。您可以有多个 sieve_after 过滤器或使用一个目录,就像 sieve_before 一样。

就像Dovecot一样,Pigeonhole的功能比这里讨论的要多得多。系统管理员可以为他们的用户创建一组Sieve脚本,以包含在他们自己的规则中。用户可以设置规则来处理自动回复和假期消息。你可以根据需要添加这些。

让我们继续讨论垃圾邮件检测。