0

我已经实施了一种方法,但我不确定它是否正确,或者将来会给我带来问题。
给这封电子邮件:

Date: Mon, 17 Sep 2012 04:14:36 +0200   
Content-Type: text/plain;
    charset="utf-7"   
Content-Transfer-Encoding: 7bit
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 6.00.2600.0000
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000
To: user@address.com

Dear Sir/madam, ... etc

而这段代码:

MimePart part; //The email 
if (part.isMimeType("text/plain")) {
   String plainContent = part.getContent().toString();

例外是:

java.io.UnsupportedEncodingException: utf-7

我做了这个修改,所以字符集总是utf-8和编码quoted-printable

part.setHeader("Content-Transfer-Encoding", "quoted-printable");
part.setHeader("Content-Type", "text/plain; charset=utf-8");

例外不再存在并且plainContent是正确的。但这似乎太容易解决了……我将来会遇到哪些问题?有没有更好的方法来跳过异常并在不强制 carset 和编码的情况下获取电子邮件内容?

4

1 回答 1

1

如果有人真的发送 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-bitbase64quoted-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 转义)。

于 2012-10-02T08:40:55.587 回答