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 编码文本,不负责修复不合规的邮件头语法。
备注:内容仅供参考。
