Improve mailing: Always send bulk E-Mails with SPF and DKIM
Out Of Date Warning
This article was published on 20/06/2013, this means the content may be out of date or no longer relevant.
You should verify that the technical information in this article is still up to date before relying upon it for your own purposes.
When deciding, how to send mails to customers efficiently, there is always a problem of how to sustain deliverability and not get classified as spammy service. Besides organisational measures, like interesting content and visible unsubscribe links, there are 2 DNS settings, which should be set anyway: DKIM and SPF.
The SPF record roughly contains a list of servers, that are allowed to send mails on behalf of the domain. It is easy to do:
$ dig heise.de TXT heise.de. 3600 IN TXT "v=spf1 ip4:126.96.36.199/24 ip4:188.8.131.52/24 ?all"
Here, heise.de authorizes the both ip subnets to send mails on behalf of "@heise.de". Besides IPs, you can reference the A and CNAME records. (I use the standard tool dig, to query current DNS settings)
To get that, login to your DNS service provider and add a new DNS entry:
- Type TXT
- host: your server's hostname
v=spf1 mx a ip4:184.108.40.206 -all
- TTL: e.g. 3600 (seconds)
This way, you allow mails only come from your server's MX, A-records or manual IP. The
-all forbidds any other server to send e-Mails for your domain.
Just send a mail from your server to a mail provider (like gmail) and view the e-mail header ("full source"). It should contain:
spf=pass (google.com: domain of XXX@yyy designates 220.127.116.11 as permitted sender) smtp.mail=xxx@yyy;
Besides SPF, which is relatively easy to implement, there is the somewhat more complicated DKIM, a.k.a. Domain Keys. Here, you also need two custom DNS TXT entries and also have to configure your mail sending daemons (MTU) and/or applications to sign your mails.
First, generate a public and private key pair
openssl genrsa -out dkim.private.key 1024 openssl rsa -in dkim.private.key -out dkim.public.key -pubout -outform PEM
Second, put the public key in the DNS record
Create a DNS entry:
- Type TXT
Choose a "selector", which can be a kind of name for the validations. Below, I will use
x. Common is also
Create another DNS entry
- Type TXT
v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQE...after p= put your public key from above without BEGIN/END header and all lines joined
After waiting some time, check the 2 DKIM DNS keys with:
$ dig _domainkey.HOSTNAME.com TXT $ dig x._domainkey.HOSTNAME.com TXT
Third, enable your MTA and/or Application to sign outgoing e-Mails
e.g. Exim (German guide),
# Gemfile gem "dkim" # config/initializers/dkim.rb if Rails.env.production? # Configure dkim globally (see above) Dkim::domain = 'YOURHOSTNAME.com' Dkim::selector = 'x' Dkim::private_key = File.read('config/dkim/dkim.private.key') # This will sign all ActionMailer deliveries ActionMailer::Base.register_interceptor(Dkim::Interceptor) end
Just send an e-Mail to e.g. Gmail/Yahoo/Outlook.com, end check the mail's source code:
spf=pass (google.com: domain of noreply@HOSTNAME designates 18.104.22.168 as permitted sender) smtp.mail=noreply@HOSTNAME;
dkim=policy (weak key)The private key needs at least 1024 bits, otherwise GMail will fail the DKIM test.
dkim=fail (test mode)Your DNS entry has an t=y part, which enables test mode
dkim=neutral (bad format)Check the format of your DNS entry. Maybe there are some spaces/newlines
DNS resolving does not update Try a shorter key length (1024bit).