概述
本文件描述了Postfix对电子邮件地址国际化(EAI)的支持,该支持符合RFC 6531(SMTPUTF8扩展)和RFC 6532(国际化电子邮件头部)和RFC 6533(国际化交付状态通知)。自 Postfix 3.0 版本起引入,完全支持 UTF-8 电子邮件地址和 UTF-8 消息头值。
本文件涵盖的主题:
- 带/不带 SMTPUTF8 支持的构建
- 启用 Postfix SMTPUTF8 支持
- 使用 Postfix SMTPUTF8 支持
- SMTPUTF8 自动检测
- 当前实现的限制
- 与预 SMTPUTF8 环境的兼容性
- 与 IDNA2003 的兼容性
- 贡献者
带/不带 SMTPUTF8 支持构建 Postfix
如果系统上安装了 ICU 版本 ≥ 46 的库和头文件,Postfix 将带 SMTPUTF8 支持进行构建。包名称因操作系统发行版而异。下表列出了本文撰写时部分平台的包名称。
操作系统发行版 包 FreeBSD、NetBSD 等 icu CentOS、Fedora、RHEL libicu-devel Debian、Ubuntu libicu-dev
要强制 Postfix 在不使用 SMTPUTF8 的情况下构建,请指定:
$ make makefiles CCARGS="-DNO_EAI ..."
请参阅 INSTALL 文档以获取更多 "make makefiles" 选项。
启用 Postfix SMTPUTF8 支持
SMTPUTF8 的实现不仅仅涉及 Postfix 本身。您的整个邮件基础设施也需要能够处理 UTF-8 格式的邮件地址和消息头值。这包括 SMTP 基于内容过滤器(如 Amavisd)中的 SMTPUTF8 协议支持、LMTP 服务器(如 Dovecot)以及下游 SMTP 服务器。
Postfix 的 SMTPUTF8 支持默认启用,但可能作为向后兼容性安全措施被禁用(参见 COMPATIBILITY_README 文件)。
SMTPUTF8 支持通过在 main.cf 中设置 smtputf8_enable 参数启用:
# postconf "smtputf8_enable = yes" # postfix reload
(对于 Postfix ≤ 3.1,您可能还需要在 Postfix MySQL 客户端文件中指定 "option_group = client",以启用 MySQL 查询中的 UTF-8 支持。此设置自 Postfix 3.2 起为默认设置。)
启用 SMTPUTF8 支持后,Postfix 的行为将与早期版本有所不同:
- UTF-8 字符集在 myorigin 参数值中被允许。然而,myhostname 和 mydomain 参数目前必须指定仅包含 ASCII 字符的域名。此限制可能在未来被移除。
- UTF-8 是 Postfix 在访问表、地址重写表及其他以电子邮件地址、主机名或域名作为索引的表中支持的唯一非 ASCII 文本格式。
- 类似于 header_checks 和 body_checks 的功能未启用 UTF-8,因此它们不会对输入和输出强制执行 UTF-8 语法规则。原因是,非 ASCII 文本可能以 UTF-8 以外的编码发送,且真实邮件有时包含格式错误的头部。为了避免跳过非 UTF-8 内容,Postfix 应能够过滤这些内容。您可以尝试通过在 PCRE 模式开头添加 (*UTF8) 序列来启用 UTF-8 处理,但这会导致 PCRE 模式匹配器遇到非 UTF-8 输入时出现 "消息未被接受,请稍后重试" 错误。其他未启用 UTF-8 的功能包括 smtpd_command_filter、smtp_reply_filter、*_delivery_status_filter 功能以及 *_dns_reply_filter 功能(后者因为 DNS 本质上是 ASCII 协议)。
Postfix SMTP 服务器在 EHLO 响应中声明支持 SMTPUTF8。
220 server.example.com ESMTP Postfix EHLO client.example.com 250-server.example.com 250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250-STARTTLS 250-AUTH PLAIN LOGIN 250-ENHANCEDSTATUSCODES 250-8BITMIME 250-DSN 250 SMTPUTF8
Postfix SMTP 服务器在 MAIL FROM 和 VRFY 命令中接受 SMTPUTF8 请求。
MAIL FROM:<;地址>; SMTPUTF8 ... VRFY 地址 SMTPUTF8
- Postfix SMTP 客户端可能在 MAIL FROM 命令中发送 SMTPUTF8 请求。
- Postfix SMTP 服务器在电子邮件地址域中接受 UTF-8,但仅在远程 SMTP 客户端在 MAIL FROM 或 VRFY 命令中发送 SMTPUTF8 请求后才接受。
Postfix 已经允许在消息头值和地址本地部分中使用 UTF-8。这一点不会改变。
使用 Postfix SMTPUTF8 支持
启用 Postfix SMTPUTF8 支持后,Postfix 的行为将取决于以下三个条件:1) 远程 SMTP 客户端是否请求 SMTPUTF8 支持,2) 消息信封和头部中是否包含 UTF-8 内容,3) 下游 SMTP(或 LMTP)服务器是否声明支持 SMTPUTF8。
- 当 Postfix SMTP 服务器收到不包含 SMTPUTF8 请求的消息时,Postfix 将按默认方式处理该消息(至少这是默认行为,详见下文的自动检测)。具体来说,Postfix SMTP 服务器不接受信封发件人域名或信封收件人域名中的 UTF-8,且 Postfix SMTP 客户端在将该消息传递给宣布支持 SMTPUTF8 的 SMTP 或 LMTP 服务器时不会发送 SMTPUTF8 请求(同样,这是默认行为)。Postfix 会接受消息头值以及信封发件人和收件人地址的本地部分中的 UTF-8,因为它一直都是这样做的。
- 当 Postfix SMTP 服务器收到包含 SMTPUTF8 请求的消息时,Postfix 会在将该消息传递给声明支持 SMTPUTF8 的 SMTP 或 LMTP 服务器时发出 SMTPUTF8 请求。此行为不可配置。
当收到包含 SMTPUTF8 请求的消息时,Postfix 仅在以下条件同时满足时,将消息传递给不支持 SMTPUTF8 的 SMTP 或 LMTP 服务器:
- 消息头值中不包含 UTF-8。
- 信封发件人地址中不包含 UTF-8,
该特定 SMTP/LMTP 交付事务的信封收件人地址中不包含 UTF-8。
注意:同一消息在其他电子邮件交付事务中的收件人仍可能包含 UTF-8。
否则,Postfix 将返回该电子邮件交付交易的收件人作为无法投递。交付状态通知消息将是一个 SMTPUTF8 消息。因此,它将受到与通过 SMTPUTF8 请求接收的电子邮件相同的限制。
- 当 Postfix SMTP 服务器收到包含 SMTPUTF8 请求的消息时,该请求在消息通过虚拟或本地别名转发,或通过 $HOME/.forward 文件转发后仍适用。
SMTPUTF8 自动检测
本节仅适用于启用了 SMTPUTF8 支持的系统(smtputf8_enable = yes)。
为了与预 SMTPUTF8 环境兼容,Postfix 不会自动在来自非 SMTPUTF8 客户端且包含 UTF-8 标头值或 UTF-8 地址本地部分的消息上设置"SMTPUTF8 请求"标志。这会导致此类消息无法送达非 SMTPUTF8 服务器,并可能成为采用 SMTPUTF8 的障碍。
默认情况下,Postfix 仅在地址验证探测和 Postfix sendmail 提交中设置 "SMTPUTF8 requested" 标志,且这些提交包含发件人地址中的 UTF-8、收件人地址中的 UTF-8 或消息头值中的 UTF-8。
/etc/postfix/main.cf: smtputf8_autodetect_classes = sendmail, verify
然而,如果你有非ASCII myorigin 或 mydomain 设置,或者配置中引入了使用虚拟别名、规范映射或 BCC 映射的 UTF-8 地址,则可能需要对所有电子邮件应用 SMTPUTF8 自动检测:
/etc/postfix/main.cf: smtputf8_autodetect_classes = all
这当然也会标记那些未通过 SMTPUTF8 请求接收的邮件,但其发件人地址本地部分、收件人地址本地部分或消息头值中包含 UTF-8 编码的邮件。此类邮件不符合标准,但如果禁用 SMTPUTF8 支持,Postfix 仍会将其投递。
当前实现的限制
Postfix 的实现仍在进行中;限制正在逐步移除。下文描述了某一时间点的状况。
不支持 ASCII 与 UTF-8 域名之间的自动转换。
背景信息:根据RFC 6530及相关文档,国际化域名可采用两种形式:UTF-8 形式和 ASCII(xn--mumble)形式。国际化地址的本地部分必须编码为 UTF-8;RFC 并未定义 ASCII 替代形式。
Postfix 目前在使用域名进行 SMTP 命令和响应之前,以及在从列表(如 mydestination、relay_domains 或访问控制表等查找表中,在策略守护进程或 Milter 请求中使用域名之前,或在记录事件之前。
Postfix 在将域名或电子邮件地址与 Postfix 配置参数或查找表进行匹配之前,会对它们进行大小写转换。
要使用 Postfix SMTPUTF8 支持:
- Postfix 参数 myhostname 和 mydomain 必须以 ASCII 形式存在。其中一个是另一个的子字符串,而 myhostname 的值用于需要 ASCII 的 SMTP 命令和响应。参数 myorigin(添加到不带域名的本地地址中)支持 UTF-8。
- 您需要在 Postfix 参数(如 mydestination 和 relay_domains,以及查找表搜索键。
- Milters、内容过滤器、策略服务器和日志文件分析工具需要能够处理国际化域名(IDN)的 ASCII 和 UTF-8 形式。
与预 SMTPUTF8 环境的兼容性
包含 UTF-8 和非 UTF-8 订阅者的邮件列表
使用 Postfix 时,无需将邮件列表拆分为 UTF-8 和非 UTF-8 成员。Postfix 会尝试通过"传统"非 SMTPUTF8 会话向非 UTF-8 订阅者发送邮件,只要邮件具有 ASCII 信封发件人地址且所有标头值均为 ASCII。邮件列表管理员可能需要应用RFC 2047编码以满足最后一个条件。
现有非ASCII邮件流
当 "smtputf8_enable = no" 时,Postfix 处理地址本地部分(以及头部)包含非 ASCII 字符的邮件与之前相同。绝大多数邮件软件均能完美处理此类邮件,即使预 SMTPUTF8 标准不支持此类做法。
拒绝非 UTF-8 地址
当 "smtputf8_enable = yes" 时,Postfix 要求非 ASCII 地址信息必须以 UTF-8 编码,并将拒绝其他编码(如 ISO-8859)。Postfix 无法同时支持多种编码。使用RFC 2047编码(如 "=?ISO-8859-1?Q?text?=")没有问题,因为这些编码仅使用ASCII字符集中的字符。
在非 SMTPUTF8 交易中拒绝非 ASCII 地址
除了设置 "strict_smtputf8 = yes" 之外, org/postconf.5.html#smtputf8_enable">smtputf8_enable = yes" 将启用对 SMTPUTF8 协议的更严格执行。具体来说,Postfix SMTP 服务器不仅会拒绝非 UTF-8 格式的发件人或收件人地址,而且仅在客户端请求 SMTPUTF8 邮件交易时才接受 UTF-8 格式的发件人或收件人地址。
与 IDNA2003 的兼容性
Postfix 3.2 及更高版本默认禁用 IDNA2003 与 IDNA2008 之间的"过渡"兼容性,在将 UTF-8 域名转换为 DNS 查询中使用的 ASCII 形式时。这使 Postfix 的行为与当前版本的 Firefox 和 Chrome 网页浏览器保持一致。若要恢复历史行为,请设置 "enable_idna2003_compatibility = yes"。
这会影响包含例如德语中的 sz(ß)和希腊语中的 zeta(ς)等字符的域名转换。更多示例请参阅 http://unicode.org/cldr/utility/idna.jsp。
致谢
- 2014年5月15日:Arnt Gulbrandsen发布了其Unicode电子邮件支持补丁。此工作由CNNIC赞助。
- 2014年7月15日:Wietse 整合了 Arnt Gulbrandsen 的代码并发布了支持 SMTPUTF8 的 Postfix。
- 2015年1月:Wietse 为 Postfix 查找表中的大小写转换添加了 UTF-8 支持,并在 Postfix 基于列表的功能中实现了无大小写字符串比较。