Skip to main content

Using the GreenMail Java-based In-Memory MailServer in Integration Tests

Posted by garysweaver on August 7, 2008 at 12:31 PM PDT

You've used in-memory databases, such as HSQLDB (formerly called Hypersonic) or it's newer, faster cousin H2, but fewer have heard about the in-memory mail server, GreenMail by IceGreen.

According to their site, "GreenMail is an open source, intuitive and easy-to-use test suite of email servers for testing purposes.
Supports SMTP, POP3, IMAP with SSL socket support. GreenMail also provides a JBoss GreenMail Service. GreenMail is the first and only library that offers a test framework for both receiving and retrieving emails from Java."

Examples of its use are available at their site, but here are a few things to note with the current version at time of writing, GreenMail v1.3.

1) In v1.3 GreenMail's start() and stop() methods start/stop the server which is running on a different thread, so for this version at least, it makes sense actually listen to the port of the GreenMail server until it starts up or shuts down. You may not have to worry about it sometimes, since it can start up fairly quickly, but be warned, unless this gets fixed in a later version. Just as a quick incomplete example, you might use code like this to check to see if the port is open (but this code is a bit messy!):

    public static boolean isPortOpen(String host, int port) {
        boolean result = false;
        Socket socket = null;
        PrintWriter out = null;
        BufferedReader in = null;
        try {
            socket = new Socket(host, port);
            out = new PrintWriter(socket.getOutputStream(),
                    true);
            in = new BufferedReader(new InputStreamReader(
                    socket.getInputStream()));
            result = true;
        } catch (UnknownHostException e) {
            System.err.println("problem with host " + host + e);
        } catch (IOException e) {
            result = false;
        }
        finally {
            try {
                socket.close();
            } catch (Throwable t) {
            }
            try {
                out.close();
            } catch (Throwable t) {
            }
            try {
                in.close();
            } catch (Throwable t) {
            }
        }
        return result;
    }

    private static void waitForStatus(boolean status, String host,
            int port, int maxWaitSeconds, int waitPeriodMillis)
            throws Exception {

        long startTime = System.currentTimeMillis();
        int lastSec = 0;

        while(isPortOpen(host, port)!=status &&
              lastSec < maxWaitSeconds) {
            long waited = System.currentTimeMillis() - startTime;
            if (lastSec!=(int)waited/1000) {
                lastSec=(int)waited/1000;
                if (status) {
                    System.err.println("Waited " + lastSec +
                       " sec total on GreenMail to start... attempting to connect to " +
                       host + ":" + port);
                }
                else {
                    System.err.println("Waited " + lastSec +
                       " sec total on GreenMail to stop... waiting for stop: " +
                       host + ":" + port);
                }
            }

            try {
                Thread.sleep(waitPeriodMillis);
            }
            catch (Throwable t) {
                System.err.println("sleep interrupted");
            }
        }

        if (isPortOpen(host, port)!=status) {
            if (status) {
                throw new Exception("GREENMAIL NOT STARTED! (waited " +
                  (System.currentTimeMillis() - startTime) + " msec total)");
            }
            else {
                throw new Exception("GREENMAIL NOT STOPPED! (waited " +
                  (System.currentTimeMillis() - startTime) + " msec total)");
            }
        }

        if (status) {
            System.err.println("Waited " +
                  (System.currentTimeMillis() - startTime) +
                  " msec total on GreenMail to start, and it started, in theory (because is listening on socket)");
        }
        else {
            System.err.println("Waited " +
                  (System.currentTimeMillis() - startTime) +
                  " msec total on GreenMail to stop, and it stopped, in theory (because is not listening on socket)");
        }
    }

2. I had trouble with receiving email from the secure servers (POPS and IMAPS). I tried to use a slight modification of InstallCert that would automatically say "Y" to install cert from GreenMail, but that didn't work. Let me know if you can get it to work, and please post your code or link to your code if you get it working. TIA!

Despite some slight issues, GreenMail is a really great tool for testing, and I hope IceGreen continues to develop it!

Related Topics >>