Integration Testing IMAP, SMTP and POP3 with GreenMail

July 31st, 2012 by

Having written some e-mail handling, sending or receiving library you’d like to run some integration tests against a real mail server?

Then GreenMail might help you out here .. the framework is not quite new on the market but it is really easy to setup IMAP,SMTP or POP3 services with it and it comes with some helpful libraries making your life a bit easier here.

That’s why I’ve come to the idea to share some examples for setting up different server instances, creating user accounts and – at last – fetching and validating e-mails…


 

Adding GreenMail to your Project

Essentially there is just one dependency needed to integrate GreenMail into your existing project .. just add this Maven snippet or the Gradle build file to your project’s pom.xml or project directory …

Maven

Just add the following dependencies to your pom.xml – for my full project descriptor please take a look at the tutorial sources at Bitbucket.

<dependencies>
    <dependency>
        <groupId>com.icegreen</groupId>
        <artifactId>greenmail</artifactId>
        <version>1.3</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.10</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>mail</artifactId>
        <version>1.4.5</version>
    </dependency>
</dependencies>

Gradle

For the fellow Maven haters here’s the gradlish variant as build.gradle

apply plugin: 'java'
apply plugin: 'maven'
 
group = 'com.hascode.tutorial'
version = '0.0.1'
 
repositories {
    mavenCentral()
}
 
configurations {
    provided
    testCompile.extendsFrom provided
    compile.transitive = true
}
 
dependencies {
    compile(
        [group: 'javax.mail', name : 'mail', version : '1.4.5'],
        [group: 'org.slf4j', name : 'slf4j-api', version : '1.6.6'],
        [group: 'ch.qos.logback', name : 'logback-core', version : '1.0.6']
    )
 
    testCompile(
        [group: 'com.icegreen', name : 'greenmail', version : '1.3'],
        [group: 'junit', name : 'junit', version : '4.10'],
        [group: 'org.hamcrest', name : 'hamcrest-all', version : '1.1']
    )
}
 
sourceSets.main.compileClasspath += configurations.provided

Using GreenMail

Now to some examples .. to keep it pure I am going to implement the component to be tested using the well-known but imho ugly javax.mail API and on the other side the GreenMail server with a specific setup.

As you might notice there are several possible default configurations available e.g. ServerSetup.IMAP creates an IMAP server, ServerSetup.SMTP creates and SMTP server .. if you need both, just add an array of ServerSetup as constructor parameter when you create a new GreenMail server instance .. e.g. new GreenMail(new ServerSetup[]{ServerSetup.IMAP, ServerSetup.SMTP}) . If you need everything from POP3 to SMTPS then just use ServerSetup.ALL and enjoy.

Per default, GreenMail uses the following ports:

  • smtp    25
  • smtps    465
  • pop3    110
  • pop3s    995
  • imap    143
  • imaps    993

It might happen that these ports are already used on your system or you’re working on an *nix like operating system that reserves the ports upto 1024 for system services and therefore only root is allowed to use them.

In this case you should – and I am doing this in the following examples – consider using GreenMail’s ServerSetupTest instead of ServerSetup .. it simply adds 3000 to the default ports so that the ports used are now:

  • smtp    3025
  • smtps    3465
  • pop3    3110
  • pop3s    3995
  • imap    3143
  • imaps    3993

If you somehow need to use another port simply pass a custom ServerSetup like in the following example where I’m creating a setup for SMTP on port 6666: new ServerSetup(6666, null, “smtp”)

POP3

In the following example we’re first creating a user account on the mail-server, we’re saving an e-mail on the server and finally an e-mail message is pulled from the GreenMail server using POP3.

package it;
 
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
 
import java.io.IOException;
import java.util.Properties;
 
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
 
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import com.icegreen.greenmail.user.GreenMailUser;
import com.icegreen.greenmail.user.UserException;
import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.ServerSetupTest;
 
public class Pop3IT {
    private static final String USER_PASSWORD = "abcdef123";
    private static final String USER_NAME = "hascode";
    private static final String EMAIL_USER_ADDRESS = "hascode@localhost";
    private static final String EMAIL_TO = "someone@localhost.com";
    private static final String EMAIL_SUBJECT = "Test E-Mail";
    private static final String EMAIL_TEXT = "This is a test e-mail.";
    private static final String LOCALHOST = "127.0.0.1";
    private GreenMail mailServer;
 
    @Before
    public void setUp() {
        mailServer = new GreenMail(ServerSetupTest.POP3);
        mailServer.start();
    }
 
    @After
    public void tearDown() {
        mailServer.stop();
    }
 
    @Test
    public void getMails() throws IOException, MessagingException,
    UserExceptionInterruptedException {
        // create user on mail server
        GreenMailUser user = mailServer.setUser(EMAIL_USER_ADDRESS, USER_NAME,
        USER_PASSWORD);
 
        // create an e-mail message using javax.mail ..
        MimeMessage message = new MimeMessage((Session) null);
        message.setFrom(new InternetAddress(EMAIL_TO));
        message.addRecipient(Message.RecipientType.TOnew InternetAddress(
        EMAIL_USER_ADDRESS));
        message.setSubject(EMAIL_SUBJECT);
        message.setText(EMAIL_TEXT);
 
        // use greenmail to store the message
        user.deliver(message);
 
        // fetch the e-mail from pop3 using javax.mail ..
        Properties props = new Properties();
        props.setProperty("mail.pop3.connectiontimeout""5000");
        Session session = Session.getInstance(props);
        URLName urlName = new URLName("pop3", LOCALHOST,
        ServerSetupTest.POP3.getPort()null, user.getLogin(),
        user.getPassword());
        Store store = session.getStore(urlName);
        store.connect();
 
        Folder folder = store.getFolder("INBOX");
        folder.open(Folder.READ_ONLY);
        Message[] messages = folder.getMessages();
        assertNotNull(messages);
        assertThat(1, equalTo(messages.length));
        assertEquals(EMAIL_SUBJECT, messages[0].getSubject());
        assertTrue(String.valueOf(messages[0].getContent())
        .contains(EMAIL_TEXT));
        assertEquals(EMAIL_TO, messages[0].getFrom()[0].toString());
    }
}

POP3S

We’re changing the server setup here and use a dummy ssl certificate provider bundled with GreenMail – and another URLName ..

@Before
public void setUp() {
  Security.setProperty("ssl.SocketFactory.provider",
      DummySSLSocketFactory.class.getName());
  mailServer = new GreenMail(ServerSetupTest.POP3S);
  mailServer.start();
}
 
[..]
URLName urlName = new URLName("pop3s", LOCALHOST,
    ServerSetupTest.POP3S.getPort(), null, user.getLogin(),
    user.getPassword());
[..]

SMTP

In the following test we’re setting up an SMTP server, we’re using javax.mail horror to send an e-mail and afterwards we’re validating it using some helpful functions from the GreenMail framework…

package it;
 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
 
import java.io.IOException;
import java.util.Date;
import java.util.Properties;
 
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
 
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import com.icegreen.greenmail.user.UserException;
import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.ServerSetupTest;
import com.sun.mail.smtp.SMTPTransport;
 
public class SmtpIT {
    private static final String USER_PASSWORD = "abcdef123";
    private static final String USER_NAME = "hascode";
    private static final String EMAIL_USER_ADDRESS = "hascode@localhost";
    private static final String EMAIL_TO = "someone@localhost.com";
    private static final String EMAIL_SUBJECT = "Test E-Mail";
    private static final String EMAIL_TEXT = "This is a test e-mail.";
    private static final String LOCALHOST = "127.0.0.1";
    private GreenMail mailServer;
 
    @Before
    public void setUp() {
        mailServer = new GreenMail(ServerSetupTest.SMTP);
        mailServer.start();
    }
 
    @After
    public void tearDown() {
        mailServer.stop();
    }
 
    @Test
    public void getMails() throws IOException, MessagingException,
    UserExceptionInterruptedException {
        // setup user on the mail server
        mailServer.setUser(EMAIL_USER_ADDRESS, USER_NAME, USER_PASSWORD);
 
        // create the javax.mail stack with session, message and transport ..
        Properties props = System.getProperties();
        props.put("mail.smtp.host", LOCALHOST);
        props.put("mail.smtp.auth""true");
        props.put("mail.smtp.port", ServerSetupTest.SMTP.getPort());
        Session session = Session.getInstance(props, null);
        Message msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress(EMAIL_TO));
        msg.setRecipients(Message.RecipientType.TO,
        InternetAddress.parse(EMAIL_USER_ADDRESS, false));
        msg.setSubject(EMAIL_SUBJECT);
        msg.setText(EMAIL_TEXT);
        msg.setSentDate(new Date());
        SMTPTransport t = (SMTPTransport) session.getTransport("smtp");
        t.connect(LOCALHOST, EMAIL_USER_ADDRESS, USER_PASSWORD);
        t.sendMessage(msg, msg.getAllRecipients());
 
        assertEquals("250 OK\n", t.getLastServerResponse());
        t.close();
 
        // fetch messages from server
        MimeMessage[] messages = mailServer.getReceivedMessages();
        assertNotNull(messages);
        assertEquals(1, messages.length);
        MimeMessage m = messages[0];
        assertEquals(EMAIL_SUBJECT, m.getSubject());
        assertTrue(String.valueOf(m.getContent()).contains(EMAIL_TEXT));
        assertEquals(EMAIL_TO, m.getFrom()[0].toString());
 
    }
}

