SMTP发送MIME邮件:Gmail与Outlook兼容性问题排查
你遇到的问题核心是不同邮件服务的MIME解析器对非标准格式的容错逻辑完全相反,哪怕你以为自己贴近标准,两家的处理方式也天差地别。
1. 去掉换行符时:Gmail能收,Outlook炸了
当附件的MIME头部和Base64编码的内容之间没有空行时,Outlook的解析器会犯一个致命错误:它把Base64内容的每一行都当成了新的邮件头部字段。比如PDF的Base64开头是JVBERi0xLjMK,Outlook会把这行当作一个无效的头部键值对,一直数到第100001个“头部”时触发了服务器的上限,直接返回554 5.6.211错误。
而Gmail的解析器容错性强得多,它能自动识别出“这明显是头部直接接了内容”,会悄悄修复格式,所以能正常解析附件。
2. 保留换行符时:Outlook能收,Gmail拒收
这里大概率你保留的是单个换行符(\r\n),而不是MIME标准要求的空行(两个连续的\r\n,也就是\r\n\r\n)。Gmail的解析器对格式要求更严,只要检测到头部和内容之间的分隔不是标准空行,就判定整个MIME结构无效,直接拒收。但Outlook的解析器对这种“差一点就标准”的格式宽容度高,能正确识别头部和内容的边界,所以正常接收。
为啥会有这种差异?
MIME标准(RFC 2045/2046)明确规定,每个MIME部分的头部结束后必须用**空行(\r\n\r\n)**分隔头部和内容,但不同厂商的解析器在处理非标准格式时的逻辑不一样:
- Outlook的解析器对“头部无空行直接接内容”的情况零容错,但对“单个换行分隔”的情况能容忍;
- Gmail的解析器则刚好相反,对“无空行接内容”能修复,但对“单个换行”严格卡标准。
怎么解决?
严格按标准来:每个MIME部分的头部最后一行之后,必须加两个连续的\r\n,再放Base64编码的附件内容。比如正确的结构是这样的:
Content-Type: application/pdf; name="document.pdf" Content-Disposition: attachment; filename="document.pdf" Content-Transfer-Encoding: base64 JVBERi0xLjMKJcfsj6IKNSAwIG9iago8PC9MZW5ndGggNiAwIFIvRmlsdGVyIC9GbGF0ZURlY29kZT4+CnN0cmVhbQp4nE2NuwoCQQxF+/mKx8tNcEUSMhBQnG7sRDCQEHLgU3L4U1Q6fKtY2FhYGBkYGBkbJijoJ5+QUBmIAQ4nCgoyMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAxMjAgMDAwMDAgbiAKMDAwMDAwMDI1MiAwMDAwMCBuIAowMDAwMDAwMDE1IDAwMDAwIG4gCjAwMDAwMDAzNzMgMDAwMDAgbiAKMDAwMDAwMDQ2NiAwMDAwMCBuIAp0cmFpbGVyCjw8L1NpemUgNi9Sb290IDEgMCBSL0luZm8gNSAwIFIvSUQgWzwzN0Y0RjE4RjE0QjRCNDg4Q0U4RjE4RjE0QjRCNDg4Pgo8MzdGNEYxOEYxNEI0QjQ4OENFOEYxOEYxNEI0QjQ4OD4gXS9Sb290U3VidHlwZSAvTWV0YWRhdGEvVmlld2VyU3VidHlwZSAvVHJ1ZVR5cGU+PgpzdGFydHhyZWYKMTM5MgolJUVPRgo=
看,头部最后一行和Base64内容之间有一个空行,这才是标准要求的。这样不管是Outlook还是Gmail,都能正确解析。
内容的提问来源于stack exchange,提问作者David B

