论坛首页 Java企业应用论坛

JavaMail的编码问题

浏览 4841 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-03-25   最后修改:2009-03-25
在使用javamail api开发邮件服务系统时,我们常常会碰到很多中文乱码问题,下面就分别介绍如何解决这些问题。
先介绍一下javamail的编码:
1、内容编码:
    当一段 Text 或者 HTML 通过电子邮件传送时,发送的内容首先通过一种指定的字符编码转化成“字节串”,然后再把“字节串”通过一种指定的传输编码(Content-Transfer-Encoding)进行转化得到另一串“字节串”。比如,打开一封电子邮件源代码,可以看到类似的内容:
Content-Type: text/plain;charset="gb2312"
Content-Transfer-Encoding: base64
sbG+qcrQuqO17cf4yee74bGjz9W7+b3wudzA7dbQ0MQNCg0KvPKzxqO6uqO17cnnsaPW0NDEDQoNCg==

最常用的 Content-Transfer-Encoding 有 Base64 和 Quoted-Printable 两种。在对二进制文件或者中文文本进行转化时,Base64 得到的“字节串”比 Quoted-Printable 更短。在对英文文本进行转化时,Quoted- Printable 得到的“字节串”比 Base64 更短。
2、标题编码:
    邮件的标题,用了一种更简短的格式来标注“字符编码”和“传输编码”。比如,标题内容为 "中",则在邮件源代码中表示为:
// 正确的标题格式
Subject: =?GB2312?B?1tA=?=   //subject是指标题内容
其中,
第一个“=?”与“?”中间的部分指定了字符编码,在这个例子中指定的是 GB2312。
“?”与“?”中间的“B”代表 Base64。如果是“Q”则代表 Quoted-Printable。
最后“?”与“?=”之间的部分,就是经过 GB2312 转化成字节串,再经过Base64 转化后的标题内容。
如果“传输编码”改为 Quoted-Printable,同样,如果标题内容为 "中":
// 正确的标题格式
Subject: =?GB2312?Q?=D6=D0?=
    如果阅读邮件时出现乱码,一般是因为“字符编码”或“传输编码”指定有误,或者是没有指定。比如,有的发邮件组件在发送邮件时,标题 "中":
// 错误的标题格式
Subject: =?ISO-8859-1?Q?=D6=D0?=
这样的表示,实际上是明确指明了标题为 [0x00D6, 0x00D0],即 "ÖÐ",而不是 "中"。
解决乱码方法
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;
       }
     }
乱码问题的调试步骤总结:

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

最后,希望这篇短文能对你有所启发,祝你成功。 
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics