【问题标题】:javax.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed; boundaryjavax.activation.UnsupportedDataTypeException:对于 MIME 类型 multipart/mixed 没有对象 DCH;边界
【发布时间】:2014-03-18 08:24:44
【问题描述】:

目前我正在编写一个将监听目录的代码。当使用 .apk 文件更新目录时,我将使用此 .apk 文件向 gmail 帐户发送一封邮件。我在我的程序中使用 Jnotify 和 JAVA Mail。

我得到的错误是,

javax.mail.MessagingException: IOException while sending message;
  nested exception is:
javax.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed; boundary="----=_Part_0_145238.1392728439484"

我在 stackoverflow 中寻找解决方案以寻求帮助,但没有一个有用。

提前致谢

public void fileCreated(int wd, String rootPath, String name) {
    print("created " + rootPath + " : " + name);

    if (name.contains(".apk"))
      SendEmail(name);
    else
        System.out.println("Not the APK file");
}

void SendEmail(String strname){
    String Path = "D:/POC/Email/apk folder/"+strname;
    System.out.println("Path->" + Path);

    Properties props = new Properties();
    props.put("mail.smtp.host","173.194.78.108");
    props.put("mail.smtp.socketFactory.port", "465");
    props.put("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");
    props.put("mail.smtp.auth","true");
    props.put("mail.smtp.port","465");

    System.out.println("Properties has been set properly");

    Session session = Session.getDefaultInstance(props,
        new javax.mail.Authenticator(){
            protected PasswordAuthentication getPasswordAuthentication(){
                return new PasswordAuthentication("SenderEmailID@gmail.com", "senderPassword");
            }
        }
    );

    System.out.println("Session Created successfully");

    try{
        Message message = new MimeMessage(session); 
        message.setFrom(new InternetAddress("SenderEmailID@gmail.com"));
        message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("ToReceiverEmailID@gmail.com"));
        message.setSubject("Android : " + strname);

        MimeBodyPart msgbody = new MimeBodyPart();
        msgbody.setText("This is the message content which is sent using JAVA MAIL 1.4.5");
        Multipart mulpart = new MimeMultipart();
        mulpart.addBodyPart(msgbody);

        //Attachement Starts here.
        msgbody = new MimeBodyPart();
        javax.activation.DataSource source = new FileDataSource(Path);
        msgbody.setDataHandler(new DataHandler(source));
        msgbody.setFileName(strname);
        message.setContent(mulpart);

        System.out.println("Attached the message going to start transporting the mail");

        //If I've the code before sending the email is getting sent but without attachment. 
        //Thread.currentThread().setContextClassLoader( getClass().getClassLoader() );

        Transport.send(message);
        System.out.println("Mail Sent successfully");
    }
    catch(MessagingException msg){
        msg.printStackTrace();
    }
    catch(Exception e){
        e.printStackTrace();
    }
}

