如果有人真的发送 UTF-7,你会导致客户端解码不正确。但这非常罕见;大多数网站都使用 Unicode 发送 UTF-8。对于您发布的示例内容,它是纯 ASCII,因此它对 UTF-7 和 UTF-8 都有效。(UTF-7 为 + 和 - 分配了特殊的语义,因此对于包含这些字符序列的消息,即使 ASCII 也不安全。也就是说,UTF-7 错误地标记为 US-ASCII 或反之亦然会错误地解码。)
将 Quoted-Printable 分配给真正不是的东西同样是随意的;消息中的任何等号在 QP 中都有特殊含义。我认为你应该离开它。
正确的解决方案是真正重新编码消息正文,即从 UTF-7 转换为 UTF-8(并可能将其包装在quoted-printable 中),然后分配正确的内容类型标头;或者,说服发送这些消息的任何人坚持使用普通的旧 US-ASCII 或切换到 UTF-8。(或者,了解如何教 Java 处理 UTF-7 编码;但这超出了我的能力范围。)
另见http://en.wikipedia.org/wiki/UTF-7
基本的 RFC822 电子邮件是纯 7 位的。为了实现丰富的内容和不同的字符集,MIME是在 1990 年代初期开发的。您问题的核心是两个 MIME 标头Content-Type:
和Content-Transfer-Encoding:
. 它们都用于标识 MIME 部分的类型,但它们是不同的概念。描述Content-Type
了数据是什么(text/html
, audio/midi
,application/octet-stream
用于无类型二进制数据等)。指示它是Content-Transfer-Encoding:
如何被编码以通过电子邮件(或另一个 MIME 管道)传输的。
Content-Transfer-Encoding:
基本上定义了两种编码和三种未编码类型。CTE:7bit
表示数据本身适合通过7位通道传输(也有行长限制);8bit
不是,如果通道不能容纳 8 位数据,则需要重新编码。同样,binary
它也是 8 位的,但另外不能保证行长(即它可能包含超过大约 1,000 个字符的行)。因此,要通过7 位通道传输binary
或数据,您需要将内容重新编码为或。这两种编码都将 8 位字符替换为 7 位序列;接收者应执行反向替换以解码和提取数据。8-bit
base64
quoted-printable
一旦提取发生,数据基本上就可以在接收端使用了。但是,对于文本类型,还有字符集编码的问题。许多字符集只是 7 位或 8 位,因此流中的一个字节对应一个字符。但多字节字符集的行为并非如此,因此它们也需要以某种方式进行编码。但这与上面描述的 MIME 7bit/8bit 不同。字符编码告诉您字节流如何编码多字节字符。
UTF-8将多字节字符编码为 8 位字符序列(虽然方便地 7 位字符与 US-ASCII 7 位编码相同)。编码具有一些不错的属性,您可以在 Wikipedia 中了解这些属性。
UTF-7 从未被正式接受为官方的 Unicode 编码,也没有被广泛使用。它与 US-ASCII 不完全兼容,因为+
和-
字符用于编码多字节字符序列。
如果您希望解码 UTF-7 并且您的语言不支持该编码,则必须编写自己的解码器。另一种方法是不对编码进行解码,而是将其留给下游消费者进行解码。在这种情况下,请注意以某种方式将字符编码中继到下游。但是,由于 UTF-7 未得到广泛支持,我建议将其重新编码为广泛支持和理解的 UTF-8(而且,如前所述,如果不存在多字节字符,则与 US-ASCII 透明兼容)。
所以,总结一下;如果更改标头,则还必须更改编码。如果幸运(并且您的示例具有代表性),文本不包含任何实际编码的 UTF-7 多字节字符,在这种情况下,您可以安全地将其重新标记为 US-ASCII。如果它确实包含+
or-
字符,它们是需要解码的 UTF-7 序列的一部分(尽管同样,您可能很幸运,并且这些序列只是编码文字加号或减号的 UTF-7 转义)。