Apache James

Below you may find few notes about installing and playing with Apache James on Mac OS X.

Installation and preliminary configuration

Fetch the source code from Apache James download page - at the time of writing this note, v. 2.3.1 was available for download (I've used james-binary-2.3.1.tar.gz file). Unpack this file into some directory. Starting from now, we'll call a directory where James is available on disk as JamesHome.

Make some necessary adjustments in James starting script, placed in ${JamesHome}/bin/run.sh by adding following lines:

export JAVA_HOME="/Library/Java/Home"
export PHOENIX_JVM_OPTS="-Djava.net.preferIPv4Stack=true"
the second line was required to force using of IPv4 instead of IPv6 on my computer - I've noticed some problems with sending test emails when using IPv6 - James was complaining about "relaying denied" and dropping every email.

Change access rights for scripts starting James - two of them should be executable, but they aren't :(

chmod a+rx ${JamesHome}/bin/run.sh ${JamesHome}/bin/phoenix.sh

Run James for the very first time - don't worry if it will fail - now you should have a new directory under ${JamesHome}/apps/james which holds a content of ${JamesHome}/apps/james.sar file.

Now it's time for tuning James configuration:

  • modify a list of started services and port numbers to which James will bind services - adjust ${JamesHome}/apps/james/SAR-INF/config.xml file - I was planning to use SMTP server only, and for first tests on some non-standard port (8025 instead of 25), to avoid running James as privileged user. Changes made by me:
    • I've changed enabled attribute for pop3server and nntpserver sections to false
    • I've changed <port>25</port> value under smtpserver section to 8025

Now you may run James once again, this time it should start successfully. You may try testing it with some mail client, or if you are one of the persons knowing SMTP protocol ;) - just by hand - contacting the port set by you in the James configuration.

Mailet API Usage

James provides a mailet container into which users can deploy Matchers and Mailets - see Mailet API.
Shortly :) - Matchers are used for controlling which Mailets are involved in email processing, while Mailets are defining actions which should be performed while this process.

I've started with creating a maven 2 project containing only the pom.xml file and one Java class implementing org.apache.mailet.Mailet interface, heading to get some working example, very simple for the beginning. The main problem encountered by me was the absence of "mailet-api.jar" containing all classes and interfaces required by my code. What I've found in maven repository was james:mailet-api:3.0 and james:mailet:3.0, useless with James v. 2.3.1 - luckily, jar required by me is included in ${JamesHome}/apps/james.sar file - all I had to do was unpack SAR-INF/lib/mailet-api-2.3.jar from the sar archive and deploy it to my maven repo under james:mailet-api:2.3

Next I've added this mailet-2.3.jar file together with javax.mail:mail:1.4 as my project dependencies, and created a very simple Mailet implementation:

package com.wikidot.warlock;
 
import org.apache.mailet.Mail;
import org.apache.mailet.Mailet;
import org.apache.mailet.MailetConfig;
 
public class MyMailet implements Mailet {
 
  private MailetConfig mailetConfig;
 
  public void destroy() {
    mailetConfig.getMailetContext().log("MyMailet#destroy called");
  }
 
  public MailetConfig getMailetConfig() {
    mailetConfig.getMailetContext().log("MyMailet#getMailetConfig called");
    return mailetConfig;
  }
 
  public String getMailetInfo() {
    mailetConfig.getMailetContext().log("MyMailet#getMailetInfo called");
    return "MyMailet ...";
  }
 
  public void init(MailetConfig mailetConfig) {
    mailetConfig.getMailetContext().log("MyMailet#init called");
    this.mailetConfig = mailetConfig;
  }
 
  public void service(Mail mail) {
    mailetConfig.getMailetContext().log("MyMailet#service called");
  }
 
}

After building the project, I've get my-mailet.jar containing this one class. Then I've created ${JamesHome}/apps/james/SAR-INF/lib directory,
and copied my-mailet.jar along with mail-1.4.jar into this directory.

Finally, I've adjusted mailetpackages section of ${JamesHome}/apps/james/SAR-INF/config.xml file, by adding the Java package holding my class:

<mailetpackages>
  <mailetpackage>org.apache.james.transport.mailets</mailetpackage>
  <mailetpackage>org.apache.james.transport.mailets.smime</mailetpackage>
  <mailetpackage>com.wikidot.warlock</mailetpackage>
</mailetpackages>

and attached MyMailet under processor[@name="root"]:

<processor name="root">
  <mailet match="All" class="MyMailet" />
  ...
</processor>

One small mail sent using James and inspection of newest ${JamesHome}/apps/james/logs/mailet-*.log file have proven that my mailet is visible in the whole system:

James.Mailet: MyMailet#init called
...
James.Mailet: MyMailet#service called
...
James.Mailet: MyMailet#destroy called

Resources

  1. Apache James
  2. "Create email-based apps with JAMES", Serge Knystautas, JavaWorld, October 2001
  3. "Working with James, Part 1: An introduction to Apache's James enterprise e-mail server", Claude Duguay, IBM developerWorks, June 2003
  4. "Working with James, Part 2: Build e-mail based applications with matchers and mailets", Claude Duguay, IBM developerWorks, June 2003
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.