Sending emails with JavaMail

JavaMail API is the reference implementation of JSR-000919 which is now open source and released under :

  • Common Development and Distribution License (CDDL) v1.1
  • GNU General Public License (GPL) v2 with Classpath Exception. Its provides full support

This API allows to handle incoming emails with IMAP or POP3 as well as sending emails through SMTP protocol. In this post we will focus on sending email using JavaMail. For this we will design a very small Java project that connects to a smtp server to send a simple text message.

Setting up the environment

We will use Maven to import & build our project. We use the simplest Maven archetype and define a single class MsgSender.
Then the project will look like this
javamail

You’ll need as well a smtp server with a valid account that you can reach from your host.

Our pom is very simple we only have the requested dependencies : com.sun.mail.mailapi and com.sun.mail.smtp.
mailapi is the generic JavaMail api and smtp artifact gives us the provider to reach the smtp server.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.jh.mail</groupId>
	<artifactId>mailsUtil</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<dependency>
			<groupId>com.sun.mail</groupId>
			<artifactId>mailapi</artifactId>
			<version>1.5.2</version>
		</dependency>
		<dependency>
			<groupId>com.sun.mail</groupId>
			<artifactId>smtp</artifactId>
			<version>1.5.2</version>
		</dependency>
	</dependencies>
</project>

Sending the email through smtp with JavaMail

We then set attributes for our MsgSender and the constructor

public class MsgSender {

	private String server = "mail.jh-test.com";
	private String user;
	private String password;

	/** default constructor
	 * @param user the email user
	 * @param password the email password
	 */
	public MsgSender(String user,String password) {
		this.user=user;
		this.password=password;
	}
}

Then we add the method that will send our text email. We provide it with several parameters.

/** Build and send text message
	 * @param textBody the text to be sent
	 * @param subject subject of the email
	 * @param sender the email address of the sender
	 * @param recipients the list of recipients
	 * @throws AddressException
	 * @throws MessagingException
	 */
	public void sendTextMessage(String textBody, String subject, String sender,
			String[] recipients) throws AddressException, MessagingException {

		// create properties so that we can retrieve a session on server
		Properties props = new Properties();

		Properties properties = new Properties();
		properties.setProperty("mail.transport.protocol", "smtp");
		properties.setProperty("mail.smtp.host", server);
		properties.setProperty("mail.smtp.user", user);
		properties.setProperty("mail.smtp.password", password);
		properties.setProperty("mail.from", sender);

		// Get the Session object
		Session session = Session.getInstance(props);

		// Construct the message and send it.
		Message msg = new MimeMessage(session);

		if (sender != null) {
			msg.setFrom(new InternetAddress(sender));
		} else {
			msg.setFrom();
		}

		// build the recipients list of the email
		if (recipients.length > 0) {
			for (int i = 0; i < recipients.length; i++) {
				msg.addRecipient(RecipientType.TO,
						(Address) new InternetAddress(recipients[i]));
				// we only use TO recipients but CC and BCC may be use in
				// addition
			}
		}

		// add the email subject from input
		msg.setSubject(subject);

		// add the text content
		msg.setText(textBody);
		
		 msg.setSentDate(new Date());
		
		Transport transport = session.getTransport("smtp");
		transport.connect(server,user, password);
		Address addresses[] = new InternetAddress[recipients.length];
		if (recipients.length > 0) {
			for (int i = 0; i < recipients.length; i++) {
				addresses[i] = new InternetAddress(recipients[i]);
			}
		}
		transport.sendMessage(msg, addresses);
		
		this.copyIntoSent(session, msg);
	}

Testing the method

To test it and to avoid creating a main class I prefer to implement a JUnit test method to test our MsgSender.
Here is what it looks like.

package com.jh.mail;

import javax.mail.MessagingException;
import javax.mail.internet.AddressException;

import org.junit.Test;

public class MsgSenderTest {

	@Test
	public void testSendTextMessage() {
		MsgSender sender = new MsgSender("test@jh-test.com", "testos");

		try {
			sender.sendTextMessage("test", "subject",
					"test@jh-test.com",
					new String[]{"foo-account@jh-test.com","foo-account2@jh-test.com"});
		} catch (AddressException e) {
                        // handle error
		} catch (MessagingException e) {
                        // handle error
		}
	}

}

Of course the pom.xml must include the appropraite JUnit dependency

                 <dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>

In this example the user test@jh-test.com with password testos, is trying to send an email to foo-account@jh-test.com and to foo-account2@jh-test.com with subject = subject and content= text.

Copying email into sent folder

A nearly mandatory feature is for our sender to get a copy on the sent email in his send folder, which is what all email clients allow to do.
To achieve this it is pretty straightforward.

Just create the following method in MsgSender class

/**
	 * Copies message to "Sent Items" folder as read
	 * @param session the current session
	 * @param msg the sent message
	 * @throws MessagingException
	 */
	private void copyIntoSent(Session session,Message msg) throws MessagingException{
		
        Store store = session.getStore("imap");
        store.connect(server, user, password);

        Folder folder = (Folder) store.getFolder("Inbox.Sent.Notifications");
        if (!folder.exists()) {
            folder.create(Folder.HOLDS_MESSAGES);
        }
        folder.open(Folder.READ_WRITE);

        folder.appendMessages(new Message[]{msg});
	}

In the above example we put the email in Sent/Notifications folder of the sender.
What is difficult to find out is the exact name of the “Sent” folder because there is no standard for that and you’re likely to get this error.

javax.mail.FolderNotFoundException: Sent not found
	at com.sun.mail.imap.IMAPFolder.checkExists(IMAPFolder.java:429)
	at com.sun.mail.imap.IMAPFolder.open(IMAPFolder.java:1017)
	at com.sun.mail.imap.IMAPFolder.open(IMAPFolder.java:950)
	at com.jh.mail.MsgSender.copyIntoSent(MsgSender.java:113)
	at com.jh.mail.MsgSender.sendTextMessage(MsgSender.java:95)

The appropriate provider for imap must be added in classpath which is achieved by adding the few line below in pom.xml

                 <dependency>
			<groupId>com.sun.mail</groupId>
			<artifactId>imap</artifactId>
			<version>1.5.2</version>
		</dependency>

Otherwise you’ll get the following error.

javax.mail.NoSuchProviderException: No provider for imap
	at javax.mail.Session.getProvider(Session.java:479)
	at javax.mail.Session.getStore(Session.java:553)
	at javax.mail.Session.getStore(Session.java:533)

About Matthieu

Hello, I joined Java-Hoster in 2009. After my engineering studies in France, I worked for several companies including some well known Natixis , Airbus and Air France . Now I am more focused and involved on Java open-source projects and of course in Java-Hoster which makes me learn a lot and feed me as well :-D I am also responsible for this blog, so if you have something to say about it feel free to contact me. Cheers.
This entry was posted in Java course and tagged , . Bookmark the permalink.

One Response to Sending emails with JavaMail

  1. Dennis says:

    Hello sir, thank you for your post.
    It really helped alot! :)
    Thanks!

Leave a Reply to Dennis Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>