Eyal Lupu Java Blog

20080131 Thursday January 31, 2008

JavaMail - Sending Embedded Image in an HTML Mail Message

Hi,
This time JavaMail.  And to be more concrete - how to send an HTML mail message including its resources embedded within the mail message. You can find resources about it over the net, but since somebody had asked me about it, and I wrote a sample class it is a good opportunity to mention it here too.

The Question


How can I, using JavaMail, send a self contained HTML mail message - for example, if the HTML has a reference to an image the image is embedded within the message, there is no need to access any web server to download the image? So <img src="http://my.server.com/images/logo.gif"> is not a good answer.

The Solution - Content-ID based URIS


OK, "Content-ID based URIS" is not an official name, just something I made up a minute ago - however, this is the answer. The idea is to embed resources required by the HTML document as MIME parts of the message and reference those parts using the cid URLs. Each part will have a unique content id (the "Content-ID" header) and the HTML will reference the different parts using the "cid:<the id>" (without the "<", and ">" symbols) URI. Follow the example below which also illustrates a full JavaMail session.

Step I - Create the session


To send a message using JavaMail we have to start with a Session (javax.mail.Session). To configure the session we use a java.util.Properties object. Below is the configuration to send an email using gmail as the SMTP server. I also set the property "mail.debug" to "true" - so JavaMail will print debug information to the console.


        Properties props = new Properties();
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.port", "465");
        props.put("mail.smtp.socketFactory.port", "465");
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.put("mail.smtp.socketFactory.fallback", "false");
        
        props.put("mail.debug", "true");

        Session session = Session.getInstance(props);

 

 

 

Step II - Create the Message and the MultiPart

The MIME MultiPart subtype has to be "related" (defined in rfc2387). multipart/related means that the message parts should be aggregated to build the whole document and that message parts can reference each other. Usually (but this is not a must) the reference is done using the "Content-ID" header (if you read the RFC carefully you will find out that the reference can be done using any "Content-" header).

Also in the segment below:

·         The creation of a MimeMessage, and

·         Setting of recipient, sender, and subject.


        Message msg = new MimeMessage(session);
        msg.setSubject("Testing embedded HTML message");

        InternetAddress from = new InternetAddress("someone-AT-somewhere-DOT-com", "Mr. Someone, Somewhere");
        InternetAddress to = new InternetAddress("someone.else-AT-somewhere-DOT-com", "Miss. Someone, Somewhere");
        msg.addRecipient(Message.RecipientType.TO, to);
        msg.setFrom(from);
       
        Multipart multipart = new MimeMultipart("related");

 

Step III - The HTML

Now we can start adding the parts to the message, the first one (it doesn't have to be the first one, but this is an easy default) includes the HTML document. My document is very simple, a header, few words in the body and an image which appears twice. The SRC attribute of the two <IMG...> elements worth some attention. The URI of these elements is in the "cid:<id>" format mentioned earlier. Using this URI the mail client looks for the resources in the other MIME parts of the message.


        BodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent("<html><body><h2>A title</h2>Some text in here<br/>" +
                "<img src=\"cid:the-img-1\"/><br/> some more text<img src=\"cid:the-img-1\"/><body></html>", "text/html");

        multipart.addBodyPart(htmlPart);

 

Step IV - The Images

To add the image to the mail message we have to complete two tasks:

Encode the image (base64) Add the encoded image as a MIME part with the appropriate Content-ID header value

Luckily for us JavaMail integrates with the Java Activation Framework (JAF) so the encoding of the image can be done using a DataSource and a DataHandler. In the sample below I use a FileDataSource to load the image from the disk and just set the data source to a MIME part using the DataHandler. In addition I set the Content-ID header for the MIME part, notice that the value of the header is identical to the value in the <IMG> tag of the HTML above.


        BodyPart imgPart=new MimeBodyPart();
 
        // Loading the image
        DataSource ds=new FileDataSource("c:/tmp/img.gif");
        imgPart.setDataHandler(new DataHandler(ds));

        //Setting the header
        imgPart.setHeader("Content-ID","the-img-1");

        multipart.addBodyPart(imgPart);
       
        // attaching the multi-part to the message
        msg.setContent(multipart);

 

 

 

Step V - Send it

I send the message using the Transport (javax.mail.Transport) class. We can use the Transport.send(message) static method, but since I didn't authenticated with the SMTP server yet I use an instance of the Transport class and authenticate using the connect method.


        Transport transport = session.getTransport("smtp");
        transport.connect("<user>", "<password>");
        transport.sendMessage(msg, msg.getAllRecipients());
        transport.close();


That's it, the message is sent with the images within it.


[image] [image] [image]
Posted by EyalLupu ( Jan 31 2008, 09:54:30 PM GMT+02:00 ) Permalink Comments [0]

Comments:

Post a Comment:

Name:
E-Mail:
URL:

Your Comment:

HTML Syntax: NOT allowed

Valid HTML! Valid CSS!

This is a personal weblog, I do not speak for my employer.


You are viewing a mobilized version of this site...
View original page here

Mobilized by Mowser Mowser