javax.activation.UnsupportedDataTypeException:没有MIME类型multipart / mixed的对象DCH;边界

时间:2014-02-18 14:05:37

标签: java email javamail ioexception jnotify

目前,我正在编写将要侦听目录的代码。当使用.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();
    }
}

12 个答案:

答案 0 :(得分:32)

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

答案 1 :(得分:18)

通过以下两个步骤可以解决此问题。

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

答案 2 :(得分:6)

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

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

答案 3 :(得分:5)

我正在将Java 8项目转换为Java10。与此同时,我一直在更新所有依赖项。我遇到了类似的例外,上述解决方案都无法为我服务。

我的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>

解决了这个问题,我能够再次发送带有附件的邮件。

答案 4 :(得分:1)

如果这是一个android项目,那么proguard很可能会错误地删除未使用的类,请在proguard文件中添加以下几行来解决问题,而无需直接修改代码:

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

答案 5 :(得分:1)

在OSGI下,以下变通办法允许javax.activation捆绑包从javax.mail捆绑包中加载“ META-INF / mailcap”资源:

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

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

答案 6 :(得分:0)

告诉我有关运行代码的环境的更多信息。您使用的JDK是什么?你在应用服务器上运行吗?

JavaBeans Activation Framework(JAF)查找配置文件,该文件告诉如何将MIME类型映射到处理它们的Java类(DataContentHandlers)。它使用ClassLoader查找配置文件。如果ClassLoader出现问题,则可能找不到配置文件。

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

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

答案 7 :(得分:0)

如果您的build.xml执行此操作: zipfileset src =“javamail-1.4.7 / mail.jar” excludes =“META-INF / ”**

然后你要删除配置信息。

答案 8 :(得分:0)

Som的答案(MailcapCommandMap)与Liferay 7.1 ga1中的Spring war Portlet一起为我工作。但是,我不得不从mail.jar中删除Tomcat的tomcat/lib/ext并替换为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 :(得分:0)

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覆盖了核心。

答案 10 :(得分:0)

即使我也遇到过同样的问题。我尝试了不同版本的javamail,但没有用。问题是Transport.send()正在使用默认Java jdk(在我的情况下为JAVA 8)中的MailCapCommandMap类,该类加载了过时的mailcap文件。

因此,我使用了最新版本的JAVA,之后它使用了来自 activation 软件包的MailCapCommandMap,该软件包加载了正确的mailcap文件。

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

答案 11 :(得分:0)

在 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 加载、处理、回退等相关的问题。