My goal is to host multiple¬†Wordpress blogs on a single Ubuntu server. This will be for outbound email only. Setting up SMTP for each of my blogs by selecting from a plethora of plugins isn’t a sound solution. With sendmail/postfix and default PHP mail() settings, it isn’t difficult to send mail. However, the problem is that seemingly valid email often times gets marked as spam (e.g., Password Reset). Case in point:
wordpress_email_labelled_as_spam

Gmail’s spam filter is incredibly sophisticated and a bit more stringent than others. Reason being, the sender address can be easily spoofed. However, the originating server can not be forged so easily. Even then, there are further checks to make sure the email isn’t spam.

Capture

From my experience, there a few factors which determine whether an email is going to be marked as spam by Gmail.

  • You need to have a Sender Policy Framework (SPF) and a DomainKeys Identified Email (DKIM) records in your DNS.
    • You could run: dig [domain name] txt to find out any domain’s TXT DNS records.
    • The SPF record determines which servers are allowed to send email.
    • The DKIM record is used to validate¬†the actual email itself. This ensures the message wasn’t tampered with even if it did come from a valid mail server.
    • If both are valid you’ll see something like this (You can see this under “Show Original” from the message pull-down menu):
      spf=pass (google.com: domain of admin@geekbacon.com designates 104.236.156.225...
      dkim=pass header.i=@geekbacon.com
  1. The “From” email address and name. From what I’ve seen, only valid sender email addresses were able to avoid being marked as spam. So if you setup admin@geekbacon.com but that email address doesn’t actually exist, it will be marked as spam. Same goes for “no-reply” addresses, etc.
    Wordpress Email Options
  2. The content itself. Even emails without subjects could be marked as valid but a suspicious “Subject” could cause the spam filter to trigger. From my experience, the content of the email has a greater weight in determining whether the email is spam or not. Play around with the email templates, fix formatting errors, broken links, etc.

Setting up a SPF DNS Record

This one is straight forward. Create a TXT record “v=spf1 ip:[IP ADDRESS] ~all”

Here is an example from DigitalOcean:

Capture

How To Setup EXIM4 with DKIM

DKIM is included in Exim 4.7+. I’m installing Exim version 4.82 on Ubuntu 14.04.1 LTS, Trusty Tahr.

# Let's remove any residual installations
apt-get --purge remove exim4 exim4-base exim4-config exim4-daemon-heavy

# Installation
sudo apt-get install exim4 -y

# Select "internet site; mail is sent and received directly using SMTP" 
# and split files.
sudo dpkg-reconfigure exim4-config

# Make sure exim4 is your default MTA
netstat -ltnp | grep :25
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 16122/exim4 
tcp6 0 0 ::1:25 :::* LISTEN 16122/exim4 

# Create keys
mkdir /etc/exim4/keys
chown -R Debian-exim:adm keys
openssl genrsa -out dkim.key 1024
openssl rsa -in dkim.key -out dkim.pub -pubout -outform pem
chmod 600 /etc/opendkim/dkim.key

You need to create a DKIM record: “v=DKIM1; k=rsa; p=[Your public key]”

Here’s another example from DigitalOcean:

Capture

cat dkim.pub
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHKj656cdca3dkJNFw5Lji63O+
R+sZWDdWiHUcwnf40sSEarmShXG8u3o6QwaDAiaVAboIpUDa0I68Lz+aP2Ws9Y5w
tE9jPO57QeGjDdByX6nXrvBgOAyZ072oF70+C3VqkN3zjA1YNuMjP5ugjo6B4sds
DR5MBOcVHc3wNFZ1FwIDAQAB
-----END PUBLIC KEY-----

You’ll replace the “p=” section with your own public key without any line breaks.

Now create a new file /etc/exim4/dkim_vhosts. Here you would list out all the virtual hosts and allowed sender addresses in your domains. For example:

*@geekbacon.com: geekbacon.com
admin@testdomain.com: testdomain.com

Now edit /etc/exim4/conf.d/transport/30_exim4_config_remote_smtp. The entire file should look something like this:

remote_smtp_dkim:
  debug_print = "T: remote_smtp_dkim for $local_part@$domain"
  driver = smtp
.ifdef REMOTE_SMTP_HOSTS_AVOID_TLS
  hosts_avoid_tls = REMOTE_SMTP_HOSTS_AVOID_TLS
.endif
.ifdef REMOTE_SMTP_HEADERS_REWRITE
  headers_rewrite = REMOTE_SMTP_HEADERS_REWRITE
.endif
.ifdef REMOTE_SMTP_RETURN_PATH
  return_path = REMOTE_SMTP_RETURN_PATH
.endif
.ifdef REMOTE_SMTP_HELO_DATA
  helo_data=REMOTE_SMTP_HELO_DATA
.endif

dkim_domain = ${lookup{$sender_address}lsearch*@{/etc/exim4/dkim_vhosts}}
dkim_selector = mail
dkim_private_key = /etc/exim4/keys/dkim.key
dkim_canon = relaxed
dkim_strict = false
#dkim_sign_headers = DKIM_SIGN_HEADERS

Now restart exim4 (and Apache if you wish):

sudo service exim4 restart
sudo service apache2 restart

Now just send a test email from WordPress and it shouldn’t be marked as spam anymore! Lastly, I want to stress that the sender email should be valid, that includes “no-reply” addresses.