2011-01-04 12 views
7

Io uso il seguente codice per scaricare l'allegato dal posta, ma dà la ClassCastException sulla dichiarazione Multipart:posta Java con allegato: ClassCastException su javax.mail.Multipart

Exception in thread java "principale" .lang.ClassCastException: com.sun.mail.imap.IMAPInputStream non può essere lanciato a javax.mail.Multipart a ReadAttachment.main (ReadAttachment.java:52)

Come faccio a gestire 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(); 
} 

risposta

2

Sì, perché si sta assumendo che getContent() restituisce qualcosa che implementa Multipart, e in questo caso non è così (IMAPInputStream estende InputStream).

Il codice deve tenere conto di questa possibilità.

+0

Grazie skaffman !! –

2

L'oggetto restituito da getContent dipende dal tipo di messaggio. Sarà Multipart se il tipo di messaggio è multipart. Si potrebbe fare un caso di controllo a guardare il tipo MIME ...

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

Certo che prevede l'utilizzo di stringhe di magia. Una soluzione più sofisticata sarebbe esaminare l'API DataHandler e utilizzare il metodo getDataHandler() nel messaggio. Sfortunatamente non ne so molto di questa API.

4

Il metodo getContent restituisce il contenuto come un oggetto Java e il suo tipo dipende ovviamente dal contenuto stesso.

L'oggetto restituito per "text/plain" di solito è un oggetto String.
L'oggetto restituito per un contenuto "multipart" è sempre una sottoclasse Multipart .
Per i tipi di contenuto che sono sconosciuti al sistema DataHandler , un flusso di input viene restituito come contenuto .

visto su 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; 

* non prendo la responsabilità per l'eventuale uso improprio di instanceof

+0

Grazie per il tuo gentile aiuto systempuntoout !!! –

+0

@Karth se hai trovato utile questa risposta, puoi invitarla o anche contrassegnarla come accettata – systempuntoout

3

OK. Penso che il vero problema qui sia che anche se dovresti controllare il tipo di oggetto che stai recuperando .... potrebbe ancora essere IMAPInputStream quando non dovrebbe esserlo.

Ho martellato su questo per oltre due giorni.

Il problema sottostante è spesso che l'API Java Mail fa qualcosa di molto stupido, prova a leggere in un file chiamato mailcap che non è sempre disponibile se è stato cambiato il programma di caricamento classi. Questo è particolarmente difficile nel mio caso perché ho a che fare con bundle OSGi e non sembrano avere il controllo diretto su quale loader sto usando .... ma sto divagando.

Ho trovato "una correzione" ... forse THE FIX dopo aver setacciato il codice sorgente dell'API Java Mail come ultima risorsa.

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

Sono stato googling per giorni e abbiamo trovato decine di persone con lo stesso problema e vari classpath, filo, suggerimenti classloader. Ma questa è l'unica cosa che ha funzionato per me ed è relativamente semplice. Quindi postare questo a quello che sembra essere il problema correlato più vicino con un certo slancio. PHEW.

3

Ho corretto questo errore aggiungendo le seguenti righe di codice. C'è qualcosa di sbagliato in MailCap, javamail non riesce a trovare un gestore per la parte multipart/mixed, quindi è necessario aggiungere questo bit. Questo ha risolto il mio problema. Spero che aiuti qualcuno là fuori.

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

Cheers!

+0

Sto provando a ricevere e-mail dal server di Gmail usando jdeveloper. Ho provato a implementare la tua soluzione ma non riesco a importare javax.activation. * Per ulteriori dettagli, fai riferimento a questo post https://stackoverflow.com/questions/38436576/unable-to-import-javax-activation-in- JDeveloper-per-MAF. Per favore aiutatemi –

+0

@HellsGuardian da molto tempo che non ci sono stati input. – jagmohan

5

Ho avuto lo stesso problema con JavaMail 1.5.1 e OSGi. L'uso di msg.getContent() ha sempre restituito un InputStream quando viene chiamato da un bundle OSGi mentre funziona perfettamente quando viene chiamato da un semplice programma di test Java.

impostazione predefinita CommandMap non ha funzionato per me, ma ho trovato qui una soluzione:

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); 
} 
Problemi correlati