Java-почта с вложением: ClassCastException на javax.mail.Multipart - PullRequest
7 голосов
/ 04 января 2011

Я использую следующий код для загрузки вложения из почты, но он дает 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();
}

Ответы [ 6 ]

5 голосов
/ 24 января 2014

У меня была такая же проблема с JavaMail 1.5.1 и OSGi.Использование msg.getContent () всегда возвращало InputStream при вызове из пакета OSGi, в то время как он прекрасно работает при вызове из простой тестовой программы на 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);
}
4 голосов
/ 04 января 2011

Метод getContent возвращает содержимое как объект Java, и его тип, конечно, зависит от самого содержимого.

Объект возвращен для "text / plain" content обычно является объектом String.
Объект возвращен для «multipart» содержание всегда является составным подкласс.
Для типов контента, которые неизвестный системе DataHandler, входной поток возвращается как содержание.

При просмотре на Java Apache Cocoon Исходный код *:

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

3 голосов
/ 29 августа 2013

Я исправил эту ошибку, добавив следующие строки кода.Что-то не так с MailCap, javamail не может найти обработчик для составной / смешанной части, поэтому этот бит необходимо добавить.Это решило мою проблему.Надеюсь, это кому-нибудь поможет.

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

Ура!

3 голосов
/ 05 октября 2012

OK. Я думаю, что реальная проблема здесь в том, что, хотя вы должны проверять тип объекта, который вы возвращаете ... это может быть 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)));

Я много дней гуглял и нашел десятки людей с такой же проблемой и различными предложениями classpath, thread, classloader. Но это единственное, что сработало для меня, и это относительно просто. Отсюда и публикация этого к тому, что кажется ближайшим связанным вопросом с некоторым импульсом. Уф.

2 голосов
/ 04 января 2011

Объект, возвращаемый 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.
}

Конечно, это связано с использованием магических строк.Более сложным решением было бы заглянуть в API DataHandler и использовать в сообщении метод getDataHandler().К сожалению, я мало что знаю об этом API.

2 голосов
/ 04 января 2011

Да, потому что вы предполагаете, что getContent() возвращает что-то, что реализует Multipart, и в этом случае это не так (IMAPInputStream расширяет InputStream).

Ваш код должен быть учтенза эту возможность.

...