Implementing a stand alone Email Server – Getting Started with Apache James

Using email as a decoupled integration mechanism for applications is a fairly crude and simplistic yet effective approach. Messaging infrastructures – MOM – were all the rage, and still are as part of the ESB architectures and products. The idea is simple: a message sent, it is queued and will be delivered to a receiver. At a simpler and more cost-effective end of the spectrum, Email can be used for much the same purpose. A message is sent and held in an email server. A receiving application can poll the email server for recently received messages, read them and act upon them. One of the attractions of using Email is that most popular programming languages and environments know how to send emails, over the SMTP protocol to email servers anywhere on the internet; SMTP is almost as omnipresent as the HTTP protocol. Take for example the Java Mail API and the Oracle utl_smpt and utl_mail (10g) PL/SQL Packages.

In the second part of a series in which I intend to implement a business process – handling the registration for a conference on SOA and BPEL – using a BPEL Container, I will set up my own specialized mail server for the decoupling of the interaction between my website that allows users to register – also see the first part in this series: Generic Service – HTML Form Post to Email Servlet – and the backoffice process that handles the registration. For this, I will use Apache James, an open source News and Mail Server. Using the Java Mail API we will programmatically check for the arrival of new emails and read their contents.

Why a stand alone mailserver?

I do not want – and our mail administrator certainly does not want – the email conversations between my applications (in reality service calls) to put additional strain on and clutter up the corporate email server. Besides, having a stand alone mailserver allows me to perform administrative tasks that otherwise I would not have permissions for. In addition, I can perform demonstrations on my laptop without any connection to the outside world – sending and receiving emails locally.

Getting Started with Apache James

1. Go to the home page of Apache James. Here we read: “The Apache Java Enterprise Mail Server (a.k.a. Apache James) is a 100% pure Java SMTP and POP3 Mail server and NNTP News server.
We have designed James to be a complete and portable enterprise mail
engine solution based on currently available open protocols. James is also a mail application platform. We have developed a Java API to let you write Java code to process emails that we call the mailet API. A mailet can generate an automatic reply, update a database, prevent spam, build a message archive, or whatever you can imagine. A matcher
determines whether your mailet should process an email in the server.
The James project hosts the Mailet API, and James provides an
implementation of this mail application platform API.” Sounds fine for our purposes.

2. Download the latest stable release: 2.2.0 from http://james.apache.org/download.cgi

Following the instructions on the James Wiki, I try to set up the email server as quickly as I can.

3. Extract the downloaded zip-file to local directory w:\james. Run W:\james\james-2.2.0\bin\run.bat. The console shows:

Implementing a stand alone Email Server - Getting Started with Apache James james1

4. Kill the process (either do kill or ctrl-c or whatever you
want). Starting James once was necessary to extract its directory
structure and expose the configuration files to edit.

5. After shutting down James for the first time, you’ll find a file in the
james-2.1-2/apps/james/SAR-INF folder called config.xml, which you
should take a look at. The first thing you would normally change is the
administrator account, which is set to root, with the password root, by
default. We’ll leave it alone for development but it would be unwise to
leave it configured this way in a production system for obvious
reasons. The next thing to change is usually the DNS server address,
which is necessary if James is to operate as a complete e-mail server.
We’ll leave this alone as well, given that all our tests will be run
from localhost, but again this is an important setting that you should
be aware of. The rest of the default settings are fine, given our
development objectives, though it’s important to understand the
configuration file. You can find more information in the documentation
provided in the james-2.1.2/docs directory.

6. Start James again using bin/run.sh or bin\run.bat. Let’s create a test user. On Windows open a second Command Console. Type: telnet localhost 4555 and login with login id root  and password root. Now we are connected to the James administration console, as the server administrator.

7.  I want to set up the COA mail account, to be used for interaction between the COA-WEB application and the COA-back office. (COA stands for Conference Organization Administration). I type: “adduser coa coa”. This creates a new user account for user coa with password coa. Not secure but it will do for development. I then add two more accounts: coa-web and coa-backoffice.

8. Send an email to our new user account. The simplest way to do so is from a telnet session, like this: telnet localhost 25 to open a new telnet session, connect to port 25 – the SMTP port:

