29

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

13 回答 13

41

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"); 
于 2014-09-03T17:10:07.060 回答
26

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

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

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

Thread.currentThread().setContextClassLoader( getClass().getClassLoader() );
于 2015-11-12T17:25:58.367 回答
7

我正忙于将 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>

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

于 2018-06-27T04:46:26.510 回答
2

索姆的回答对我有用。但是,当我使用 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 覆盖了核心。

于 2019-01-02T19:29:42.320 回答
1

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

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

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

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

于 2014-02-18T22:01:53.703 回答
1

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

-keep class com.sun.mail.handlers.**
-dontwarn com.sun.mail.handlers.handler_base
于 2018-07-20T02:09:35.527 回答
1

Som 的回答 ( MailcapCommandMap) 对我在 Liferay 7.1 ga1 中的 Spring war Portlets 有效。mail.jar但是,我必须从中删除 Tomcattomcat/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>
于 2018-09-25T14:28:36.460 回答
1

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

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

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

于 2019-08-22T15:41:25.127 回答
0

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

然后,您将剥离配置信息。

于 2017-01-27T00:27:35.810 回答
0

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

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

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

于 2020-08-20T06:27:18.033 回答
0

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

与旧 Java 的 native 不同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>

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

于 2021-05-27T08:31:36.713 回答
0

如果有人在包含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>
于 2022-02-10T14:20:09.473 回答