In the tutorial Send e-mail with attachment in Java, we discussed how to attach files to an e-mail message using JavaMail. In this article, we will use a similar technique plus some modification in order to embed some images directly into the message. The embedded images are called inline attachments which users see the images right inside the e-mail’s content. That’s different with regular attachments which the users have to download and open them manually.

The message must in HTML format in order to have inline images, so we should set content type of the message as follows:

MimeBodyPart bodyPart = new MimeBodyPart();
bodyPart.setContent(htmlMessage, "text/html");

 

Where htmlMessage is a String represents content of the message with HTML tags:

String htmlMessage = "<html>Hi there,<br>";
htmlMessage += "See this cool pic: <img src=\"cid:AbcXyz123\" />";
htmlMessage += "</html>";

 

As you notice in the HTML code above, we use the <img> tag to include an image, but its src attribute does not point to name of the image. Instead, the src attribute must refer to Content-ID header’s value of a MIME part which contains the actual image, in the following form:

src=”cid:<content_id>

Then the image part should be created as follows:

MimeBodyPart imagePart = new MimeBodyPart();
imagePart.setHeader("Content-ID", "AbcXyz123");
imagePart.setDisposition(MimeBodyPart.INLINE);
// attach the image file
imagePart.attachFile(imageFilePath);

 

Value of the Content-ID header must be a unique identifier. This convention is described in the RFC 2387.

Now let’s create a real example with a utility class and a test program.

 

Coding utility class

We create an out-of-the-box utility class as follows:

package net.codejava.mail;

import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

/**
 * This utility class provides a functionality to send an HTML e-mail message
 * with embedded images.
 * @author www.codejava.net
 *
 */
public class EmbeddedImageEmailUtil {

	/**
	 * Sends an HTML e-mail with inline images.
	 * @param host SMTP host
	 * @param port SMTP port
	 * @param userName e-mail address of the sender's account 
	 * @param password password of the sender's account
	 * @param toAddress e-mail address of the recipient
	 * @param subject e-mail subject
	 * @param htmlBody e-mail content with HTML tags
	 * @param mapInlineImages 
	 * 			key: Content-ID
	 * 			value: path of the image file
	 * @throws AddressException
	 * @throws MessagingException
	 */
	public static void send(String host, String port,
			final String userName, final String password, String toAddress,
			String subject, String htmlBody, 
			Map<String, String> mapInlineImages)
				throws AddressException, MessagingException {
		// sets SMTP server properties
		Properties properties = new Properties();
		properties.put("mail.smtp.host", host);
		properties.put("mail.smtp.port", port);
		properties.put("mail.smtp.auth", "true");
		properties.put("mail.smtp.starttls.enable", "true");
		properties.put("mail.user", userName);
		properties.put("mail.password", password);

		// creates a new session with an authenticator
		Authenticator auth = new Authenticator() {
			public PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication(userName, password);
			}
		};
		Session session = Session.getInstance(properties, auth);

		// creates a new e-mail message
		Message msg = new MimeMessage(session);

		msg.setFrom(new InternetAddress(userName));
		InternetAddress[] toAddresses = { new InternetAddress(toAddress) };
		msg.setRecipients(Message.RecipientType.TO, toAddresses);
		msg.setSubject(subject);
		msg.setSentDate(new Date());

		// creates message part
		MimeBodyPart messageBodyPart = new MimeBodyPart();
		messageBodyPart.setContent(htmlBody, "text/html");

		// creates multi-part
		Multipart multipart = new MimeMultipart();
		multipart.addBodyPart(messageBodyPart);

		// adds inline image attachments
		if (mapInlineImages != null && mapInlineImages.size() > 0) {
			Set<String> setImageID = mapInlineImages.keySet();
			
			for (String contentId : setImageID) {
				MimeBodyPart imagePart = new MimeBodyPart();
				imagePart.setHeader("Content-ID", "<" + contentId + ">");
				imagePart.setDisposition(MimeBodyPart.INLINE);
				
				String imageFilePath = mapInlineImages.get(contentId);
				try {
					imagePart.attachFile(imageFilePath);
				} catch (IOException ex) {
					ex.printStackTrace();
				}

				multipart.addBodyPart(imagePart);
			}
		}

		msg.setContent(multipart);

		Transport.send(msg);
	}
}

 

Clients can call the static method send() to send an e-mail message in HTML format with embedded images passed via the parameter mapInlineImages. So it’s convenient for embedding an image as follows:

Map<String, String> inlineImages = new HashMap<String, String>();
inlineImages.put("ID123456", "D:/Images/stockchart.jpg");

 

Note this line:

imagePart.setHeader("Content-ID", "<" + contentId + ">");

 

The reason that we have to wrap the contentId between the “<” and “>” is because some e-mail clients (such as Gmail) won’t show the inline images without those angle brackets.

 

 

Coding test program

Code the test program as follows:

package net.codejava.mail;

import java.util.HashMap;
import java.util.Map;

/**
 * This program tests out the EmbeddedImageEmailUtil utility class.
 * @author www.codejava.net
 *
 */
public class InlineImageEmailTester {

	/**
	 * main entry of the program
	 */
	public static void main(String[] args) {
		// SMTP info
		String host = "smtp.gmail.com";
		String port = "587";
		String mailFrom = "YOUR_EMAIL";
		String password = "YOUR_PASSWORD";

		// message info
		String mailTo = "YOUR_RECIPIENT";
		String subject = "Test e-mail with inline images";
		StringBuffer body
			= new StringBuffer("<html>This message contains two inline images.<br>");
		body.append("The first image is a chart:<br>");
		body.append("<img src=\"cid:image1\" width=\"30%\" height=\"30%\" /><br>");
		body.append("The second one is a cube:<br>");
		body.append("<img src=\"cid:image2\" width=\"15%\" height=\"15%\" /><br>");
		body.append("End of message.");
		body.append("</html>");

		// inline images
		Map<String, String> inlineImages = new HashMap<String, String>();
		inlineImages.put("image1", "E:/Test/chart.png");
		inlineImages.put("image2", "E:/Test/cube.jpg");

		try {
			EmbeddedImageEmailUtil.send(host, port, mailFrom, password, mailTo,
				subject, body.toString(), inlineImages);
			System.out.println("Email sent.");
		} catch (Exception ex) {
			System.out.println("Could not send email.");
			ex.printStackTrace();
		}
	}
}

 

In this test program, we configure SMTP settings for a GMail account and compose an HTML message with two inline images image1 and image2 which correspond to two actual images file chart.png and cube.jpg.

When running this program, we got the following result in GMail:

email embedded images in GMail

And in Microsoft Outlook:

email embedded images in Outlook

 

Recommended Book: JavaMail API

Attachments:
Download this file (EmbeddedImageEmailUtil.java)EmbeddedImageEmailUtil.java[Utility class]3 kB
Download this file (InlineImageEmailTester.java)InlineImageEmailTester.java[Test program]1 kB