Kohei Nozaki's blog 

Setting up Apache James mail server


Posted on Wednesday Feb 04, 2015 at 11:04PM in Technology


I’m trying to setup the Apache James server. latest 3.0.0.beta4 looks obsolete so I’ll use latest version in SVN trunk. first I’m afraid about if it is abandonded because the last beta release was released on 2012, but there are some traffics in its mailing list and issue tracker. I think I would be able to contact with users or developers.

Checkout and build

First, checkout the code from trunk and build it.

UPDATE November 2015 According to http://www.mail-archive.com/server-user@james.apache.org/msg15244.html It looks like the SVN repository involved some changes so use the following instead:

svn checkout http://svn.apache.org/repos/asf/james/project/trunk james-trunk
cd james-trunk
mvn clean install -DskipTests=true
cd server/app
mvn clean package -Pwith-assembly

svn co http://svn.apache.org/repos/asf/james/server/trunk james-server
cd james-server; mvn clean install

UPDATE February 2016

Now the repository of James has been migrated to git, and build instruction has changed as well. I’ve succeeded to build the package with following procedure:

git clone http://git-wip-us.apache.org/repos/asf/james-project.git
cd james-project
mvn package -DskipTests=true -Pwith-assembly

Check official guide for latest info.

Then james-server-app-3.0.0-beta5-SNAPSHOT-app.tar.gz will be built in server/app/target. I’ll use this archive.

Configure and run

Initially James will try to listen ports of 25, 110 and 143 but it requires root privilege. I don’t want to run James process in root account so I changed the port which James will use. it can be achieved with custom configuration files named smtpserver.xml, popserver.xml and imapserver.xml in $JAMES_HOME/conf. we have to copy the configuration templates and modify to suit each use case.

cd conf
cp smtpserver-template.xml smtpserver.xml
cp pop3server-template.xml pop3server.xml
cp imapserver-template.xml imapserver.xml

First, I changed the value of bind element as follows which is placed inside smtpserver element in smtpserver.xml.

<bind>0.0.0.0:10025</bind>

For pop3server.xml I did the same as follows.

<bind>0.0.0.0:10110</bind>

imapserver.xml too.

<bind>0.0.0.0:10143</bind>

Then execute following command.

cd ../bin
./james start

Then you can test if James is up and running properly with command telnet localhost 10025 as follows. if you can’t connect to James check $JAMES_HOME/log/wrapper.log to find what the cause is.

$ telnet localhost 10025
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 kyle-no-MacBook.local JAMES SMTP Server Server (JAMES SMTP Server ) ready
QUIT
221 2.0.0 kyle-no-MacBook.local Service closing transmission channel
Connection closed by foreign host.

You can stop James as follows.

./james stop

Create an account and domain

I’ll create a domain my.localdomain and a user kyle who uses his password as mypassword.

./james-cli.sh -h localhost -p 9999 adddomain my.localdomain
./james-cli.sh -h localhost -p 9999 adduser kyle@my.localdomain mypassword

Test from Thunderbird

Now you can send and receive mails using James server.

  1. Configure mail account as follows:

    • Mail address: kyle@my.localdomain

    • Password: mypassword

    • Receiving server: protocol=IMAP, hostname=localhost, port=10143

    • Sending server: protocol=SMTP, hostname=localhost, port=10025

  2. Send a mail to kyle@my.localdomain

Add a shutdown hook which executes shutdown of Derby

By default, $JAMES_HOME/var/store/derby/db.lck file will be left undeleted after shutdown of James. it means that James doesn’t execute properly shutdown procedure of Derby. I guess it may cause data corruption of the Derby database. so I added shutdown hook so that Derby can execute properly shutdown at every shutdown of James.

  1. Clone my GitHub repository named derby-shutdown-bean, build a jar and copy it to $JAMES_HOME/conf/lib. it contains a bean named DerbyShutdownSpringBean which implements DisposableBean. it will be instantiated at the time of booting James, then it executes shutdown procedure of Derby at the time of shutdown of James.

    git clone https://github.com/lbtc-xxx/derby-shutdown-bean
    cd derby-shutdown-bean
    mvn clean package
    cp target/derby-shutdown-bean.jar ~/servers/james-server-app-3.0.0-beta5-SNAPSHOT/conf/lib
  2. Copy spring-server.xml to $JAMES_HOME/conf/META-INF/org/apache/james. that file is available at /container/spring/src/main/resources/META-INF/org/apache/james/spring-server.xml of source distribution.

    $ pwd
    /Users/kyle/servers/james-server-app-3.0.0-beta5-SNAPSHOT/conf
    $ mkdir -p META-INF/org/apache/james
    $ cp ~/src/james-server/container/spring/src/main/resources/META-INF/org/apache/james/spring-server.xml META-INF/org/apache/james
  3. Add following definition to $JAMES_HOME/conf/META-INF/org/apache/james/spring-server.xml. I think you should put that definition as the first children of beans element because it makes invocation of DerbyShutdownSpringBean#destroy() just before termination of the JVM. I suppose that if Derby was shutdown before stopping of other services of James, it may bring problem.

    <bean id="derbyShutdownSpringBean" class="org.nailedtothex.derby.DerbyShutdownSpringBean"/>
  4. Add following definition to $JAMES_HOME/conf/log4j.properties.

    log4j.logger.org.nailedtothex.derby=INFO, CONS, FILE

    Then you can check whether shutdown was successfully executed in $JAMES_HOME/log/james-server.log as follows:

    INFO  22:13:50,633 | org.nailedtothex.derby.DerbyShutdownSpringBean | Derby shutdown succeeded. SQLState=XJ015, message=Derby system shutdown.

Adjusting timeouts of Java Service Wrapper

James uses Java Service Wrapper to manage its JVM. if you have to run James on cheaper environment, consider adjusting following variables in $JAMES_HOME/conf/wrapper.conf to prevent unexpected emergency shutdown. it may cause data corruption of Embedded Derby server.

wrapper.jvm_exit.timeout=120
wrapper.startup.timeout=120
wrapper.shutdown.timeout=120
wrapper.ping.timeout=300

See following URLs for detail.

Remaining tasks or configurations

I would write more as another posting about more realistic topics that needed to use James as external server.

  • Disallowing mail relaying except connection from localhost

  • Checking whether the server is prohibited open relay

  • Using secure connection

  • Register as a daemon of Linux