摘要

  • RFC 5231 为 Sieve 原有的地址、信封与头字段测试加入有序 :value 比较和 :count 计数。选用不同测试,计数的单位也不同。
  • 地址测试数的是 mailbox 元素,信封测试数的是传输地址,头字段测试数的是字段实例,而非字段里列出的地址。信封 to 则按设计只向当前脚本用户呈现一个地址。

“有多少收件人”并不是一个问题

看见邮件里的 To: 行,计数似乎不难:列出两个邮箱,就是两个收件人。但邮件过滤器不是按人读这行文字的直觉工作。它面对的是头字段、SMTP 信封以及解析后的地址结构;这些表面代表不同的信息,也由不同环节掌握。

2008 年 1 月发布的 RFC 5231,为 Sieve 已有的 address、envelope 与 header 测试补上关系比较能力。脚本不再只能问某个值是否匹配,还可以判断它大于、小于、等于或不等于给定值。扩展定义了两种匹配类型::value 使用能提供排序信息的比较器比较字符串;:count 则先数出选定实体,再比较所得数量。

运算符包括 gt、ge、lt、le、eq 和 ne。在 :value 中,来自邮件的值是关系式左侧,脚本键列表中的值在右侧。任一侧存在多个值时,只要有一对满足关系,测试结果就为真。文本排序并非天然一致,所选比较器会影响含义。RFC 5231 要求支持 i;ascii-numeric,至少处理 32 位无符号整数;该比较器不表示负数。

更能说明问题的是 :count。假设 To: 有两个邮箱地址项,Cc: 有一个。对 to 与 cc 做 address :count,会数到三个 mailbox 元素。群组名称本身不计数,群组里的邮箱成员会计入。改用 header :count 检查同样两个字段,数的则是头字段实例。符合 RFC 2822 的邮件最多有一个 To: 字段和一个 Cc: 字段,因此结果是二,不是三个人。

envelope :count 量的是另一种东西:所选传输信封部分里的地址。信封的 to 永远只有一个条目,即运行该 Sieve 脚本的用户地址。规范要求这个测试不能让用户推断邮件是否也投递给了别人。信封 from 若对应空的 SMTP MAIL FROM,计数为零;否则为一。因此,“统计收件人”可能指头字段可见的邮箱、脚本能够读取的某个信封地址,或者头字段行数。仅凭测试名称无法确定。

这一差别也会改变条件组合的效果。对 to 与 cc 做一次地址计数,会把两边相加。如果规则想表达“To 至少有三个地址,或者 Cc 至少有三个”,必须分别比较,再放入 anyof;合并后的总数回答的是另一个问题:“两个字段加起来至少三个”。RFC 的例子中,两个 To 地址加一个 Cc 地址让合并测试为真,但两个独立的阈值判断都为假。

RFC 5231 并不是从零创造关系测试。它取代了 RFC 3431;后者在 2002 年已经引入这一扩展及两种匹配类型。新版本把比较器引用从 ACAP 更新为 RFC 4790 的应用协议整理规则注册表,修正示例,澄清 COUNT 所数的 RFC 2822 元素,并删除了空白修剪要求,因为 Sieve 基础规范后来已加入更一般的要求。IANA 的 Sieve 扩展注册表将 relational 记录为一项能力。

扩展到此为止:它不改变隐式 KEEP,也不改变 fileinto、redirect 或 reject 等显式动作。谓词可以决定走哪条脚本分支,却不能单独证明服务器究竟解析了什么、是否正确执行了分支,或者邮件最终投递到哪里。比较规则只有在单位、比较器和实现边界都清楚时才有意义。

来源