之所以本人称之为疑难杂症,主要是这个问题网上几乎找不到什么合适解决方式,显然这是小概率事件,呵,言归正传.
故事发生在接收邮件时,有一封邮件死活接收不下来,注意:几百上千封中就那一封!其它的都正常!出现的异常如下:
javax.mail.MessagingException: error fetching POP3 content;
  nested exception is:
java.io.IOException: Unexpected response: 
at com.sun.mail.pop3.POP3Message.getContentStream(POP3Message.java:207)
at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1760)
at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1718)很显然是这封邮件的格式有问题,我在服务器上找到该封邮件,下载下来打开一看,果然是格式问题导致的,该邮件内容如下:
X-QQ-mid:esmtp7t1238394547t84t8787
Received: from aa (unknown [121.204.126.238])
by esmtp7.qq.com (ESMTP) with SMTP id 0
for <[email protected]>; Mon, 30 Mar 2009 14:27:35 +0800 (CST)
subjcecet:111s
.这样导导我用:
FileOutputStream so = new FileOutputStream("c://test.eml",true);
mimeMessage.writeTo(so);//保存邮件到磁盘
保存失败,得到的test.eml文件大小为0!
应该表述得还算清楚吧,我研究了大半天,还是无效解决,只能请高人支招了!
注:用foxmail和outlook都可以接收,我想,javamail没理由不行吧?如果你也在搞javamail,不知你测试过格式不正确的邮件接收么?
如果没有,那只是你没见到这个问题而已,并不表示你写的javamail程序不存在这个问题哦.
呵,在没解决问题前,都是难题啊,不知道这个高底是不是难题呢?有待高人出现!先谢了!

