The biggest four email providers Gmail, AOL, Hotmail and Yahoo (in this order according to Comscore) all implement some form of anti-spam techniques.

The main technologies are reverse DNS checking, SPF, SenderID, Domainkeys and DKIM. I will discuss all of these here and provide my tips on setting up SPF, SenderID and DKIM. Please keep in mind that I am not an expert on email servers - but I hope this helps someone! It took me about half a day to figure this all out, so it is probably worth doing to improve your email delivery rates.

This blog entry from Dave Zohrom provides a nice discussion of sending email to a general audience (part 2 of a 3-post series).

Introduction

SPF or Sender Policy Framework

SPF is easy to setup. It uses DNS TXT records to allow the email providers to check which servers are authorized to send email for a particular domain. The SPF project has done a great job at making this simple to setup. Just go to their homepage and use the setup wizard to generate the appropriate TXT records (the text field underneath "Deploying SPF"). Then change the values in your DNS records.

One thing to note is that if you have multiple servers and send email from a server with a different hostname (e.g. "mail.example.com"), you need to setup a record for that server as well. See the common mistakes page on the SPF site. Also, if you have hostnames that are not supposed to send mail, you ought to indicate this as well.

Another thing is that if you are using Google Apps for Your Domain to send email, then you will need to have to add "include:aspmx.googlemail.com" to also allow mail from Google to validate. See this answer for more.

SenderID from Microsoft

SenderID is a variant of SPF, which for most practical cases is the same as SPF. Just setup SPF and this should produce a validation pass for SenderID as well. The semantics of the validation are a bit different, but this does not seem to be a major practical problem. See testing tips below to make sure that this is also true in your case.

DomainKeys

DomainKeys is an older version of DKIM (DomainKeys Identified Mail) developed by Yahoo. Despite having very similar names, these ARE NOT the same!

Both DomainKeys and DKIM store public key information in DNS records and sign the message headers of every email sent. The recipient can then verify the signature.

DomainKeys was deprecated in 2007, but some email providers may still be using it. However, these are a shrinking minority and Yahoo does support the newer DKIM. Because of this I did not add DomainKeys support but opted only to use DKIM.

You can add it to sendmail or Postfix using the dk-milter project code, but the unofficial RPM release is not maintained anymore, which means you will need to install it from source (available via SourceForge).

DKIM, or DomainKeys Identified Mail

DKIM on the other hand seems to be gaining momentum. It is used by Gmail, Yahoo and AOL and many others, and also works by publishing public keys via DNS TXT records and by signing the emails at the email server.

To setup DKIM, you need an additional filter which takes the completed email and adds the DKIM signature to the email prior to sending it out.

Postfix and sendmail support "milters", which is apparently short for "mail filter". There is a DKIM-milter package available for Centos at the EPEL repositories (see Centos page for 3rd party repos).

Setting up DKIM-milter with sendmail

Updated: Linked tutorial is DEAD. Here are the steps:

Step 1. Generate a private key

openssl genrsa -out default.private 1024

A “default.private” key file will be generated. It will be moved to a specific location later.

Step 2. Generate a public key for this private key

openssl rsa -in default.private -pubout -out default.public -outform PEM

A file with filename “default.public” will be generated with content like

-----BEGIN PUBLIC KEY-----

...

-----END PUBLIC KEY----

It will be used to create a DNS TXT record. See next step.

Step 3. Create a DNS record of type TXT

Modify DNS records and add a record of type TXT:

TXT record name

default._domainkey

TXT record value

v=DKIM1; g=*; k=rsa; p=<content of default.public>

Note that the prefix “—–BEGIN PUBLIC KEY—–” and suffix “—–END PUBLIC KEY—-” should not be put in the TXT record value.

This DNS record will be retrieved by mail receivers who want to verify emails with DKIM signatures. The record name “default._domainkey” tells verifier that the “selector” of this signature is “default”, therefore if you are changing selector name to something else, make sure you change all of them consistently.

Step 4. Install dkim-milter in Fedora

Run the following as root to install the dkim-milter pacakge.

yum install dkim-milter

Step 5. Enable dkim-milter to run on start-up

Make sure dkim-milter service will run on start-up by running this command:

chkconfig --level 3 dkim-milter on

Note that your server may use a different “runlevel”. You can check “/etc/inittab” to see which run level you are on.

Step 6. Move private key to appropriate location

As root, copy the private key to the location specified by the “keylist” (refer to next step) and make sure it is readable by dkim-milter:

mkdir /etc/dkim-milter/

mv default.private /etc/dkim-milter/default

chown dkim-milter.dkim-milter /etc/dkim-milter/default

Make sure the filename of private key file matches the “selector” name specified in the DNS record.

Step 7. Add an entry to the keylist for dkim-milter to read

Add the following line to /etc/mail/dkim-milter/keys/keylist. Replace <domain.com> with your domain name.

*:<domain.com>:/etc/dkim-milter/default

Step 8. Configure dkim-milter

Open configuration file /etc/mail/dkim-milter/dkim-filter.conf and use the following configuration:

Canonicalization simple
Domain example.com
KeyFile /some/path/to/whatever-your-keyfile-was
Selector name-of-the-selector
SignatureAlgorithm rsa-sha256
Socket inet:8891@localhost
Syslog Yes
Userid dkim-milter

NOTE: you will be configuring dkim-milter to use the loopback interface instead of a socket file. I was unable to get dkim-milter to work via the socket file with sendmail. If you get it working, let me know.

You may also want to setup the following:

SubDomains Yes
SyslogSuccess Yes
X-Header Yes

The X-Header and Syslog options are useful for debugging. See the config file, each option should be documented there.

Step 9. Change the default init.d script to use the loopback interface

Comments

radu: I've used this: Canonicalization simple Domain mydomain.com KeyFile /etc/dkim-milter/default Selector mail Signature default SignatureAlgorithm rsa-sha256 Socket inet:8891@localhost Syslog Yes Userid dkim-milter SubDomains Yes SyslogSuccess Yes X-Header Yes

but it says: Starting DomainKeys Identified Mail Milter (dkim-filter): dkim-filter: /etc/mail/dkim-milter/dkim-filter.conf: configuration error at line 5: unrecognized parameter

The selector name is "default".

Do you know what's wrong?

admin: Hi, it's a mistake in my post, the "Signature default" part should not be there (there is no Signature parameter). Fixed this in the post.

So try removing that line.

See man dkim-filter.conf for the actual options.

radu: Great, thanks.

Do you know how to setup this for multiple domains?

Vnmls: Good tutorial, thanks! Couple things I ran into:

  1. I had to put the INPUT_MAIL_FILTER into sendmail.mc, not submit.mc. Sendmail was not communicating w/ dkim-milter at all until I did this.
  2. I see no mention of ADSP. Your readers can go here: http://www.sendmail.org/dkim/tools to help set this up.

Steve Jenkins: Thanks for this write-up. I used OpenDKIM on my CentOS setup, and wrote about it here.

Daisy Rosa: I also had to move INPUT_MAIL_FILTER from submit.mc to sendmail.mc

Daisy Rosa: For multiple domains do: REPLACE Domain example.com WITH Domain example1.com, example2.com, example3.com

Kris: Great doc, but it is missing the starting of dkim-milter.

So you have do add:

service dkim-milter start

after its install via yum.