如何转义SMTP头中包含非ASCII字符的完整邮箱地址?
这问题我太有共鸣了!当初第一次处理带非ASCII字符的邮箱地址时,也在SMTP命令和邮件头的区别上卡了好久,尤其是分不清哪些地方该用punycode,哪些地方可以直接写原始字符。咱们一步步理清楚:
核心原则:分清楚两个独立环节
首先要明确,SMTP传输层的命令(比如RCPT TO)和邮件内容里的To:/From:头字段是完全分开的,处理规则不一样:
1. SMTP传输层:必须用Punycode
你已经知道这一点了,但再强调下:所有SMTP命令里的邮箱地址(不管是MAIL FROM还是RCPT TO),只要包含非ASCII字符,就必须转换成Punycode格式。比如你提到的tüst@domain.de,在SMTP命令里要写成:
RCPT TO:<xn--tst-0qa@domain.de>
这是RFC 6531强制要求的,因为传统SMTP只支持ASCII字符。
2. 邮件头的To:/From:字段:两种合法写法
这里是你困惑的核心,其实取决于收件方的邮件系统是否支持**国际化邮箱(EAI,Email Address Internationalization)**标准:
写法一:现代系统友好(推荐)
如果收件方用的是主流现代邮件系统(比如Gmail、Outlook、苹果邮件等),它们都支持UTF-8编码的邮件头。这时候:
- 用户友好名称可以直接写UTF-8字符(比如
Tüst),也可以继续用RFC 2047编码(比如=?UTF-8?Q?T=c3=bcst?=),两种都合法; - 尖括号里的邮箱地址可以直接写原始的非ASCII格式(
<tüst@domain.de>),不需要转Punycode。
完整的邮件头示例:
MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To: Tüst <tüst@domain.de> From: Your Name <your@example.com>
这种写法用户体验最好,收件人看到的就是原始的邮箱地址,不会出现难懂的Punycode字符串。
写法二:兼容老旧系统
如果需要兼容那些不支持国际化邮箱的老旧邮件系统,就得做妥协:
- 用户友好名称依然用RFC 2047编码(比如
=?ISO-8859-1?Q?T=FCst?=); - 尖括号里的邮箱地址必须转换成Punycode格式(
<xn--tst-0qa@domain.de>)。
示例:
MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable To: =?ISO-8859-1?Q?T=FCst?= <xn--tst-0qa@domain.de> From: Your Name <your@example.com>
老旧系统能正确解析Punycode地址完成投递,而现代系统会自动把Punycode转成原始的非ASCII地址显示给用户,不会影响体验。
重要避坑提醒
绝对不要尝试用RFC 2047的编码格式(=?...?=)去包裹尖括号里的邮箱地址,这是不符合标准的!RFC 2047只能用来编码用户友好名称部分,不能处理邮箱地址本身。
内容的提问来源于stack exchange,提问作者xMRi




