RFC 5228《Sieve 邮件过滤语言》中文导读
非官方中文导读声明:本页为 IETF RFC 5228《Sieve: An Email Filtering Language》 的非官方中文技术导读,按原文章节顺序梳理规范要点,并非逐字全文翻译;任何规范性判断均以英文原文为准。英文原文见 rfc-editor.org/rfc/rfc5228.txt。
1. Sieve 的定位
Sieve 是一种在邮件服务器端运行、用于在邮件进入用户信箱前/后自动处理的过滤语言。典型用途是按规则分拣到文件夹、自动转发、丢弃垃圾、自动回复等。
它废止了 RFC 3028,其最大特征是非图灵完备:没有循环、没有用户变量、没有自定义函数。这一限制是刻意为之——过滤脚本应能静态分析、可安全在网络上传送、且不会因脚本陷入死循环而拖垮服务器。
2. 结构:require / 控制 / 测试 / 动作
一个 Sieve 脚本由若干命令组成,命令分三类:
- require:声明本脚本需要哪些扩展能力(如 fileinto、vacation),必须出现在使用前;
- 控制结构:
if/elsif/else构成条件分支;stop用于提前结束脚本(阻止隐式 keep 之外的后续默认动作); - 测试(test)与动作(action):测试判断条件,动作用于实际处置。
require ["fileinto"];
if header :contains "Subject" "紧急" {
fileinto "Urgent";
} else {
keep;
}
3. 内置测试
规范定义了一组基础测试(无需扩展即可用):
| 测试 | 用途 |
|---|---|
| address | 检查邮件地址类头字段(From/To/Cc 等)中的地址部分。 |
| allof | 逻辑与:所有子测试为真才为真。 |
| anyof | 逻辑或:任一子测试为真即为真。 |
| exists | 检查指定头字段是否存在。 |
| false / true | 恒为假 / 恒为真,常用于占位或调试。 |
| header | 检查任意头字段的值。 |
| not | 逻辑非,取反一个测试。 |
| size | 按邮件大小(:over / :under)判断。 |
| envelope | 检查 SMTP 信封(需实现支持,常来自 RFC 3028 后的扩展)。 |
4. 匹配关键字与比较器
大多数测试可带匹配关键字(match type),决定“如何比较”:
:is:要求完全相等;:contains:要求包含子串;:matches:支持通配符*(匹配零个或多个字符)与?(匹配单个字符)的全局匹配。
比较器(comparator)决定“按什么规则比”,默认有两个:
i;octet:按原始字节逐字节比较,区分大小写且对本地化不友好;i;ascii-casemap:ASCII 大小写不敏感比较(默认值,适合英文)。
例如 header :contains :comparator "i;ascii-casemap" "Subject" "news" 会忽略主题里的大小写去匹配 news/News/NEWS。
5. 动作与隐式 keep
规范定义的基础动作包括:
keep:把邮件存入用户主信箱;fileinto:存入指定文件夹(属于扩展,需 require);redirect:转发到另一地址;discard:静默丢弃(注意:规范要求 discard 在语义上等价于“丢弃”,某些实现会记为已处理而不再隐式 keep)。
最关键的默认行为是隐式 keep:如果脚本跑完没有任何动作命中(也没有 discard),则邮件按 keep 处理——这保证了“写错脚本不会丢邮件”。实现方可以定义额外动作(如 reject、vacation),但都通过 require 引入。
6. 安全性与可分析性
由于非图灵完备,Sieve 脚本可以被实现静态检查:循环依赖、未声明扩展、语法错误都能在上传时拒绝,而不必等到运行时。文档还规定脚本中的字符串常量、命令顺序都有明确约束,便于服务器沙箱执行。
对运维而言,Sieve 的价值在于把过滤逻辑放在服务端:用户无论用哪个设备收发,规则都一致生效;且脚本文件通常可跨不同邮件服务器(只要它们都支持 Sieve 扩展集)移植。
参考:https://www.rfc-editor.org/rfc/rfc5228.txt
