【问题标题】:Java mail with attachment: ClassCastException on javax.mail.Multipart带附件的 Java 邮件:javax.mail.Multipart 上的 ClassCastException
【发布时间】:2011-06-03 09:54:18
【问题描述】:

我使用以下代码从邮件中下载附件,但它在 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();
}

【问题讨论】:

    标签: java jakarta-mail


    【解决方案1】:

    是的,因为您假设 getContent() 返回实现 Multipart 的东西,而在这种情况下它没有(IMAPInputStream 扩展 InputStream)。

    您的代码需要考虑这种可能性。

    【讨论】:

      【解决方案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 了解不多。

      【讨论】:

        【解决方案3】:

        getContent 方法将内容作为 Java 对象返回,其类型当然取决于内容本身。

        为“text/plain”返回的对象 content 通常是一个字符串对象。
        为“多部分”返回的对象 内容始终是 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

        承担责任

        【讨论】:

          【解决方案4】:

          好的。我认为这里真正的问题是,尽管您应该检查您要返回的对象类型....它仍然可能是 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)));
          

          我已经在谷歌上搜索了好几天,发现有几十个人有同样的问题以及各种类路径、线程、类加载器的建议。但这是唯一对我有用的东西,而且相对简单。因此,将此发布到似乎是最接近的相关问题,并具有一定的动力。呸。

          【讨论】:

            【解决方案5】:

            我已通过添加以下代码行来修复此错误。 MailCap有问题,javamail找不到multipart/mixed部分的handler,所以需要加上这个位。这解决了我的问题。希望它可以帮助那里的人。

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

            干杯!

            【讨论】:

            • 我正在尝试使用 jdeveloper 从 gmail 服务器接收电子邮件。我尝试实施您的解决方案,但无法导入 javax.activation。* 请参阅此帖子了解更多详细信息 stackoverflow.com/questions/38436576/…。请帮帮我
            • @HellsGuardian 我已经很久没有从事这个工作了,所以无法提供任何输入。
            【解决方案6】:

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

            【讨论】:

              猜你喜欢
              • 2013-07-11
              • 2018-06-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-07-23
              相关资源
              最近更新 更多