javax.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed; boundary
Asked Answered
O

14

33

Currently I'm inline of writing a code that will be listening to a directory. when the directory is updated with .apk file, I'll send a mail with this .apk file to a gmail account. I'm using Jnotify and JAVA Mail in my program.

The Error I'm getting is,

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"

I looked for the solutions given in the stackoverflow for help but none of them where helpful.

Thanks in Advance

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("[email protected]", "senderPassword");
            }
        }
    );

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

    try{
        Message message = new MimeMessage(session); 
        message.setFrom(new InternetAddress("[email protected]"));
        message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("[email protected]"));
        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();
    }
}
Oh answered 18/2, 2014 at 14:5 Comment(0)
O
31

This issue can get a solution by taking up the below two steps.

  1. Make sure java mail is 1.4.7.(Previously I used 1.4.5 which led to all confusions). Download it from http://www.oracle.com/technetwork/java/index-138643.html
  2. Add this piece of code before sending the message:
    Thread.currentThread().setContextClassLoader( getClass().getClassLoader() );
Oh answered 20/2, 2014 at 5:30 Comment(6)
yes, you need to make sure that the classes find the resource files (mailcap etc.). In my case I had to rename META-INF directory and therefore they were not found any more. Moved the mailcap etc. stuff up one level and it works again.Shortie
I can confirm - Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); - is indeed required to make it working again.Roscoeroscommon
worked for me in kotlin script Thread.currentThread().contextClassLoader = javaClass.classLoaderImmortality
Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); worked for me too, thanks!Michale
This shouldn't be needed... I was using javax.mail with apache commons and it all worked well. It started to fail after i updated apache commons-email from 1.4 to 1.5, and/or javax.mail from 1.5.2 to 1.5.6!Mccleary
We use OSGO and we used this hack too and set the classloader of a specific javax.mail class like Session, to make sure it is the classloader which knows where those MailCap files live. e.g. : Thread.currentThread().setContextClassLoader( javax.mail.Session.class.getClassLoader() );Exurbia
O
43

JavaMail depends on some configuration files to map MIME types to Java classes (e.g., multipart/mixed to javax.mail.internet.MimeMultipart). These configuration files are loaded using the ClassLoader for the application. If the ClassLoader doesn't function properly, these configuration files won't be found.

You can simply add below lines .. that solves the issue .

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"); 
Odine answered 3/9, 2014 at 17:10 Comment(3)
What do you mean with "If the ClassLoader doesn't function properly, these configuration files won't be found". Is this a bug in Java? Should these always be added? Or should it have been loaded automatically?Hadlock
Additional info for ics / text/calendar files: have a look here: https://mcmap.net/q/452423/-javax-activation-unsupporteddatatypeexception-no-object-dch-for-mime-type-text-calendar-method-requestBenzoin
Oddly, when running my application in unit testing using Maven it correctly retrieves all mailcap entries from all jars and loads the defaults as the sum from all jars. When kicking off from the command line invoking java directly with a classpath etc it only retriecves one of the jars mailcap entries.Tees
O
31

This issue can get a solution by taking up the below two steps.

  1. Make sure java mail is 1.4.7.(Previously I used 1.4.5 which led to all confusions). Download it from http://www.oracle.com/technetwork/java/index-138643.html
  2. Add this piece of code before sending the message:
    Thread.currentThread().setContextClassLoader( getClass().getClassLoader() );
Oh answered 20/2, 2014 at 5:30 Comment(6)
yes, you need to make sure that the classes find the resource files (mailcap etc.). In my case I had to rename META-INF directory and therefore they were not found any more. Moved the mailcap etc. stuff up one level and it works again.Shortie
I can confirm - Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); - is indeed required to make it working again.Roscoeroscommon
worked for me in kotlin script Thread.currentThread().contextClassLoader = javaClass.classLoaderImmortality
Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); worked for me too, thanks!Michale
This shouldn't be needed... I was using javax.mail with apache commons and it all worked well. It started to fail after i updated apache commons-email from 1.4 to 1.5, and/or javax.mail from 1.5.2 to 1.5.6!Mccleary
We use OSGO and we used this hack too and set the classloader of a specific javax.mail class like Session, to make sure it is the classloader which knows where those MailCap files live. e.g. : Thread.currentThread().setContextClassLoader( javax.mail.Session.class.getClassLoader() );Exurbia
R
10

I am busy converting a Java 8 project to Java 10. At the same time I have been updating all of the dependencies. I was getting a similar exception and none of the above solutions worked for me.

I have the following in my pom.xml:

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

I did a bit more research and found the following link:

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

So I tried adding the following dependency to my pom.xml:

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

That fixed the problem, I was able to send mail with attachments again.

Rubirubia answered 27/6, 2018 at 4:46 Comment(2)
Thank you. This is exactly what I was looking for. Had the same problem migrating to Java 10.Willingham
are you using jboss server?Retiarius
E
4

