JavaMail 之 杜绝邮件乱码

王朝java/jsp·作者佚名  2008-05-30
窄屏简体版  字體: |||超大  

我一直想不通,RFC822 标准都发布多少年了,为什么还有那么多不符合规范的email 出现呢?一来也许是服务器的问题,二来就是不负责任的程序员的错了。所以我突然意识到,不是只有冷血无情的老板和咄咄逼人的客户让程序员的身心饱受摧残,同行的不经意或经意也在加剧着伤害。

我面对着一份邮件原文发出以上的感慨,客户抱怨该邮件收到的时候在系统中正文显示是乱码而标题正常。这是一份典型的不合规范的邮件: Content-Type : text/plain ,没有说明 charset,而接下来的正文直接就是未进行任何编码的中文文字。不过 Subject 却是符合规范的(=?gb2312?B?xxxxxxx?=)。

行行色色的不合规范的邮件见过不少,最常见的就是某些header未编码,还有的可能就是,Body编码了而Subject 未编码,最讨厌的就是整份Email都没有编码信息。

恨归恨,问题还是得解决,我修改了代码,处理逻辑如下:

1. 在最开始解析邮件的时候,先解析某些可能带有编码信息的header,并记录为 headerCharset;部分代码如下:

private static Pattern encodeStringPattern = Pattern.compile("=\\?(.+)\\?(B|Q)\\?(.+)\\?=", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);

private final String[] CHARTSET_HEADER = new String[] { "Subject", "From", "To", "Cc", "Delivered-To" };

..........

Enumeration enum = message.getMatchingHeaderLines(CHARTSET_HEADER);

while (enum.hasMoreElements()) {

String header = (String) enum.nextElement();

Matcher m = encodeStringPattern.matcher(header);

if (m.find()) {

this.headCharset = m.group(1);

log.debug("guess mail charset is " + this.headCharset);

break;

}

}

..........

2. 接着解析邮件体,找到 Body 的时候,看看是否指明 charset 信息;如果指定了,记录为 bodyCharset;如果没有,使用 headerCharset,如果 headerCharset 也是 null,使用默认charset。通常是 ISO-8859-1,但通常我们收到的很多不符合规范的邮件都是简体或者繁体中文的,所以设置默认charset 为 GBK比较保险。

3. 最后再处理邮件 header,如果没有charset 信息,使用 bodyCharset,否则使用默认charset。

以上的解决方案,只要邮件的Body或者Header中的一个提供了编码信息,那么都可能可以避免乱码的产生,如果哪份遭千杀的邮件,Body 用 gb2312 编码,Subject 却是未编码的日文,那我只能长叹被击败了。如果整份邮件都没有编码信息的话,除非你确定邮件都是指定的编码并进行转码,否则只有听天由命。

在寻求解决方案的过程中,参考了JCharDet 项目,一个猜测字符串编码集的程序包,具体参见竹笋炒肉的blog。不过在实际操作中,猜测结果并不准确,繁体字总被猜作UTF-16。

最后呼吁一声,请遵循规范!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
© 2005- 王朝網路 版權所有 導航