【问题讨论】:

    标签: java email jakarta-mail ioexception jnotify


    【解决方案1】:

    JavaMail 依赖于一些配置文件来将 MIME 类型映射到 Java 类(例如,multipart/mixedjavax.mail.internet.MimeMultipart)。这些配置文件是使用应用程序的 ClassLoader 加载的。如果 ClassLoader 不能正常工作,就找不到这些配置文件。

    您可以简单地添加以下行 .. 解决问题。

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

    【讨论】:

    • “如果 ClassLoader 无法正常运行,将找不到这些配置文件”是什么意思。这是Java中的错误吗?应该总是添加这些吗?还是应该自动加载?
    • ics/文本/日历文件的其他信息:看看这里:stackoverflow.com/a/67521336/14972917
    【解决方案2】:

    这个问题可以通过以下两个步骤得到解决。

    1. 确保 java 邮件是 1.4.7。(以前我使用 1.4.5,这导致了所有的混乱)。从http://www.oracle.com/technetwork/java/index-138643.html下载
    2. 在发送消息前添加这段代码:
        Thread.currentThread().setContextClassLoader( getClass().getClassLoader() );
    

    【讨论】:

    • 是的,您需要确保类找到资源文件(mailcap 等)。在我的情况下,我不得不重命名 META-INF 目录,因此不再找到它们。将邮件帽等东西上移了一层,它又可以工作了。
    • 我可以确认 - Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); - 确实需要让它再次工作。
    • 在 kotlin 脚本中为我工作Thread.currentThread().contextClassLoader = javaClass.classLoader
    • Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); 也为我工作,谢谢!
    • 我们使用 OSGO,我们也使用了这个 hack,并设置了特定 javax.mail 类(如 Session)的类加载器,以确保它是知道这些 MailCap 文件所在位置的类加载器。例如:Thread.currentThread().setContextClassLoader( javax.mail.Session.class.getClassLoader() );
    【解决方案3】:

    在发送邮件之前添加当前线程是解决方案:

    Thread.currentThread().setContextClassLoader( getClass().getClassLoader() );
    

    【讨论】:

      【解决方案4】:

      我正忙于将 Java 8 项目转换为 Java 10。同时我一直在更新所有依赖项。我遇到了类似的异常,上述解决方案都不适合我。

      我的 pom.xml 中有以下内容:

      <dependency>
          <groupId>com.sun.mail</groupId>
          <artifactId>javax.mail</artifactId>
          <version>1.6.1</version>
      </dependency>
      

      我做了更多的研究,发现了以下链接:

      http://www.jguru.com/faq/view.jsp?EID=237257

      所以我尝试将以下依赖项添加到我的 pom.xml:

      <dependency>
          <groupId>javax.activation</groupId>
          <artifactId>activation</artifactId>
          <version>1.1.1</version>
       </dependency>
      

      这解决了问题,我可以再次发送带有附件的邮件。

      【讨论】:

      • 谢谢。这正是我一直在寻找的。在迁移到 Java 10 时遇到了同样的问题。
      【解决方案5】:

      Som 的回答对我有用。但是,我在使用 JavaMail DSN 时必须修改映射,并且还需要那些 mailcap 条目(包括在下面,包括 Som 的回答):

      // Original answer from Som:
      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");
      
      // Additional elements to make DSN work 
      mc.addMailcap("multipart/report;;  x-java-content-handler=com.sun.mail.dsn.multipart_report");
      mc.addMailcap("message/delivery-status;; x-java-content-handler=com.sun.mail.dsn.message_deliverystatus");
      mc.addMailcap("message/disposition-notification;; x-java-content-handler=com.sun.mail.dsn.message_dispositionnotification");
      mc.addMailcap("text/rfc822-headers;;   x-java-content-handler=com.sun.mail.dsn.text_rfc822headers");
      

      事实证明,将 DSN JAR 添加到我的胖 JAR(使用 shadowJar/Gradle)中导致了问题:DSN jar 中的 META-INF/mailcap 覆盖了核心。

      【讨论】:

        【解决方案6】:

        请告诉我更多关于您的代码运行环境的信息。你用的是什么JDK?您是否在应用服务器中运行?

        JavaBeans 激活框架 (JAF) 查找配置文件,这些文件告诉如何将 MIME 类型映射到处理它们的 Java 类 (DataContentHandlers)。它使用 ClassLoader 来查找配置文件。如果 ClassLoader 有问题,可能是找不到配置文件。

        您可能想尝试here 描述的解决方法,但当然最好为您确定问题的根本原因。

        最后,您可能希望通过修复其中一些common JavaMail mistakes 来简化您的程序。

        【讨论】:

        • 感谢您的回复 java version "1.7.0_51" Java(TM) SE Runtime Environment (build 1.7.0_51-b13) Java HotSpot(TM) Client VM (build 24.51-b03, mixed mode,分享)我没有在应用服务器上运行代码。我在传输消息之前在我的代码中尝试了解决方法,但它对我没有帮助我得到了同样的错误我想在这里添加的另一个信息,当我在函数中运行代码时,“SendEmail”分别运行成功并且能够发送带有附件的邮件。只有当我使用 JNotifyListener 函数时才会出现问题。
        • 你是如何运行你的应用程序的?您的应用程序是否在 jar 文件中?您是否还在使用未更改的 javax.mail.jar 文件?还是您将 JavaMail 类放在您的应用程序 jar 文件中?
        • 另外,请注意 JDK 7 能够监视文件的更改,因此您可能不需要 JNotify。
        • 怎么样?出了什么问题?
        • 主要问题是我使用的是 Java Mail 1.4.5。当我尝试使用 Thread.currentThread().setContextClassLoader(getClass().getClassLoader());我收到了邮件,但没有附件。当我将 Java Mail 的版本更改为 1.4.7.it 解决了这个问题
        【解决方案7】:

        如果是android项目,很有可能是proguard误删掉了未使用的类,请在proguard文件中添加以下行修复问题,无需直接修改代码:

        -keep class com.sun.mail.handlers.**
        -dontwarn com.sun.mail.handlers.handler_base
        

        【讨论】:

          【解决方案8】:

          Som 的回答 (MailcapCommandMap) 对我在 Liferay 7.1 ga1 中的 Spring war Portlet 有效。但是,我必须从 tomcat/lib/ext 中删除 Tomcat 的 mail.jar 并将其替换为 javax.mail-1.6.2.jar,然后确保依赖项的范围与项目的 pom.xml 中提供的一样:

          <dependency>
              <groupId>com.sun.mail</groupId>
              <artifactId>javax.mail</artifactId>
              <version>1.6.2</version>
              <scope>provided</scope>
          </dependency>
          

          【讨论】:

            【解决方案9】:

            在 OSGI 下,以下解决方法允许 javax.activation 包从 javax.mail 包中加载“META-INF/mailcap”资源:

            Thread.currentThread().setContextClassLoader(javax.mail.Message.class.getClassLoader());
            

            注意:字符集转换可能有此解决方法的限制...

            【讨论】:

            • 我在 OSGI 下,一切正常。在我将 apache commons-email 从 1.4 更新到 1.5 和/或 javax.mail 从 1.5.2 更新到 1.5.6 后,它开始失败!
            【解决方案10】:

            如果您的 build.xml 这样做: zipfileset src="javamail-1.4.7/mail.jar" excludes="META-INF/"**

            然后您将剥离配置信息。

            【讨论】:

              【解决方案11】:

              即使我也遇到过同样的问题。我尝试了不同版本的javamail,它没有工作。问题是 Transport.send() 使用了默认 java jdk(在我的例子中是 JAVA 8)中的 MailCapCommandMap 类,该类加载了过时的 mailcap 文件。

              所以我使用了最新版本的 JAVA,之后它使用了 activation 包中的 MailCapCommandMap,它加载了正确的 mailcap 文件。

              如果将来有人遇到同样的问题,只需在可用的MailCapCommandMap 类中添加一个断点,以便您知道它正在使用哪个 mailcap 文件。

              【讨论】:

                【解决方案12】:

                在 Java 12 上运行 Java 8 S/MIME 解析代码时出现了类似的问题。 相关(缺失)DCH 用于自定义 MIME 类型 message/disposition-notification

                与旧 Java 的原生 javax.activation.ObjectDataContentHandler 不同, 用于 Java 9+ 的外部 javax.activation:activation 库似乎不能容忍“未知”的 MIME 类型; 早期,具有此类自定义内容类型的多部分“部分”(在mailcap 元文件中找不到) 如果它们包含 byte[]String 内容,它们仍然会被消耗 - 但现在不会了。

                // old native
                    public void writeTo(Object obj, String mimeType, OutputStream os) throws IOException {
                        if (this.dch != null) {
                            this.dch.writeTo(obj, mimeType, os);
                        } else if (obj instanceof byte[]) {
                            os.write((byte[])((byte[])obj));
                        } else {
                            if (!(obj instanceof String)) {
                                throw new UnsupportedDataTypeException("no object DCH for MIME type " + this.mimeType);
                            }
                
                            OutputStreamWriter osw = new OutputStreamWriter(os);
                            osw.write((String)obj);
                            osw.flush();
                        }
                    }
                
                
                // new javax.activation:activation
                    public void writeTo(Object obj, String mimeType, OutputStream os)
                                        throws IOException {
                    if (dch != null)
                        dch.writeTo(obj, mimeType, os);
                    else
                        throw new UnsupportedDataTypeException(
                                "no object DCH for MIME type " + this.mimeType);
                    }
                

                解决方案是为message/disposition-notification 定义一个条目(它可以安全地解释为文本) 在mailcap 文件中;技术上类似于@Som 的回答,但我们都喜欢无代码解决方案,对吧?

                message/disposition-notification;;x-java-content-handler=com.sun.mail.handlers.text_plain
                

                并将其捆绑到 JAR(类路径)中;例如使用 Maven:

                    <build>
                        <resources>
                            <resource>
                                <directory>src/main/resources</directory>
                                <includes>
                                    <include>META-INF/mailcap</include>
                                </includes>
                            </resource>
                        </resources>
                    </build>
                

                另外值得注意的是:在JVM上设置一个-Djavax.activation.debug=true系统属性, 极大地帮助跟踪与 mailcap 加载、处理、回退等相关的问题。

                【讨论】:

                  【解决方案13】:

                  如果有人在包含 Apache Tika 2 后遇到问题,可能是由于 Tika 中嵌入了邮件依赖项。

                  我们设法通过添加一个 Maven 排除来解决这个问题,只在类路径上留下 javax.mail。比如:

                  <dependency>
                    <groupId>org.apache.tika</groupId>
                    <artifactId>tika-parsers-standard-package</artifactId>
                    <exclusions>
                      <exclusion>
                        <groupId>org.bouncycastle</groupId>
                        <artifactId>bcmail-jdk15on</artifactId>
                      </exclusion>
                    </exclusions>
                  </dependency>
                  

                  【讨论】:

                    猜你喜欢
                    • 2013-08-08
                    • 2020-06-11
                    • 1970-01-01
                    • 1970-01-01
                    • 2014-11-18
                    • 2014-10-16
                    • 1970-01-01
                    • 2015-01-06
                    • 2019-07-21
                    相关资源
                    最近更新 更多