The answer from Som worked for me. However I had to modify the mappings as I was using JavaMail DSN, and needed those mailcap entries also (included below, including Som's answer):

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

As it turns out, it was adding the DSN JAR into my fat JAR (using shadowJar/Gradle) that caused the problem: the META-INF/mailcap from the DSN jar was overwriting the core one.

Eldwun answered 2/1, 2019 at 19:29 Comment(0)
G
1

Tell me more about the environment in which your code is running. What JDK are you using? Are you running in an application server?

The JavaBeans Activation Framework (JAF) looks for configuration files that tell how to map MIME types to the Java classes (DataContentHandlers) that handle them. It uses the ClassLoader to find the configuration files. If there are problems with the ClassLoader, the configuration files might not be found.

You might want to try the workaround described here, but of course it would be better to determine the root cause of the problem for you.

Finally, you might want to simplify your program by fixing some of these common JavaMail mistakes.

Grandpapa answered 18/2, 2014 at 22:1 Comment(7)
Thanks for your response 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, sharing) I'm not running the code on application server. I tried the workaround in my code before transporting the message but it didn't help me i got he same error One more information i like to add here, When i run the code in the function, "SendEmail" separately its running successfully and able to send a mail with attachment. The problem happens only when i club it with the JNotifyListener function.Oh
How are you running your application? Is your application in a jar file? Are you also using the javax.mail.jar file unchanged? Or did you put the JavaMail classes in your application jar file?Grandpapa
Also, note that JDK 7 has the ability to watch files for changes so you might not need JNotify.Grandpapa
How? What was the problem?Grandpapa
The main Problem was that i was using Java Mail 1.4.5. When i tried using Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); I was getting the mail sent but without attachment. When i changed the version of Java Mail to 1.4.7.it solved the issueOh
Did you try JavaMail 1.5.1, the current version?Grandpapa
No i didn't try that. Let me do that and post you the update.Oh
E
1

If it's a android project, it's highly possible the proguard stripped out unused classes by mistake, please add the following lines in the proguard file to fix the problem without modifying the code directly:

-keep class com.sun.mail.handlers.**
-dontwarn com.sun.mail.handlers.handler_base
Earnest answered 20/7, 2018 at 2:9 Comment(0)
A
1

Som's answer (MailcapCommandMap) worked for me with Spring war Portlets in Liferay 7.1 ga1. However, I had to remove Tomcat's mail.jar from tomcat/lib/ext and replace it with javax.mail-1.6.2.jar, then make sure the dependency is scoped as provided in the project's pom.xml:

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
    <scope>provided</scope>
</dependency>
Abiotic answered 25/9, 2018 at 14:28 Comment(0)
T
1

Under OSGI, the following workaround allows the javax.activation bundle to load the "META-INF/mailcap" resource from the javax.mail bundle :

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

Note : character sets conversions may have limitations with this workaround...

Tisatisane answered 22/8, 2019 at 15:41 Comment(1)
I'm under OSGI, and it all worked well. It started to fail after i updated apache commons-email from 1.4 to 1.5, and/or javax.mail from 1.5.2 to 1.5.6!Mccleary
F
1

A similar problem appeared when running a Java 8 S/MIME parsing code on Java 12. Relevant (missing) DCH was for a custom MIME type message/disposition-notification.

Unlike in old Java's native javax.activation.ObjectDataContentHandler, the external javax.activation:activation library for Java 9+, does not seem to tolerate "unknown" MIME types; earlier, multipart "parts" with such custom content-types (not found in mailcap meta-files) were still consumed if they contained byte[] or String content - but not anymore.

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

Solution was to define an entry for message/disposition-notification (it can be safely interpreted as text) in a mailcap file; technically similar to @Som's answer, but we all love no-code solutions, right?

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

and bundle it into the JAR (classpath); e.g. with Maven:

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

Also noteworthy: setting a -Djavax.activation.debug=true system property on the JVM, greatly helps in tracing issues related to such mailcap loading, handling, fallbacks etc.

Fleda answered 27/5, 2021 at 8:31 Comment(0)
U
1

If anyone encountered the problem after including Apache Tika 2, it could be due to a mail dependency embedded in Tika.

We manage to fix the issue by adding a Maven exclusion, leaving only javax.mail on classpath. Something like:

<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>
Ume answered 10/2, 2022 at 14:20 Comment(0)
A
0

If your build.xml does this: zipfileset src="javamail-1.4.7/mail.jar" excludes="META-INF/"**

Then you're stripping out the configuration information.

Apollyon answered 27/1, 2017 at 0:27 Comment(0)
U
0

Even I had faced same issue. I tried different versions of javamail it didnt work. The problem was Transport.send() was using MailCapCommandMap class from the default java jdk (JAVA 8 in my case) that loaded outdated mailcap files.

So I used the latest version of JAVA after which it used MailCapCommandMap from the activation package which loaded the correct mailcap file.

If any anyone faces same problem in future just add a breakpoint in MailCapCommandMap classes available so that u know which mailcap file it is using.

Unmeriting answered 20/8, 2020 at 6:27 Comment(0)
T
0

I was starting my Java app using file globbing for the classpath in the startup script. eg.

java -cp ${LIBDIR}/*.jar org.MyApp

Changing it to do this solved the problem without any code change:

CLASSPATH=$(echo "${LIBDIR}/"*".jar" | tr ' ' ':')
java -cp ${CLASSPATH} org.MyApp
Tees answered 23/3, 2022 at 10:13 Comment(0)
D
0

Old post, but for Apache Tika it still applies for the latest version (2.9.2). You will have to exclude bcmail-jdk18on:

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

I could reproduce the error as soon as this jar file is on the classpath (and the other way round).

Dineen answered 21/6, 2024 at 6:22 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.