PAYATHON 2026

PHP IMAP 中 imap_utf8 为何未解码带引号的编码词?

数据小许

结论

示例中的 MIME 编码词被双引号包住了。根据 RFC 2047,encoded-word 不应位于 quoted-string 内,因此这不是合规的编码邮件头。imap_utf8() 对这种输入原样返回,不一定意味着 UTF-8 转换失败。RFC 2047;PHP imap_utf8() 手册

合规写法应去掉编码词外侧的双引号:

=?utf-8?Q?part1=40part2.com?= <part1@part2.com>

其中,=40 是 quoted-printable 编码的 @。解码显示名后,整体值应类似 part1@part2.com <part1@part2.com>。

处理现有值

如果输入符合示例中的固定形式,可以先移除包住完整编码词的双引号,再调用 imap_utf8():

$raw = '"=?utf-8?Q?part1=40part2.com?=" <part1@part2.com>';

$normalized = preg_replace(
    '/"((?:=\?[^?]+\?[bq]\?[^?]*\?=))"/i',
    '$1',
    $raw
);

$converted = imap_utf8($normalized);

这个替换只处理双引号恰好包住一个完整 B 或 Q 编码词的情况。邮件头格式可能不同;遇到其他形式时,应按地址字段结构解析,并单独处理显示名。不要对整个字段做宽泛的引号替换。PHP 的 imap_mime_header_decode() 也可用于解码 MIME 邮件头片段,但输入仍需符合邮件头编码格式。PHP imap_mime_header_decode() 手册

注意事项

如果可以控制邮件发送端,应修正邮件头的生成方式,避免 encoded-word 出现在双引号内。若只能读取已有数据,可先根据实际字段结构检查输入,再针对该格式进行兼容处理。imap_utf8() 负责转换 MIME 编码文本,不负责修复不合规的邮件头语法。

备注:内容仅供参考。