Implementing a stand alone Email Server - Getting Started with Apache James jamesEmailFromTelnet

Note: to end the message, type ENTER followed by the period followed by another ENTER.

When we take a look at the file system in the James directory structure, we can see that an Inbox is created for the COA user account. It contains the email we just so primitively sent:

Implementing a stand alone Email Server - Getting Started with Apache James jamesFileSystem

Looking in the file reveals the email itself:

Implementing a stand alone Email Server - Getting Started with Apache James jamesFirstEmail

9. A more refined alternative is for example from Java using the Emailer class from the article Generic Service – HTML Form Post to Email Servlet:

package nl.amis.util;

import java.util.Properties;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;


public class EmailSender {
    public EmailSender() {
    }

    public static void sendEmail( String to, String subject, String from, String content) throws Exception{
        Properties props = new Properties();
        props.setProperty("mail.transport.protocol", "smtp");
        props.setProperty("mail.host", "localhost"); 
        props.setProperty("mail.user", "coa-web"); 
        props.setProperty("mail.password", "");

        Session mailSession = Session.getDefaultInstance(props, null);
        Transport transport = mailSession.getTransport();

        MimeMessage message = new MimeMessage(mailSession);
        message.addFrom(new Address[] { new InternetAddress("coa-web@localhost",from)});  // the reply to email address and a logical descriptor of the sender of the email!

        message.setSubject(subject);
        message.setContent(content, "text/plain");
        message.addRecipient(Message.RecipientType.TO,
             new InternetAddress(to));

        transport.connect();
        transport.sendMessage(message,
            message.getRecipients(Message.RecipientType.TO));
        transport.close();
        }
        
        public static void main (String[] args) throws Exception {
            String content = "Some test content.";
            EmailSender.sendEmail("coa-backoffice@localhost","An interesting message","THE APP",content);
        }
   }

10. Now it is all working, I want to step up to the world of the GUI MailClient. Let’s get Thunderbird!

The Thunderbird Email Client

