我使用以下代码从邮件中下载附件,但它在Multipart声明中提供了ClassCastException
:
线程“main”中的异常java.lang.ClassCastException:com.sun.mail.imap.IMAPInputStream无法强制转换为javax.mail.Multipart 在ReadAttachment.main(ReadAttachment.java:52)
如何处理IMAPInputStream?
Message messages[] = inbox.getMessages();
for (int j = 0; j < messages.length; j++) {
String mailType = messages[j].getContentType();
System.out.println("-- Message " + (j + 1) + " --");
System.out.println("SentDate : " + messages[j].getSentDate());
System.out.println("From : " + messages[j].getFrom()[0]);
System.out.println("Subject : " + messages[j].getSubject());
System.out.println("Type :" + messages[j].getContentType());
System.out.println("Attachment :" + messages[j].getFileName());
Multipart mp = (Multipart) messages[j].getContent();
..
System.out.println();
}
答案 0 :(得分:5)
我遇到了与JavaMail 1.5.1和OSGi相同的问题。使用msg.getContent()总是在从OSGi包中调用时返回一个InputStream,而当从一个简单的Java测试程序调用时它可以正常工作。
设置默认的CommandMap对我来说不起作用,但我在这里找到了一个解决方案:
https://www.java.net/node/705585
ClassLoader tcl = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(javax.mail.Session.class.getClassLoader());
// now call JavaMail API
// ...
} finally {
Thread.currentThread().setContextClassLoader(tcl);
}
答案 1 :(得分:4)
getContent方法将内容作为Java对象返回,其类型当然取决于内容本身。
为“text / plain”返回的对象 content通常是一个String对象 返回的对象为“multipart” 内容始终是Multipart 子类。
对于内容类型 DataHandler系统未知, 输入流作为返回 内容。
见到Java Apache Cocoon source code * :
Object objRef = msg.getContent();
if (!(objRef instanceof Multipart)) {
String message = "This Message is not a multipart message!";
getLogger().warn(message);
return;
}
Multipart multipart = (Multipart) objRef;
*我不承担可能滥用 instanceof
的责任答案 2 :(得分:3)
行。我认为这里真正的问题是,虽然你应该检查你正在回来的对象类型......它仍然可能是IMAPInputStream,但它不应该是。
我已经坚持了两天以上。
基本问题通常是Java Mail API做了一些非常愚蠢的事情,它试图读取一个名为mailcap的文件,如果已经切换了类加载器,那么这个文件并不总是可用。这在我的情况下特别棘手,因为我正在处理OSGi包,并且似乎没有直接控制我正在使用哪个加载器....但我离题了。
我发现'修复'......也许是在筛选Java Mail API的源代码之后作为最后的手段进行修复。
// Set up our Mailcap entries. This will allow the JAF
// to locate our viewers.
File capfile = new File("/path/to/mailcap");
if (!capfile.isFile()) {
System.out.println(
"Cannot locate the \"simple.mailcap\" file.");
System.exit(1);
}
CommandMap.setDefaultCommandMap( new MailcapCommandMap(
new FileInputStream(capfile)));
我已经谷歌搜索了几天,发现了几十个有同样问题和各种类路径,线程,类加载器建议的人。但这是唯一对我有用的东西,它相对简单。因此将这个发布到似乎是最接近的相关问题并且有一些动力。呼。
答案 3 :(得分:3)
我已通过添加以下代码行修复了此错误。 MailCap有问题,javamail找不到multipart / mixed部分的处理程序,所以需要添加这个位。这解决了我的问题。希望它可以帮助那些人。
MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
CommandMap.setDefaultCommandMap(mc);
干杯!
答案 4 :(得分:2)
是的,因为您假设getContent()
返回实现Multipart
的内容,而在这种情况下它不会(IMAPInputStream
扩展InputStream
)。
您的代码需要考虑到这种可能性。
答案 5 :(得分:2)
getContent
返回的对象取决于消息类型。如果消息类型是 multipart ,它将只是Multipart。您可以执行if检查以查看MIME类型...
if(messages[j].getContentType().equals("multipart")) {
//Do your cast and stuff
} else {
//This message isn't a multipart message, maybe just skip it.
}
当然,这涉及使用魔术字符串。更复杂的解决方案是查看DataHandler API并在消息上使用getDataHandler()
方法。不幸的是,我对该API了解不多。