跳转到主要内容

于 2025年04月22日 摘录自 Postfix SMTPUTF8 support

概述

本文件描述了Postfix对电子邮件地址国际化(EAI)的支持,该支持符合RFC 6531(SMTPUTF8扩展)和RFC 6532(国际化电子邮件头部)和RFC 6533(国际化交付状态通知)。自 Postfix 3.0 版本起引入,完全支持 UTF-8 电子邮件地址和 UTF-8 消息头值。

本文件涵盖的主题:

带/不带 SMTPUTF8 支持构建 Postfix

如果系统上安装了 ICU 版本 ≥ 46 的库和头文件,Postfix 将带 SMTPUTF8 支持进行构建。包名称因操作系统发行版而异。下表列出了本文撰写时部分平台的包名称。

操作系统发行版
FreeBSD、NetBSD 等icu
CentOS、Fedora、RHELlibicu-devel
Debian、Ubuntulibicu-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 参数值中被允许。然而,myhostnamemydomain 参数目前必须指定仅包含 ASCII 字符的域名。此限制可能在未来被移除。
  • UTF-8 是 Postfix 在访问表、地址重写表及其他以电子邮件地址、主机名或域名作为索引的表中支持的唯一非 ASCII 文本格式。
  • 类似于 header_checksbody_checks 的功能未启用 UTF-8,因此它们不会对输入和输出强制执行 UTF-8 语法规则。原因是,非 ASCII 文本可能以 UTF-8 以外的编码发送,且真实邮件有时包含格式错误的头部。为了避免跳过非 UTF-8 内容,Postfix 应能够过滤这些内容。您可以尝试通过在 PCRE 模式开头添加 (*UTF8) 序列来启用 UTF-8 处理,但这会导致 PCRE 模式匹配器遇到非 UTF-8 输入时出现 "消息未被接受,请稍后重试" 错误。其他未启用 UTF-8 的功能包括 smtpd_command_filtersmtp_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.cfsmtputf8_autodetect_classes = sendmail, verify

然而,如果你有非ASCII myoriginmydomain 设置,或者配置中引入了使用虚拟别名、规范映射或 BCC 映射的 UTF-8 地址,则可能需要对所有电子邮件应用 SMTPUTF8 自动检测:

/etc/postfix/main.cfsmtputf8_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 命令和响应之前,以及在从列表(如 mydestinationrelay_domains 或访问控制表等查找表中,在策略守护进程或 Milter 请求中使用域名之前,或在记录事件之前。

Postfix 在将域名或电子邮件地址与 Postfix 配置参数或查找表进行匹配之前,会对它们进行大小写转换。

要使用 Postfix SMTPUTF8 支持:

  • Postfix 参数 myhostnamemydomain 必须以 ASCII 形式存在。其中一个是另一个的子字符串,而 myhostname 的值用于需要 ASCII 的 SMTP 命令和响应。参数 myorigin(添加到不带域名的本地地址中)支持 UTF-8。
  • 您需要在 Postfix 参数(如 mydestinationrelay_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 基于列表的功能中实现了无大小写字符串比较。