updated long ago, so way out of date, but may still be helpful
the perfect java email server
How to set up an almost entirely java based email server, with smtp, imap/imaps and webmail access. Note that although
this was all thoroughly tested only on linux servers, it ought to work just as well on that other operating system.
Accessing this server with java based webmail is dealt with here.
A note on versions
This writeup is based on the apache james server 3.3.0
version. Not the latest
release, but at the time of writing there appeared to be problems with version 3.4.0. The 3.3.0 version of
james needs a java 8 runtime; it does not for instance work with java 11.
Starting james
After downloading james from the link above, unzip the archive in a suitable place - on a linux server /opt is a
reasonable choice. There are a number of scripts in it's bin directory; I recommend using the run.sh command
(there's a run.bat for windows):-
root@skaro # cd /opt/james-server-app-3.3.0/bin/
root@skaro # nohup ./run.sh &
I have a couple of reasons for favouring the use of run.sh over the james command. Firstly I found that
although james start and james console works fine on a fedora linux system, it fails in a way mysterious to me on
debian. Using run.sh offers an easy way to set the appropriate version of java to use. in
/opt/james-server-app-3.3.0/conf create an executable file setenv.sh (on windows setenv.bat) with
content something like
JAVA_HOME="/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.fc29.x86_64/jre".
The james command does not seem to reference setenv.sh, but alternatively the JAVA_HOME can be set as an
environmental variable in whatever way your OS recommends.
James must be started by the root user (administrator on windows) as it needs access to priviledged ports below 1000; you
must first ensure that no other services are listening on the smtp and imap/imaps ports. It must be stopped and restarted
whenever it's configuration files are changed. A linux way of doing this is suggested below:-
root@skaro # ps aux | grep james
root 2427 108 9.9 3214224 389752 pts/0 Sl 12:18 0:52 /usr/lib/jvm/java-1.8.0-openjdk-1.8.0
/\/\/\/\/\/\/\
output snipped
\/\/\/\/\/\/\/
root@skaro # kill -9 2427
root@skaro # nohup ./run.sh &
Configuring maibox storage
The default for email storage is to use the embedded derby database. On a linux system maildir is an alternative, this is
configured in the mailbox.xml file.
Ajusting the smtp server
This is done by editing the smtpserver.xml file. I'd like to enable socketTLS, but my jwma webmail app
doesn't like that at the moment and mail doesn't get sent from it.
I uncommented the SMTP authentication code, changing the value from true to announce.
I uncommented the DNSRBLHandler code, but commented out the whitelist and replaced the DNSBL databases to use
sbl-xbl.spamhaus.org, bl.spamcop.net and cbl.abuseat.org. Don't neglect to leave the . after
each one.
Uncommenting the SPFHandler code looks like a good idea, but for me it stops mail being delivered.
I uncommented the SpamAssassinHandler code and adjusted down spamdRejectionHits from 10 to 4 (I'm guessing
this refers to the spamassassin score). There are some more notes on spamassassin
here.
Ajusting the imap server
This is done by editing the imapserver.xml file and this is as good a point as any to mention that I do not want to
support pop3, so I set pop3server enabled to false in the pop3server.xml file.
Rather than unencrypted imap, I only want to offer imaps and for that several steps are necessary. Firstly this line
<bind>0.0.0.0:143</bind>
is changed from port 143 to 993. The tls socketTLS is set to true
and key and self signed certificate are generated; the linux way of doing this is as follows (I believe there is also a
openssl version for windows):-
keytool -genkey -alias james -keyalg RSA -keystore /opt/james-server-app-3.3.0/conf/keystore
keytool -selfcert -alias james -keystore /opt/james-server-app-3.3.0/conf/keystore
I've found this technology to be very fragile. As well as imaps failing if the wrong version of java is used by a java webmail
client as mentioned in the webmail client notes, it also does not work if the key is created by the root user and if permissions and ownership are
messed with after the commands are run.
The first command asks for a password, which must match what you enter as <secret>.
I ignore the other questions except for
What is the name of your organization?
where I enter the domain name of the server. Do not enter a second password for the james certificate and do not
convert the keystore from JKS to pkcs12.
The final step is to add a provider to the conf/lib folder and configure the <provider> option to
either be
org.bouncycastle.jce.provider.BouncyCastleProvider, getting the jar from
here
or com.sun.crypto.provider and downloading here.
You can check that this has worked on a linux system with the openssl command:-
root@skaro # openssl s_client -servername localhost -connect localhost:993
CONNECTED(00000003)
/\/\/\/\/\/\/\/\/\/\/
certificate details snipped
\/\/\/\/\/\/\/\/\/\/\
---
* OK JAMES IMAP4rev1 Server Server skaro is ready.
root@skaro # cd /opt/james-server-app-3.3.0/conf/lib
root@skaro # openssl genrsa -out dkim-private.pem 1024
Generating RSA private key, 1024 bit long modulus (2 primes)
............................................+++++
.............................................+++++
e is 65537 (0x010001)
root@skaro # openssl rsa -in dkim-private.pem -out dkim-public.pem -pubout
writing RSA key
Place the following code block in the mailetcontainer.xml file immediately before the RemoteDelivery
mailet:-
<!-- DKIM signing -->
<mailet match="All" class="org.apache.james.jdkim.mailets.ConvertTo7Bit"/>
<mailet match="All" class="org.apache.james.jdkim.mailets.DKIMSign">
<signatureTemplate>v=1; s=your_selector; d=your_domain; c=relaxed/relaxed; h=Message-ID:Date:Subject:From:To:MIME-Version:Content-Type; a=rsa-sha256; bh=; b=;</signatureTemplate>
<privateKey>
-----BEGIN RSA PRIVATE KEY-----
contents of your dkim-private.pem here
-----END RSA PRIVATE KEY-----
</privateKey>
</mailet>
your_selector is dealt with on the
email authentication page and
your_domain should be the
domain that james is signing email for. Then within the
RemoteDelivery mailet add
<mail.smtp.allow8bitmime>false</mail.smtp.allow8bitmime>
There are other changes to be made in the default mailetcontainer.xml that do not relate to DKIM signing. The
<postmaster> line should be configured with a working email address in your domain. For tidyness that also
applies to the <notice> section of the AttachmentFileNameIs mailet.
The mailet with match SenderIs can be used to whitelist known allowed users and blacklist unwanted senders. I
assume that additional matches can be added as necessary. I comment out the ToSenderFolder mailet as the jwma webmail
program that I use does this and we do not need to save two copies of each mail sent to an outbox. I also comment out the
RemoteAddrNotInNetwork mailet as we are using SMTP auth. It's a good plan to check that your james is not acting as
an open relay at the MXtoolbox site.
I uncomment the RecipientIsLocal mailet and set the mailbox name to Spam. My hope is I will not see too
much in there!
Logging
The default logging system is sub-optimal and provided a
log4j.properties file that much improves the situation despite it being intended
for version 3.4.0 of james. Simply put it in the conf directory and restart james.