JavaMail的编码问题

在使用javamail api开发邮件服务系统时,我们常常会碰到很多中文乱码问题,下面就分别介绍如何解决这些问题。
[b]先介绍一下javamail的编码:[/b]
1、内容编码:
当一段 Text 或者 HTML 通过电子邮件传送时,发送的内容首先通过一种指定的字符编码转化成“字节串”,然后再把“字节串”通过一种指定的传输编码(Content-Transfer-Encoding)进行转化得到另一串“字节串”。比如,打开一封电子邮件源代码,可以看到类似的内容:
[color=blue]Content-Type: text/plain;charset="gb2312"
Content-Transfer-Encoding: base64
sbG+qcrQuqO17cf4yee74bGjz9W7+b3wudzA7dbQ0MQNCg0KvPKzxqO6uqO17cnnsaPW0NDEDQoNCg==[/color]
最常用的 Content-Transfer-Encoding 有 Base64 和 Quoted-Printable 两种。在对二进制文件或者中文文本进行转化时,Base64 得到的“字节串”比 Quoted-Printable 更短。在对英文文本进行转化时,Quoted- Printable 得到的“字节串”比 Base64 更短。
2、标题编码:
邮件的标题,用了一种更简短的格式来标注“字符编码”和“传输编码”。比如,标题内容为 "中",则在邮件源代码中表示为:
// 正确的标题格式
[color=blue]Subject: =?GB2312?B?1tA=?=[/color] //subject是指标题内容
其中,
第一个“=?”与“?”中间的部分指定了字符编码,在这个例子中指定的是 GB2312。
“?”与“?”中间的“B”代表 Base64。如果是“Q”则代表 Quoted-Printable。
最后“?”与“?=”之间的部分,就是经过 GB2312 转化成字节串,再经过Base64 转化后的标题内容。
如果“传输编码”改为 Quoted-Printable,同样,如果标题内容为 "中":
// 正确的标题格式
[color=blue]Subject: =?GB2312?Q?=D6=D0?=[/color]
如果阅读邮件时出现乱码,一般是因为“字符编码”或“传输编码”指定有误,或者是没有指定。比如,有的发邮件组件在发送邮件时,标题 "中":
// 错误的标题格式
[color=blue]Subject: =?ISO-8859-1?Q?=D6=D0?=[/color]
这样的表示,实际上是明确指明了标题为 [0x00D6, 0x00D0],即 "ÖÐ",而不是 "中"。
[b]解决乱码方法[/b]:
1.邮件主题乱码或附件名乱码
解决办法:
在调用setSubject()设置主题时使用Base64编码。例如:
sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
//mailMessage是一个javax.mail.Message,而mailInfo是我们自己写的一个类,作用是存放邮件信息。mailInfo.getSubject()是MailInfo类中的方法,目的是获取邮件的主题。
mailMessage.setSubject("=?utf8?B?"+enc.encode(mailInfo.getSubject().getBytes())+"?=");

2.接收邮件时,获取某些邮件发送程序发送的email地址,发送地址显示为乱码
解决办法:
对含有中文的发送地址,使用MimeUtility.decodeTex方法,对其他则把地址从ISO8859_1编码转换成gbk编码,见下例
  public static String getFrom(Message msg){
String from="";
try{
if(msg.getFrom()[0]!=null)
from=msg.getFrom()[0].toString();
if(from.startsWith("=?GB")||from.startWith(“=?gb”)){
from=MimeUtility.decodeText(from);
}else{
from=StringUtil.toChinese(from);
}
}catch(Exception e){
e.printStackTrace();
}
from=StringUtil.replaceStr(from,“<”,“<”);// replaceStr为字符串替换函数
from=StringUtil.replaceStr(from,">",">");
return from;
}
///StringUtil的toChinese方法//
public static String toChinese(String strvalue){
try{
if(strvalue==null)
return null;
else{
strvalue = new String(strvalue.getBytes("ISO8859_1"), "GBK");
return strvalue;
}
}catch(Exception e){
return null;
}
}
3.接收邮件时,获取某个邮件的中文附件名,出现乱码
解决办法:
对于用base64编码过的中文,则采用base64解码,否则对附件名进行ISO8859_1到gbk的编码转换,例如:
 String temp=part.getFileName();//part为Part实例
if((temp.startsWith("=?GBK?B?")&&temp.endsWith("?="))
||(temp.startsWith("=?gbk?b?")&&temp.endsWith("?="))){
temp=StringUtil.getFromBASE64(temp.substring(8,temp.indexOf("?=")-1));
}else{
temp=StringUtil.toChinese(temp);//该方法如前所叙
}

/StringUtil的getFromBASE64方法/

public static String getFromBASE64(String s) {
if (s == null) return null;
BASE64Decoder decoder = new BASE64Decoder();
try {
byte[] b = decoder.decodeBuffer(s);
return new String(b);
} catch (Exception e) {
return null;
}
}
[b]乱码问题的调试步骤总结:[/b]

基本上在javamail中碰到的中文乱码问题就这么多了,如果你的程序出现了中文乱码,首先不要惊慌,可用多个其他的邮件发送或接收程序进行验证,看是在哪个环节出现了问题,然后再仔细对照原文和乱码,调用相应的编码解码方法就行了。

最后,希望这篇短文能对你有所启发,祝你成功。 :arrow:

你可能感兴趣的:(java)