Thunderbird ( see http://www.mozilla.com/thunderbird/ ) is a free Email Client from the Mozilla Foundation. Its 6.0 Mb download contains an EXE file that can be run to install Thunderbird like a breeze. Thunderbird can be used to access many mail-servers – IMAP and POP protocol – including Microsoft Exchange and Apache James. Note: getting Thunderbird downloaded and installed took less than three minutes. It can import alls kinds of meta-data from my Outlook Client, including contacts, addresses etc. Thunderbird also has support for RSS Feeds and Newsgroups.

You can setup multiple email accounts in Thunderbird. I start by setting up one for the coa-backoffice email account created earlier in James:

Implementing a stand alone Email Server - Getting Started with Apache James thunderbird1

Implementing a stand alone Email Server - Getting Started with Apache James thunderbird2

Implementing a stand alone Email Server - Getting Started with Apache James thunderbird3

Thunderbird now connects to the mailserver@localhost, which is our Apache James instance. It reads out the account information for coa-backoffice, and runs into the email sent earlier from our little Java class EmailSender:

 Implementing a stand alone Email Server - Getting Started with Apache James thunderbird4

Let’s make it a little more interesting. We return to the case introduced in the article Generic Service – HTML Form Post to Email Servlet – the website (just a static HTML Document) that posts a form with Conference Visitor registration details to a servlet that uses the EmaiSender class to send an email to an account on mailserver that is monitored by a back office process. The HTML Form:

Implementing a stand alone Email Server - Getting Started with Apache James coaForm

I made a few trivial changes to the document as it was in the previous article, to have it send the email to the coa-backoffice@localhost address:

          <form action="http://10.0.0.156:8988/COA_WEB-ViewController-context-root/htmlpost2emailservlet" method="post"
                enctype="application/x-www-form-urlencoded">
            <input type="hidden" name="email_addressee"
                   value="coa-backoffice@localhost"/>
            <input type="hidden" name="email_subject"
                   value="Conference Registration"/>
            <input type="hidden" name="email_sender"
                   value="COA-WEB"/>

After submitting the registration form, the following email is found in Thunderbird:

Implementing a stand alone Email Server - Getting Started with Apache James thunderbird5

 

Programmatically access an email account

So far we have used a very primitive way of inspecing our email account (by browsing the mailserver’s file system) and a very slick way (using the Thunderbird mail client). However, if we want to use email to initiate business processes, we also need programmatic access to the email account. Let’s see how to do that.

Using the article by Claude Dugay, I can quickly develop a class that connects to the James Email-server and reads out the messages in the inbox for the coa-backoffice user:

package nl.amis.util;

import java.io.*;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;

public class EmailClient  extends Authenticator
{
  public static final int SHOW_MESSAGES = 1;
  public static final int CLEAR_MESSAGES = 2;
  public static final int SHOW_AND_CLEAR =
    SHOW_MESSAGES + CLEAR_MESSAGES;
  
  protected String from;
  protected Session session;
  protected PasswordAuthentication authentication;
  
  public EmailClient(String user, String host)   {
    this(user, host, false);
  }
  
  public EmailClient(String user, String host, boolean debug)  {
    from = user + '@' + host;
    authentication = new PasswordAuthentication(user, user);
    Properties props = new Properties();
    props.put("mail.user", user);
    props.put("mail.host", host);
    props.put("mail.debug", debug ? "true" : "false");
    props.put("mail.store.protocol", "pop3");
    props.put("mail.transport.protocol", "smtp");
    session = Session.getInstance(props, this);
  }
  
  public PasswordAuthentication getPasswordAuthentication()  {
    return authentication;
  }
   
  public void checkInbox(int mode)
    throws MessagingException, IOException  {
    if (mode == 0) return;
    boolean show = (mode & SHOW_MESSAGES) > 0;
    boolean clear = (mode & CLEAR_MESSAGES) > 0;
    String action =
      (show ? "Show" : "") +
      (show && clear ? " and " : "") +
      (clear ? "Clear" : "");
    System.out.println(action + " INBOX for " + from);
    Store store = session.getStore();
    store.connect();
    Folder root = store.getDefaultFolder();
    Folder inbox = root.getFolder("Inbox");
    inbox.open(Folder.READ_WRITE);
    Message[] msgs = inbox.getMessages();
    if (msgs.length == 0 && show)
    {
      System.out.println("No messages in inbox");
    }
    for (int i = 0; i < msgs.length; i++)
    {
      MimeMessage msg = (MimeMessage)msgs[i];
      if (show)
      {
        System.out.println("    From: " + msg.getFrom()[0]);
        System.out.println(" Subject: " + msg.getSubject());
        System.out.println(" Content: " + msg.getContent());
      }
      if (clear)
      {
        msg.setFlag(Flags.Flag.DELETED, true);
      }
    }
    inbox.close(true);
    store.close();
    System.out.println();
  }
  public static void main(String[] args) throws Exception{
      // CREATE CLIENT INSTANCES
      EmailClient emailClient = new EmailClient("coa-backoffice", "localhost", false);
         
      // LIST MESSAGES FOR email client
      emailClient.checkInbox(EmailClient.SHOW_MESSAGES);
  }
}

The result of running this EmailClient class:

Show INBOX for coa-backoffice@localhost
    From: COA-WEB <coa-web@localhost>
 Subject: Conference Registration
 Content: country=Netherlands
email_sender=COA-WEB
nomeat=Y
telephone=030-6016000
Address=Voorweg 146
y=45
receive_emails=Y
postal_code=2716 NK
email=jellema@amis.nl
email_addressee=coa-backoffice@localhost
fax=030-6016001
name=Lucas Jellema
x=27
city=Zoetermeer
email_subject=Conference Registration

Process exited with exit code 0.

Resources

Working with James, Part 1: An introduction to Apache’s James enterprise e-mail server – Claude Duguay 10 June 2003 on IBM Developer Works

Apache James Wiki – Quickstart

Apache James Home Page

Business Case of the Conference Organisation Administration – Generic Service – HTML Form Post to Email Servlet

7 Comments

  1. sumeet March 20, 2011
  2. Ria September 29, 2009
  3. Amit Gupta November 24, 2008
  4. Lucas Jellema October 8, 2006
  5. Lucas Jellema October 5, 2006
  6. Krishnan June 12, 2006
  7. David Medinets April 11, 2006