Search code examples
javamimejakarta-mailmime-types

How to set MimeBodyPart ContentType to "text/html"?


The program below shows an unexpected return value for HTML multipart MIME type. Why does this program print text/plain and not text/html?

public class Main {
  public static void main(String[] args) throws javax.mail.MessagingException, java.io.IOException {
    javax.mail.internet.MimeBodyPart mime_body_part = new javax.mail.internet.MimeBodyPart();
    mime_body_part.setContent("<h1>foo</h1>", "text/html");
    System.out.println(mime_body_part.getContentType());
  }
}

I have tried numerous alternative ways including setting a ByteArrayDataSource wrapped in a DataHandler, but to no avail. The same thing happens when I try this with a MimeMessage instead of a MimeBodyPart.

To compile and run on Linux:

javac -classpath .:activation.jar:mail.jar Main.java
java -classpath .:activation.jar:mail.jar Main

Solution

  • Call MimeMessage.saveChanges() on the enclosing message, which will update the headers by cascading down the MIME structure into a call to MimeBodyPart.updateHeaders() on your body part. It's this updateHeaders call that transfers the content type from the DataHandler to the part's MIME Content-Type header.

    When you set the content of a MimeBodyPart, JavaMail internally (and not obviously) creates a DataHandler object wrapping the object you passed in. The part's Content-Type header is not updated immediately.

    There's no straightforward way to do it in your test program, since you don't have a containing MimeMessage and MimeBodyPart.updateHeaders() isn't public.


    Here's a working example that illuminates expected and unexpected outputs:

    public class MailTest {
    
      public static void main( String[] args ) throws Exception {
        Session mailSession = Session.getInstance( new Properties() );
        Transport transport = mailSession.getTransport();
    
        String text = "Hello, World";
        String html = "<h1>" + text + "</h1>";
    
        MimeMessage message = new MimeMessage( mailSession );
        Multipart multipart = new MimeMultipart( "alternative" );
    
        MimeBodyPart textPart = new MimeBodyPart();
        textPart.setText( text, "utf-8" );
    
        MimeBodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent( html, "text/html; charset=utf-8" );
    
        multipart.addBodyPart( textPart );
        multipart.addBodyPart( htmlPart );
        message.setContent( multipart );
    
        // Unexpected output.
        System.out.println( "HTML = text/html : " + htmlPart.isMimeType( "text/html" ) );
        System.out.println( "HTML Content Type: " + htmlPart.getContentType() );
    
        // Required magic (violates principle of least astonishment).
        message.saveChanges();
    
        // Output now correct.    
        System.out.println( "TEXT = text/plain: " + textPart.isMimeType( "text/plain" ) );
        System.out.println( "HTML = text/html : " + htmlPart.isMimeType( "text/html" ) );
        System.out.println( "HTML Content Type: " + htmlPart.getContentType() );
        System.out.println( "HTML Data Handler: " + htmlPart.getDataHandler().getContentType() );
      }
    }