Java mail with attachment: ClassCastException on javax.mail.Multipart

I use the following code to load attachments from mail, but it gives a ClassCastException in the Multipart declaration:

An exception in the "main" thread java.lang.ClassCastException: com.sun.mail.imap.IMAPInputStream cannot be attributed to javax.mail.Multipart in ReadAttachment.main (ReadAttachment.java:52)

How to handle 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(); } 
+7
source share
6 answers

I had the same issue with JavaMail 1.5.1 and OSGi. Using msg.getContent () always returned an InputStream when called from an OSGi package, when it worked fine when called from a simple Java test program.

Setting CommandMap by default did not work for me, but I found a solution here:

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); } 
+5
source

The getContent method returns the content as a Java object, and its type, of course, depends on the content itself.

The object returned for "text / plain" Content is usually a String object.
The object returned for "multi-part" content is always a multi-page subclass.
For content types that are unknown to the DataHandler system, the input stream is returned as content.

Take a look at 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; 

* I do not accept responsibility for possible abuse of an instance

+4
source

OK I think the real problem is that although you have to check the type of object you're returning with ... it can still be IMAPInputStream when it shouldn't.

I beat this for more than two days.

The main problem is that the Java Mail API does something very dumb, it tries to read in the mailcap file, which is not always available if the class switch has been switched. This is especially difficult in my case because I am dealing with OSGi packages and do not seem to have direct control over which bootloader I use .... but I'm distracted.

I found a “fix” ... maybe THE FIX after sifting the Java Mail API source code as a last resort.

  // 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))); 

I worked for several days and found dozens of people with the same problem and different sentences classpath, thread, classloader. But this is the only thing that worked for me, and it is relatively simple. Therefore, post this to what appears to be the closest related issue with some momentum. Phew

+3
source

I fixed this error by adding the following lines of code. There is something wrong with MailCap, javamail cannot find a handler for the multi-part / mixed part, so this bit needs to be added. This solved my problem. Hope this helps someone out there.

 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); 

Hooray!

+3
source

Yes, because you assume that getContent() returns something that Multipart implements, in which case it is not ( IMAPInputStream extends InputStream ).

Your code should consider this possibility.

+2
source

The object returned by getContent depends on the type of message. This will be Multipart if the message type is multipart. You can do an if check to see the MIME type ...

 if(messages[j].getContentType().equals("multipart")) { //Do your cast and stuff } else { //This message isn't a multipart message, maybe just skip it. } 

Of course, this is due to the use of magic strings. A more complicated solution would be to learn the DataHandler API and use the getDataHandler() method in the message. Unfortunately, I know little about this API.

+2
source

All Articles