之所以本人称之为疑难杂症,主要是这个问题网上几乎找不到什么合适解决方式,显然这是小概率事件,呵,言归正传.
故事发生在接收邮件时,有一封邮件死活接收不下来,注意:几百上千封中就那一封!其它的都正常!出现的异常如下:
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程序不存在这个问题哦.
呵,在没解决问题前,都是难题啊,不知道这个高底是不是难题呢?有待高人出现!先谢了!
故事发生在接收邮件时,有一封邮件死活接收不下来,注意:几百上千封中就那一封!其它的都正常!出现的异常如下:
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程序不存在这个问题哦.
呵,在没解决问题前,都是难题啊,不知道这个高底是不是难题呢?有待高人出现!先谢了!
解决方案 »
- 定时器能否加入线程池进行线程管理呢?
- engine 怎么解释??有什么作用??
- 递归不能执行
- 一个非常让我困惑的问题!!!包外子类覆盖方法了吗????
- 写一个方法接收一个字符串,完成以下要求然后返回处理后的字符串
- 请问大家,哪有java编辑器啊?
- 急,关于java打包
- 真心求JAVA源码~~~~给高分(这里只能给100,但我给300,做好后另外开帖给)
- 将两个数组 排列组合到一个数组集合 求java 代码
- 为什么还出现Exception in thread "main" java.lang.NoClassDefFoundError: Client(wrong name Helloworld/Client)
- JButton反序列化后,原来注册的事件不起作用了,要重新注册?
- __面试题,高手低手都请进,在线等!
不然subjcecet:111 是什么意思 乱码?
foxmail收下来主题也是为空的
我想,这封只是特例,现在要解决的是这一类问题,而不是单指这一封
在我印象中其实javamail不单单是这种传输过程中出现邮件头关键字(如:subject,Date等)为乱码的才不能接收,
其它的格式不正确也常不能接收呢,解析先不管(若收下来了,解析还好办点,取不值为空就行了),现在我只想把邮件保存在本地而已,这理论上说应该可以的.
另注:我不用writeTo的方式来保存,用流保存也不行,InputStream is= mimeMessage.getInputStream();并且用流保存只保存邮件体,邮件头丢失,故
本人认为,用流应该不合理,但除了这两种方法保存邮件,我实在想不出第三种了,难道就这样算了?继续等待高人出现......
至于你想
FileOutputStream so = new FileOutputStream("c://test.eml",true);
mimeMessage.writeTo(so);//保存邮件到磁盘
应该没有问题啊,如果用字节流的话。
其实我平时做程序就有种感觉,java有时不是很稳定
与其运行机制有关吧
个人感觉这个问题还是挺不错的,只是专业性较强些,不知道这贴有没达到被推荐的要求呢?不知各位如何认为呢?有没推荐的必要呢?
希望得到你们的支持,谢谢!
曾经在表单中的file类型中,见过file字段的路径中"\"变成"“符号,应该是这个特殊符号的问题吧。
可以说是这个问题吧,但我要说的是,我还有一封没有这个标志,即把subjcecet:111 这行去掉也是接收不了!
这封邮件好像就一个Received字段,其它的都没了,也就是说,邮件格式严重出错了,现在关键是如何把它收到本地来啊后来我又想了下,感觉用只是用writeTo可能无法解决的,只能获取调试信息并分析它来获取主要信息,自己来组合成mimeMessage再使用writeTo输出来解决它,
至于如何获取调试信息,并分析后组成mimeMessage还在研究中,各位也可往这方面提点建意吧.(感觉javamail封装了很多实现提供同时却要格式严格,方便的同时,纠错能力却下降了,有点无奈,不知道这算不算javamail的bug呢?若自己通过调试信息来组合成mimeMessage,这应该是与javamail的初衷是相悖的)(再注:如果foxmail或outlook对这些不规范的邮件收不下来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编码吧?还有接收邮件的时候,我们不都有自己规定的格式么?现在遇到接收格式不对的邮件,你为什么不抛个异常去捕捉呢,做一个提示说此邮件格式不对,不能接收或发送什么的。
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中碰到的中文乱码问题就这么多了,如果你的程序出现了中文乱码,首先不要惊慌,可用多个其他的邮件发送或接收程序进行验证,看是在哪个环节出现了问题,然后再仔细对照原文和乱码,调用相应的编码解码方法就行了。 最后,希望这篇短文能对你有所启发,祝你成功。
收到本地来了,并解析了,javamail现在根本就没收到本地来!故也谈不上去解析(直接解析导常更多了,显然更不可取)
还有就是一碰到异常,此后的邮件经常不收了(有时也收,但收下的全部大小变为0了),也很有问题,看来对于此类不规范邮件只能分析调试信息了,不知有没更好办法呢?
本问题可以这样说吧,"如何解决邮件收不下来"?
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网上有下,找到解决问题的方法比找到问题的结果更有意义,呵呵
javamail其实封装的还是可以的,主要是这个邮件系统里面包含的东西太多了,很多很多的东西虽然有规范,但很多的程序员等不按照规范来,导致了邮箱这块的东西太乱了,OE、FOXMAIL也是经过了很多次的测试和异常处理才出炉的。
我留下我联系方式,我们可以交流交流,我最近也在做这方面的项目。
qq:344964911
[email protected]