maahd
maahd

Reputation: 712

javax.activation.UnsupportedDataTypeException: no object DCH for MIME type image/png on trying to send email

I updated my project from Java 8 to 14. I also updated a bunch of dependencies in my project pom.xml. Now I have a problem whenever I try to send an email via the application. I tried many different solutions that I found online but none of them seems to work for me. Here is the error log:

javax.mail.MessagingException: IOException while sending message;
  nested exception is:
    javax.activation.UnsupportedDataTypeException: no object DCH for MIME type image/png
    at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1365)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:88)
    at 
    java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: javax.activation.UnsupportedDataTypeException: no object DCH for MIME type image/png
    at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:885)
    at javax.activation.DataHandler.writeTo(DataHandler.java:316)
    at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1687)
    at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:991)
    at javax.mail.internet.MimeMultipart.writeTo(MimeMultipart.java:561)
    at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:84)
    at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:883)
    at javax.activation.DataHandler.writeTo(DataHandler.java:316)
    at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1687)
    at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1906)
    at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1315)
    ... 16 more
2020-09-02 17:00:03 INFO  EmailDirectSignOneTimeLogin:79 - direct sign url: http://localhost:3000/direct_sign/czDSIg3Fms
FINISHED JOB

Any help would be appreciated. If you need more info, please comment on the question.

Upvotes: 2

Views: 3211

Answers (2)

Piro
Piro

Reputation: 1435

This happens, because newer versions of DataHandler does not handle as many cases as before, more can be read in this answer. This is why ByteArrayDataSource works as pointed out by D. J. Lynch. In my case I used FileDataSource and that fails with standard DataHandler so I had to use own implementation of DataHandler:

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;

public class FileDataHandler extends DataHandler{

    private final File file;
    
    public FileDataHandler(File file, String contentType) {
        super(new FileDataSource(file), contentType);
        this.file = file;
    }
    
    @Override
    public void writeTo(OutputStream os) throws IOException {
        try (InputStream is = new FileInputStream(file); BufferedInputStream bis = new BufferedInputStream(is)) {
            byte data[] = new byte[8 * 1024];
            int bytes_read;

            while ((bytes_read = bis.read(data)) > 0) {
                os.write(data, 0, bytes_read);
            }
        }
    }
}

Data source is irrelevant here, but if you are mixing various data sources it is easy to support them all, just create custom data handler when needed and use default otherwise:

DataSource dataSource = getDataSource();
DataHandler dataHandler;
if(dataSource instanceof FileDataSource) {
    dataHandler = new FileDataHandler(((FileDataSource) dataSource).getFile(), getMimeType());
}
else {
    dataHandler = new DataHandler(dataSource, mimeType);
}
bodyPart.setDataHandler(dataHandler);

Depending on your usage what you probably need is also just a custom version of DataHandler.writeTo method

Upvotes: 0

D. J. Lynch
D. J. Lynch

Reputation: 21

This could use more information about what you're trying to do, but I happened to find this question while working on the same issue and also found this question and got the code below that works in Java 11:

            part = new MimeBodyPart();
            ByteArrayDataSource source = new ByteArrayDataSource(logoBytes, "image/png");
            DataHandler handler = new DataHandler(source);
            part.setDataHandler(handler);
            part.setHeader("Content-ID", "<Logo>");
            multipart.addBodyPart(part);

Upvotes: 2

Related Questions