解决方案 »

  1.   

    是不是这邮件在传输的时候损坏了
    不然subjcecet:111 是什么意思 乱码?
      

  2.   

    还没有试过接受不正确的。最近在用swing做一个客户端,学下swing而已。可能还在初级阶段吧,没遇到什么难题。
      

  3.   

    应该是传输过程或发送时产生的,那个应该是乱码,我打开看就那样了,服务器上解析为无主题无发件人,内容为:s . 
    foxmail收下来主题也是为空的
    我想,这封只是特例,现在要解决的是这一类问题,而不是单指这一封
      

  4.   

    可人家的却可以接收啊(如foxmail),虽然只是小概率事件,但还是希望能解决呢
    在我印象中其实javamail不单单是这种传输过程中出现邮件头关键字(如:subject,Date等)为乱码的才不能接收,
    其它的格式不正确也常不能接收呢,解析先不管(若收下来了,解析还好办点,取不值为空就行了),现在我只想把邮件保存在本地而已,这理论上说应该可以的.
    另注:我不用writeTo的方式来保存,用流保存也不行,InputStream is= mimeMessage.getInputStream();并且用流保存只保存邮件体,邮件头丢失,故
    本人认为,用流应该不合理,但除了这两种方法保存邮件,我实在想不出第三种了,难道就这样算了?继续等待高人出现......
      

  5.   

    会不会是发送或接收时,解析文件格式不同如:ISO8859,解析为GBK。这样会出现乱码格式
    至于你想
    FileOutputStream so = new FileOutputStream("c://test.eml",true); 
    mimeMessage.writeTo(so);//保存邮件到磁盘 
    应该没有问题啊,如果用字节流的话。
      

  6.   

    顶了,
    其实我平时做程序就有种感觉,java有时不是很稳定
    与其运行机制有关吧
      

  7.   

    不知有没那位跟版主比较熟呀,希望能帮忙推荐下到首页,多让些高手来参与下啊,我想csdn应该有人能解决这个问题的,虽然很多是来学习的,但相信高人还是不少的,呵
    个人感觉这个问题还是挺不错的,只是专业性较强些,不知道这贴有没达到被推荐的要求呢?不知各位如何认为呢?有没推荐的必要呢?
    希望得到你们的支持,谢谢!
      

  8.   

    JAVAX.MAIL实在是没用过这个类
      

  9.   

    帮你UP一下,偶只用过一点点jmail
      

  10.   

    subjcecet:111
    曾经在表单中的file类型中,见过file字段的路径中"\"变成"“符号,应该是这个特殊符号的问题吧。
      

  11.   

    首先感谢版主的推荐啦
    可以说是这个问题吧,但我要说的是,我还有一封没有这个标志,即把subjcecet:111 这行去掉也是接收不了!
    这封邮件好像就一个Received字段,其它的都没了,也就是说,邮件格式严重出错了,现在关键是如何把它收到本地来啊后来我又想了下,感觉用只是用writeTo可能无法解决的,只能获取调试信息并分析它来获取主要信息,自己来组合成mimeMessage再使用writeTo输出来解决它,
    至于如何获取调试信息,并分析后组成mimeMessage还在研究中,各位也可往这方面提点建意吧.(感觉javamail封装了很多实现提供同时却要格式严格,方便的同时,纠错能力却下降了,有点无奈,不知道这算不算javamail的bug呢?若自己通过调试信息来组合成mimeMessage,这应该是与javamail的初衷是相悖的)(再注:如果foxmail或outlook对这些不规范的邮件收不下来javamail也没什么可说的了,现在问题是它们能够啊)
    对了,有人可能好奇我这些不规范邮件是怎么产生了,记得好像是当初做邮件发送测试(应该是在命令中测试发送)时产生的.
      

  12.   

    我没写过javamail,但是也很想学学
    lz是不是接收的时候不是乱码的话就能保存呢?也就是说
    X-QQ-mid:esmtp7t1238394547t84t8787 
    Received: from aa (unknown [121.204.126.238]) 
    by esmtp7.qq.com (ESMTP) with SMTP id 0 
    for <[email protected]>; Mon, 30 Mar 2009 14:27:35 +0800 (CST) 
    subjcecet:111 s 

    这段接收的内容不是乱码就行?lz是否用了base64解码呢?

    //base64解码 
     private String base64Decoder(String s) throws Exception 
     { 
      sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder(); 
      byte[] b=decoder.decodeBuffer(s); 
       
      return(new String(b)); 
     } 
    不过好像只有文件名才需要base64编码吧?还有接收邮件的时候,我们不都有自己规定的格式么?现在遇到接收格式不对的邮件,你为什么不抛个异常去捕捉呢,做一个提示说此邮件格式不对,不能接收或发送什么的。
      

  13.   

    是不是用foxmail接收的话,就没有产生乱码?而是正常的接收了?
      

  14.   

    把test.eml的文件保存成utf-8的编码形式
      

  15.   

    楼主请读下这篇文章,也许对你的问题有所帮助:
    JavaMail的编码问题
    关键字: javamail的编码问题, javamail乱码 
    在使用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编码。例如:Java代码 
    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())+"?=");  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编码,见下例Java代码 
    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;   
         }   
       }    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的编码转换,例如:Java代码 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;   
          }   
        }   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中碰到的中文乱码问题就这么多了,如果你的程序出现了中文乱码,首先不要惊慌,可用多个其他的邮件发送或接收程序进行验证,看是在哪个环节出现了问题,然后再仔细对照原文和乱码,调用相应的编码解码方法就行了。 最后,希望这篇短文能对你有所启发,祝你成功。  
      

  16.   

    捕捉异常还是没解决问题啊,这封邮件还是没法弄到本地来呢,foxmail收下来,由于主题关系字subject有乱码,认不到,故为无主题(主题为空)的,但内容还是有的,总之它是
    收到本地来了,并解析了,javamail现在根本就没收到本地来!故也谈不上去解析(直接解析导常更多了,显然更不可取)
    还有就是一碰到异常,此后的邮件经常不收了(有时也收,但收下的全部大小变为0了),也很有问题,看来对于此类不规范邮件只能分析调试信息了,不知有没更好办法呢?
      

  17.   

    呵,如果你没搞过javamail,或其它邮件方面的系统,确实有点抽象,也别怀疑自己阅读能力啦(呵,我从不怀疑自己的任何能力的,虽然知道自己能力不济)
    本问题可以这样说吧,"如何解决邮件收不下来"?
      

  18.   

    你在foxmail里把那封用javamail生成不了eml的邮件令存为文件,看看foxmail另存为的eml文件有什么不一样的地方
      

  19.   

    还有就是跟踪一下抛出的异常javax.mail.MessagingException: error fetching POP3 content; 
      nested exception is: 
    java.io.IOException: Unexpected response: 
    at com.sun.mail.pop3.POP3Message.getContentStream(POP3Message.java:207) 
    at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1760) 
    at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1718) 这里面应该告诉了哪一行产生了错误,你可以跟踪到POP3Message.java:207 MimeMessage.java:1760 MimeMessage.java:1718javamail的src网上有下,找到解决问题的方法比找到问题的结果更有意义,呵呵
      

  20.   

    是呀,研究javamail的源码,并更改下理论上说也是可行的,但这样麻烦且不好改先不说,改了可能会产生更多的问题(本来只是小概率的问题,可能会变大概率的了,那样得不偿失啊),但研究下源码这思想是很好的,这就直面问题本质了,但若能用其它替换方式解决的话,也是不错的.
      

  21.   

    哥们同感啊,我最近也遇到了,不知道你解决了没有。
    javamail其实封装的还是可以的,主要是这个邮件系统里面包含的东西太多了,很多很多的东西虽然有规范,但很多的程序员等不按照规范来,导致了邮箱这块的东西太乱了,OE、FOXMAIL也是经过了很多次的测试和异常处理才出炉的。
    我留下我联系方式,我们可以交流交流,我最近也在做这方面的项目。
    qq:344964911
    [email protected]