Configuring DKIM and SPF for Apache James Email Server

In my last post, I provided an updated tutorial on (Installing and Configuring Apache James Email Server)[/blog/install-and-configure-apache-james-email/]. While that tutorial goes through the necessary configuration changes to James to get a basleline server running in production, it does not cover DKIM and SPF, which are technologies used to ensure that email proclaiming to come from a certain domain is really being sent from that domain and not being spoofed.

SPF - Sender Policy Framework

Both DKIM and SPF are implemented through DNS. (DKIM requires additional configuration on the server). Since SPF is by far the easier of the two to configure, I will cover it first.

SPR simply requires a TXT entry in the DNS for your domain that points to the IP address of your email server. That way, email servers receiving email from your domain can verify that the sending IP address matches the address in your SPF DNS record.

In my tutorials, I have been using the domain shoestringlab.com as the example domain for configuration. The SPF record for shoestringlab.com looks like this:

TXT   v=spf1 ip4:104.168.165.76 -all

The Host in the DNS TXT entry should be set to nothing, i.e. @.

In case you are using the multihoming features of Apache James to serve email for more than one domain, when you add an SPF record for the next domain, you should include shoestringlab.com so receiving email servers know that shoestringlab.com is allowed to send mail on behalf of that other email domain.

v=spf1 ip4:104.168.165.76 include:shoestringlab.com -all

That’s all you need to implement SPF, the servers will do the rest.

DKIM - DomainKeys Identified Mail

DKIM goes a step further than SPF by digitally signing all outbound emails from your mail server so that receiving mail servers can check the signature to verify its authenticity. In order to do that, you need to generate a secure cryptopgrahic public/private key pair that DKIM will use for signing and verifying email.

Using OpenSSL, generate a private key. 1024 bit is the minimium encryption level for DKIM:

openssl genrsa -out dkim-private.pem 1024

and then extract a public key:

openssl rsa -in dkim-private.pem -out dkim-public.pem -pubout

Next, you need to publish your public DKIM key in DNS using a TXT record. For the Host name in the TXT record, create a selector using year/month/day._domainkey to create a unique selector record. For the text entry, use k=rsa; p=<public_key>, where <public_key> is the public key you extracted above from your generated key. Here is the DKIM record for shoestringlab.com:

TXT 20210620._domainkey v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGHGeF1DuKqWD4ucM0rKO+GvXO D4UhqRujZ123q0EUUWCVvFLp0rDnvMlJsWSQ870ehRx/UaQG9yJAJKCTTAnfXdNM qdGgK8SVCmMaR03saYrG9N0kDPref5PD8h9MxWc1Xm0ygao2s2ClAVxNwCUu/3ge BndYEcZU2E7WNff85QIDAQAB

Lastly, you need to add two maillets to the mailletcontainer.xml file in the /conf file of Apache James. The first converts messages to 7 bit to prevent incorrent encoding. The second uses the selector from your DNS record and the private key you generated above, which you can open with a plain text editor and copy into the XML file.

<mailet match="All" class="org.apache.james.jdkim.mailets.ConvertTo7Bit"/>

<mailet match="All" class="org.apache.james.jdkim.mailets.DKIMSign">
    <signatureTemplate>v=1; s=20210620; d=shoestringlab.com; 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-----
<Your Key Goes Here>
-----END RSA PRIVATE KEY-----
    </privateKey>
</mailet>

Add this pair of mailets to the transport processor section, directly after the SMTPAuthSuccessful mailet.