MIME 电子邮件主题等标题与 utf8:首先拆分,然后编码?

问题描述

让我们以这个主题行,

$ echo -n 台電用戶意見電子信箱-信件受 | base64
5Y+w6Zu755So5oi25oSP6KaL6Zu75a2Q5L+h566xLeS/oeS7tuWPlw==

它(连同“主题:”等)在编码时超过了 limits。所以, 一些邮件程序(某个电力公司的)首先对其进行编码,然后将其拆分:

Subject: =?utf-8?B?5Y+w6Zu755So5oi25oSP6KaL6Zu75a2Q5L+h566xLeS/oeS7?=
 =?utf-8?B?tuWPl+eQhumAmuefpQ==?=

(但这可能很容易“破坏”一个 UTF-8 多字节字符。)

其他邮件程序(例如 Gnus)首先将其拆分,然后对其进行编码:

Subject: =?utf-8?B?5Y+w6Zu755So5oi25oSP6KaL6Zu75a2Q5L+h566xLeS/oeS7tg==?=
 =?utf-8?B?5Y+X55CG6YCa55+l?=

后者保证在所有邮件阅读器中正确呈现 今天。

我的问题是,某些邮件阅读器(例如 Gmail android 应用程序)对前者感到窒息?

邮件读者是否应该始终先将两个字符串粘贴在一起,然后 解码? (所以 Gmail 应用是错误的。)

或者也可以先解码,然后将两个解码后的字符串粘贴在一起。 (所以邮件软件有问题?)

(我认为 Quoted Printable 也会出现同样的问题,不仅仅是 Base64。)

Broken UTF-8

确实,如果你仔细想想,说 =?utf-8?B?...?= 意味着 ... 的东西应该是一个有效的 UTF-8 字符串,(就其本身而言)对吗?所以邮件软件是错误的!

同样,可能从来没有定义过如何将 =?utf-8?B?...?= 拆分为两个短语的语法,因为应该事先注意,因为创建 =?utf-8?B?...?= 字符串应该始终是最后的步骤。

所以:邮件软件:有罪。 Gmail:无罪。

解决方法

根据 RFC 2047 § 8 的示例(以及整体解释),编码词不会神奇地跨越多个实例:

  • =?UTF-8?Q?a?= 既不能延续之前的编码词,也不能延续后面的编码词——它是什么:a
  • 当我们混合文本编码时更明显:=?UTF-8?Q?a?= =?ISO-8859-1?Q?b?= 应该呈现为 ab,并且很明显,当下一个编码字是 UTF- 8(虽然不同的文本编码肯定使用不同的字节)。

作为一个逻辑结果,UTF-8 应该被字符分割,而不是字节。这意味着:编码 B (Base64) 和 Q (Quoted) 都不应该被剪切(除非剪切也是在编码文本的字符之间巧合) - 剪切必须发生在之前。

我只能猜测这对一些程序员来说“太复杂了”,他们只是认为“无论如何它不会破坏任何东西 - 到目前为止没有人抱怨”。但是,如果必须切割编码字,正确的方法是首先对其进行解码,以便可以按字符(而不是按字节)切割文本,然后再次对这两个部分进行编码。一个警告是:谁这样做也必须支持所述文本编码 - 虽然今天 UTF-8 很普遍,但软件是否也知道在哪里剪切 Shift-JISBig5UTF-16BE?>

,

您拥有的是 RFC 2047 中定义的 encoded word 语法。您可以混合未编码的标记和各种编码,因此每个编码的单词本身都应该是有效的。首先解码,然后组合看起来是正确的方法。

阅读 RFC,其中一些注释和示例与您的案例相关。

当然,RFC 介绍中的注释“虽然很不幸……”告诉您整个区域总是一团糟。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...