SMTPS

For SMTPS we’re changing our setup a bit and we’re using the DummySSLSocketFactory shipped with GreenMail to avoid certificate errors here: Security.setProperty(“ssl.SocketFactory.provider”, DummySSLSocketFactory.class.getName());

package it;
 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
 
import java.io.IOException;
import java.security.Security;
import java.util.Date;
import java.util.Properties;
 
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
 
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import com.icegreen.greenmail.user.UserException;
import com.icegreen.greenmail.util.DummySSLSocketFactory;
import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.ServerSetupTest;
import com.sun.mail.smtp.SMTPTransport;
 
public class SmtpsIT {
    private static final String USER_PASSWORD = "abcdef123";
    private static final String USER_NAME = "hascode";
    private static final String EMAIL_USER_ADDRESS = "hascode@localhost";
    private static final String EMAIL_TO = "someone@localhost.com";
    private static final String EMAIL_SUBJECT = "Test E-Mail";
    private static final String EMAIL_TEXT = "This is a test e-mail.";
    private static final String LOCALHOST = "127.0.0.1";
    private GreenMail mailServer;
 
    @Before
    public void setUp() {
        Security.setProperty("ssl.SocketFactory.provider",
        DummySSLSocketFactory.class.getName());
        mailServer = new GreenMail(ServerSetupTest.SMTPS);
        mailServer.start();
    }
 
    @After
    public void tearDown() {
        mailServer.stop();
    }
 
    @Test
    public void getMails() throws IOException, MessagingException,
    UserExceptionInterruptedException {
        // setup user on the mail server
        mailServer.setUser(EMAIL_USER_ADDRESS, USER_NAME, USER_PASSWORD);
 
        // create the javax.mail stack with session, message and transport ..
        Properties props = System.getProperties();
        props.put("mail.smtps.host", LOCALHOST);
        props.put("mail.smtps.auth""true");
        props.put("mail.smtps.port", ServerSetupTest.SMTPS.getPort());
        Session session = Session.getInstance(props, null);
        Message msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress(EMAIL_TO));
        msg.setRecipients(Message.RecipientType.TO,
        InternetAddress.parse(EMAIL_USER_ADDRESS, false));
        msg.setSubject(EMAIL_SUBJECT);
        msg.setText(EMAIL_TEXT);
        msg.setSentDate(new Date());
        SMTPTransport t = (SMTPTransport) session.getTransport("smtps");
        t.connect(LOCALHOST, EMAIL_USER_ADDRESS, USER_PASSWORD);
        t.sendMessage(msg, msg.getAllRecipients());
 
        assertEquals("250 OK\n", t.getLastServerResponse());
        t.close();
 
        // fetch messages from server
        MimeMessage[] messages = mailServer.getReceivedMessages();
        assertNotNull(messages);
        assertEquals(1, messages.length);
        MimeMessage m = messages[0];
        assertEquals(EMAIL_SUBJECT, m.getSubject());
        assertTrue(String.valueOf(m.getContent()).contains(EMAIL_TEXT));
        assertEquals(EMAIL_TO, m.getFrom()[0].toString());
 
    }
}

IMAP

Again we’re creating a user account first, we’re creating an e-mail message and afterwards pull the message from the IMAP server using the javax.mail API..

package it;
 
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
 
import java.io.IOException;
import java.util.Properties;
 
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
 
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import com.icegreen.greenmail.user.GreenMailUser;
import com.icegreen.greenmail.user.UserException;
import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.ServerSetupTest;
 
public class ImapIT {
    private static final String USER_PASSWORD = "abcdef123";
    private static final String USER_NAME = "hascode";
    private static final String EMAIL_USER_ADDRESS = "hascode@localhost";
    private static final String EMAIL_TO = "someone@localhost.com";
    private static final String EMAIL_SUBJECT = "Test E-Mail";
    private static final String EMAIL_TEXT = "This is a test e-mail.";
    private static final String LOCALHOST = "127.0.0.1";
    private GreenMail mailServer;
 
    @Before
    public void setUp() {
        mailServer = new GreenMail(ServerSetupTest.IMAP);
        mailServer.start();
    }
 
    @After
    public void tearDown() {
        mailServer.stop();
    }
 
