Mime 7bit编码和UnsupportedEncodingException

时间:2012-10-01 13:49:56

标签: java mime mime-message

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

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是正确的。但这似乎太容易解决了......未来我可以遇到哪些问题?有没有更好的方法来跳过异常并获取电子邮件内容而不强制使用caret和编码?

1 个答案:

答案 0 :(得分: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是在20世纪90年代初开发的。问题的核心是两个MIME标头Content-Type:Content-Transfer-Encoding:。这些都用于标识MIME部分的类型,但它们是不同的概念。 Content-Type描述了数据的内容(text/htmlaudio/midiapplication/octet-stream,用于非类型化二进制数据等)。 Content-Transfer-Encoding:表示如何通过电子邮件(或其他MIME管道)进行传输编码。

Content-Transfer-Encoding:基本上定义了两种编码和三种未编码类型。 CTE:7bit表示数据本身适合在7比特信道上传输(也有线路长度限制); 8bit不是,如果通道无法容纳8位数据,则​​需要重新编码。类似地,binary也是8位,但另外不保证行长度(即它可能包含长度大于约1,000个字符的行)。因此,要在7位通道上传输binary8-bit数据,您需要将内容重新编码为base64quoted-printable。这两种编码都用7位序列代替8位字符;期望接收者执行反向替换以解码和提取数据。

一旦提取完成,数据基本上就可以在接收端使用了。但是,对于文本类型,还存在字符集编码问题。许多字符集只是7位或8位,因此流中的一个字节对应一个字符。但是多字节字符集的行为并不像这样,因此它们也需要以某种方式进行编码。但这与上面描述的MIME 7bit / 8bit不同。字符编码告诉您字节流如何编码多字节字符。

UTF-8将多字节字符编码为8位字符序列(而方便的7位字符与US-ASCII 7位编码相同)。编码有一些很好的属性,您可以在维基百科中阅读。

UTF-7从未被正式接受为官方Unicode编码,并未得到广泛使用。它与US-ASCII不完全兼容,因为+-字符用于编码多字节字符序列。

如果您希望解码UTF-7并且您的语言不支持编码,则必须编写自己的解码器。另一种方法是不解码编码,并将其留给下游消费者进行解码。在这种情况下,请注意以某种方式将字符编码中继到下游。但是,由于UTF-7没有得到广泛支持,我建议重新编码为UTF-8,这是广泛支持和理解的(如上所述,如果没有多字节字符,也会与US-ASCII透明兼容)。

所以,总结一下;如果更改标题,则还必须更改编码。如果您幸运(并且您的示例具有代表性),则文本不包含任何实际编码的UTF-7多字节字符,在这种情况下,您可以安全地将其重新标记为US-ASCII。如果它包含+-个字符,它们是需要解码的UTF-7序列的一部分(尽管如此,你可能很幸运,序列只是UTF-7的转义,编码文字加号或减号。)