Configuring SSL in Apache James Email Server

If you have followed my post on (Installing and Configuring Apache James)[/blog/install-and-configure-apache-james/], you will have installed your base Apache James server and have the settings configured to send and receive mail for one or more domains. You may have also followed the post on (configuring DKIM and SPF)[/configuring-dkim-and-spf-for-apache-james/], in which case you have set up DNS and configuration information for you mail server to sign messages as authenticated from your email server and verify specific domains as authorized to send email from your server.

There is one more step, and a couple of configuration items, and then you will be off and running to have your email server communicate with other email servers on the Internet.

Why SSL

When the Internet was born, nothing was encrypted and all traffic across the network was essentially open. As the Internet became commercial and mushroomed in size, that situation became untenable, as banks and other commercial enterprises demanded security for their online offerings. Apart from anti-spoofing features in SPF and DKIM, the most important development in email has been the wide adoption of SSL encryptrion to protect traffic between email servers from spying.

In the early days, obtaining an SSL certificate was both expensive and complicated, requiring registration with a certificate authority, proof of domain ownership, and other steps left encryption out of reach for many server hosts.

A few years ago, a group of people put together a free service, (Let’s Encrypt)[https://letsencrypt.org], that provides an automated way for anyone to obtain a publicly signed SSL certificate for their domains. You will need a certificate in order to enable encryption on James.

A Note About Email Server IP Addresses

For best interoperability, you should plan on providing an IP address for your email server that is exclusive to the mail server hostname your are using. For example, mail.shoestringlab.com has an IP address that is not used by other hostnames.

Obtaining a Certificate

If you already have a certificate, skip this section. Otherwise, follow along. The easiest way to get a certificate from Let’s Encrypt is to set up a web site for the hostname of your mail server and use certbot, the Let’s Encrypt agent, to generate a certificate.

In the case of Shoestring Lab, we’re using mail.shoestringlab.com as the hostname of the mail server. Set up a simple one page web site at http://mail.shoestringlab.com (e.g. your hostname). I have used Nginx to create my site.

Install certbot if you have not yet:

$ sudo snap install --classic certbot

Then ask certbot to create a certificate for your domain:

$ sudo certbot --nginx

Certbot will ask you some questions to guide you through the steps for creating a new certificate. Once the certificate has been generated, you can move to the next step. You may delete the web site for the hostname at this point, but make sure you copy the location of the SSL certificate. It will be somewhere like:

/etc/letsencrypt.live/mail.shoestringlab.com/fullchain.pem

with the private key:

/etc/letsencrypt.live/mail.shoestringlab.com/privkey.pem

Once you have the location, go to the command line on your system and cd to the folder above, then use openssl to create a Java keystore:

$ openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out server.p12 -name mail.shoestringlab.com

This command will generate a file called server.p12 that contains an entry for your mail server SSL certificate. Next, use keytool to convert this keystore into a JKS format keystore that Apache James needs:

$ keytool -importkeystore -deststorepass <pass> -destkeypass <pass> -destkeystore keystore.jks -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass <pass> -alias mail.shoestringlab.com -storetype JKS

This command will generate a file called keystore.jks. Make sure you change to a secure password. Take that file and move it into the james/conf folder.

There are several configuration files where you need to make changes in order to use your new cert.

imapserver.xml

This file contains the configuration for the James IMAP server that receives mail and manages your mail folders. I prefer to use startTLS over the standard email ports, so I will be leaving the port definitions for all of the services alone. You may choose differently.

Here is the base configuration for using startTLS, just replace the tls section in imapserver.xml:

    <tls socketTLS="false" startTLS="true">
      <keystore>file://conf/keystore.jks</keystore>
      <secret>your_password_here</secret>
      <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
    </tls>

Where it says “your_password_here”, you will need to put in the password for the keystore.jks file that you created in the last step.

managesieveserver.xml

Sieve provides a way to script actions on mail across your server. If you have it turned on, just do the same as above and replace the tls section with this entry:

    <tls socketTLS="false" startTLS="true">
      <keystore>file://conf/keystore.jks</keystore>
      <secret>your_password_here</secret>
      <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
      <algorithm>SunX509</algorithm>
    </tls>

pop3server.xml

I personally do not use POP3, but if you have a reason to have the POP3 server turned on, make sure you update the configuration to use SSL:

    <tls socketTLS="false" startTLS="true">
        <keystore>file://conf/keystore.jks</keystore>
        <secret>your_password_here</secret>
        <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
    </tls>

smtpserver.xml

Again, update the tls configuration in this file with this block.

A special note about SMTP services. You may be tempted to update the service port to 465 or 587, but I have found (through extensive and painful experience) that many big email providers only try to connect to SMTP servers over port 25. Your mileage may vary, don’t say I didn’t warn you.

    <tls socketTLS="false" startTLS="true">
        <keystore>file://conf/keystore.jks</keystore>
        <secret>your_password_here</secret>
        <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
        <algorithm>SunX509</algorithm>
    </tls>

If you would like to change your SMTP server to require authentication (a good idea IMO), you need to uncomment the authRequired block in this file and set it to announce like so:

<authRequired>announce</authRequired>

Miscellaneous Configuration

If you have enabled SMTP authentication, you need to disable the Relay Denied message in mailetcontainer.xml. Find this mailet definition in the transport processor and comment it out:

    <!-- <mailet match="RemoteAddrNotInNetwork=127.0.0.1" class="ToProcessor">
        <processor>relay-denied</processor>
        <notice>550 - Requested action not taken: relaying denied</notice>
    </mailet> -->

Now that we have the services configured, go back to your command line and restart James:

$ sudo james restart

You may want to add a soft link to the james binary to your PATH so you can use the james command like above from anywhere.

You should also go to the top of the mailetcontainer.xml file and find the entry for the postmaster address and update it to something specific:

<postmaster>postmaster@shoestringlab.com</postmaster>

Reverse DNS Update

One last note. You will need to have a reverse DNS entry for the IP address for your mail server hostname that points to that hostname. Most likely you will need to work with your hosting provider to add this reverse DNS entry. Some hosting providers have automated ways to create these entries, so check with your hosting provider or network admin if you are unsure how to proceed.

Conclusion

That should be everything necessary to get your email server running and securely exchanging mail with other mail servers on the Internet. There are other detailed configuration changes you can make to James, I will cover some of them in a future post.