    @Test
    public void getMails() throws IOException, MessagingException,
    UserExceptionInterruptedException {
        // create user on mail server
        GreenMailUser user = mailServer.setUser(EMAIL_USER_ADDRESS, USER_NAME,
        USER_PASSWORD);
 
        // create an e-mail message using javax.mail ..
        MimeMessage message = new MimeMessage((Session) null);
        message.setFrom(new InternetAddress(EMAIL_TO));
        message.addRecipient(Message.RecipientType.TOnew InternetAddress(
        EMAIL_USER_ADDRESS));
        message.setSubject(EMAIL_SUBJECT);
        message.setText(EMAIL_TEXT);
 
        // use greenmail to store the message
        user.deliver(message);
 
        // fetch the e-mail via imap using javax.mail ..
        Properties props = new Properties();
        Session session = Session.getInstance(props);
        URLName urlName = new URLName("imap", LOCALHOST,
        ServerSetupTest.IMAP.getPort()null, user.getLogin(),
        user.getPassword());
        Store store = session.getStore(urlName);
        store.connect();
 
        Folder folder = store.getFolder("INBOX");
        folder.open(Folder.READ_ONLY);
        Message[] messages = folder.getMessages();
        assertNotNull(messages);
        assertThat(1, equalTo(messages.length));
        assertEquals(EMAIL_SUBJECT, messages[0].getSubject());
        assertTrue(String.valueOf(messages[0].getContent())
        .contains(EMAIL_TEXT));
        assertEquals(EMAIL_TO, messages[0].getFrom()[0].toString());
    }
}

IMAPS

Again we just need to change the server setup and the URLName

@Before
public void setUp() {
  Security.setProperty("ssl.SocketFactory.provider",
      DummySSLSocketFactory.class.getName());
  mailServer = new GreenMail(ServerSetupTest.IMAPS);
  mailServer.start();
}
 
[..]
URLName urlName = new URLName("imaps", LOCALHOST,
    ServerSetupTest.IMAPS.getPort(), null, user.getLogin(),
    user.getPassword());
[..]

GreenMail Utilities

There are a lot of helper methods and utilities encapsuled in the GreenMailUtil class .. whatever you need from generating a random string with a specific length to extracting headers from an email part or creating a MimeMessage body from a string you should take a look at this class and its static methods.

GreenMailUtil’s JavaDocs can be found at here.

Tutorial Sources

Please feel free to to view and download the complete sources from this tutorial from my Bitbucket repository – or if you’ve got Mercurial installed just check it out with

hg clone https://bitbucket.org/hascode/greenmail-it-samples

Resources

package it;

import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.icegreen.greenmail.user.GreenMailUser;
import com.icegreen.greenmail.user.UserException;
import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.ServerSetupTest;

public class Pop3IT {
private static final String USER_PASSWORD = “abcdef123″;
private static final String USER_NAME = “hascode”;
private static final String EMAIL_USER_ADDRESS = “hascode@localhost”;
private static final String EMAIL_TO = “someone@localhost.com”;
private static final String EMAIL_SUBJECT = “Test E-Mail”;
private static final String EMAIL_TEXT = “This is a test e-mail.”;
private static final String LOCALHOST = “127.0.0.1″;
private GreenMail mailServer;

@Before
public void setUp() {
mailServer = new GreenMail(ServerSetupTest.POP3);
mailServer.start();
}

@After
public void tearDown() {
mailServer.stop();
}

@Test
public void getMails() throws IOException, MessagingException,
UserException, InterruptedException {
// create user on mail server
GreenMailUser user = mailServer.setUser(EMAIL_USER_ADDRESS, USER_NAME,
USER_PASSWORD);

// create an e-mail message using javax.mail ..
MimeMessage message = new MimeMessage((Session) null);
message.setFrom(new InternetAddress(EMAIL_TO));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(
EMAIL_USER_ADDRESS));
message.setSubject(EMAIL_SUBJECT);
message.setText(EMAIL_TEXT);

// use greenmail to store the message
user.deliver(message);

// fetch the e-mail from pop3 using javax.mail ..
Properties props = new Properties();
props.setProperty(“mail.pop3.connectiontimeout”, “5000″);
Session session = Session.getInstance(props);
URLName urlName = new URLName(“pop3″, LOCALHOST,
ServerSetupTest.POP3.getPort(), null, user.getLogin(),
user.getPassword());
Store store = session.getStore(urlName);
store.connect();

Folder folder = store.getFolder(“INBOX”);
folder.open(Folder.READ_ONLY);
Message[] messages = folder.getMessages();
assertNotNull(messages);
assertThat(1, equalTo(messages.length));
assertEquals(EMAIL_SUBJECT, messages[0].getSubject());
assertTrue(String.valueOf(messages[0].getContent())
.contains(EMAIL_TEXT));
assertEquals(EMAIL_TO, messages[0].getFrom()[0].toString());
}
}

Tags: , , , , , , , , , , , ,

One Response to “Integration Testing IMAP, SMTP and POP3 with GreenMail”

  1. dean Says:

    very helpful, thanks.

Leave a Reply

Please leave these two fields as-is:

Protected by Invisible Defender. Showed 403 to 81,008 bad guys.

Search
Categories