WordPress Email Deliverability
This is a copy of a post I wrote for a private WordPress Hosting Facebook group.
For the purpose of this little write up I’ll be using “WP Mail SMTP” by WPForms which is the most installed SMTP plugin; However, this applies to all SMTP plugins. (SMTP stands for “Simple Mail Transfer Protocol” and is how email is passed around the internet.)
Choosing a Mailer
There are three main options for sending mail: PHP’s mail() function, local SMTP, or remote SMTP. In WP Mail SMTP the PHP mail() function is the default and is called “none.” You should almost never opt to use the default PHP mail() option.
Default: When you select the default PHP mail() function PHP sends the email and it will originate from your web server. The main problem is that the IP address of the web server will either have no mail reputation or in the case of shared hosting more likely bad reputation. The IPs of web hosts are also frequently found on blacklists. Beyond that, PHP’s mail() function is not designed for large volume and doesn’t handle the intricacies of the email process besides just handing the message off to the recipient.
Local SMTP: This is typically something people will set up on a VPS or may be provided by some hosts. The web server will have something called a “Mail Transfer Agent” or MTA (typically sendmail, Postfix, or Exim4) and you will select SMTP but use “localhost” as the server. Without a dedicated IP the same reputation concerns as with PHP’s mail() apply here and even when it is dedicated not having any reputation can cause delivery issues until built up.
Remote SMTP: This is generally going to be the best option and involves using your domain’s mail provider like GSuite or a special service designed for sending only like Sendgrid. Cost and volume limits are the biggest concerns with using a remote SMTP provider but reputation generally isn’t an issue and their documentation walks you through a lot of the best pratices.
If you are using a service to handle mail for your domain like GSuite, Office 365, etc and your WordPress mail volume will be low you can use their SMTP relay; However, if you do not have a service setup or you expect a large volume of mail to be sent from your site you should look in to a transactional mail service like Sendgrid or Mailgun.
Choosing the “From” Address
One of the first options provided by the plugin is the address that email will come from. By default, it populates your account’s email address which is almost never a good idea. Mine has populated my @gmail.com address but unless I select “Gmail” as the Mailer and authenticate using the same username/password as my gmail.com address those messages will end up in spam or blocked. Why? Only Google can send email from @gmail.com (more on that later.)
You should generally send email from the same domain as the website. So, if your site is example.com your mail should come from email@example.com. The nature of the messages being sent also means you probably don’t want to deal with replies so firstname.lastname@example.org or something similar is standard practice. Using the same domain is not only good branding but using a domain you own will be necessary for the next part.
What the Heck is SPF?
Pretty much every email question brings up SPF at some point. SPF stands for “Sender Policy Framework” and is an authentication mechanism used to combat spoofing by specifying a list of authorized senders for a domain. When mail is received from a domain, SPF can be checked to make sure the origin of the message was allowed to use the domain.
For example, if your web server is 10.25.110.1 and you’re using PHP’s mail() function then 10.25.110.1 must be in the SPF record for the domain after the “@” in the from address. So, if we’re using email@example.com then 10.25.110.1 must be listed in example.com’s SPF record. This is why sending from @gmail.com as mentioned before isn’t going to work unless I use Gmail as the mailer (it would be the source.)
SPF records are stored in a special kind of DNS record on a domain called a “TXT” record. TXT records allow the storage and retrieval of small strings of text using DNS. Much like example.com points at an IP using an A record or CNAME in DNS, if you ask DNS for example.com’s TXT records it can return bits of text. The anatomy of an SPF record is the version tag so the receiver knows it’s an SPF record, the list of allowed senders, and a failure condition for if the source of an email isn’t in the list.
example.com IN TXT “v=spf1 ip4:10.25.110.1 -all”
Which says for example.com the IP address 10.25.110.1 is allowed to send email and anything else should fail (-all.) If I was using Sendgrid to send and GSuite for my mailboxes it might look like this:
example.com IN TXT “v=spf1 include:sendgrid.net include:_spf.google.com -all”
Which would cause SPF checks against my domain to include everything from the records for Sendgrid and Google as well.For more information you should start with the Wikipedia article on Sender Policy Framework and then find a guide.
NOTE: Not having an SPF record or setting it up incorrectly can have serious negative consequences on the deliverability of mail.
DKIM and DMARC?
DKIM stands for Domain Keys Identified Mail and is another authentication mechanism that relies on a combination of DNS and certificates. Its purpose is to cryptographically “sign” part of the email message verifying not only the contents but the sender who controls the keys.
DKIM uses certificate pairs (private and public) where the private key is used to “sign” part of the message and the receiver who retrieves the public key from DNS can verify the signature.
DMARC is a mouthful… It stands for Domain-based Message Authentication, Reporting & Conformance. It adds some additional checks to SPF and DKIM called “alignment checks,” can provide further guidance to receivers on what to do with email that isn’t authenticated, and provides a reporting mechanism where you can get information about failures.
While both DKIM and DMARC combine with SPF to provide a comprehensive authentication strategy, SPF should be your first concern. After that I would look in to DKIM and finally DMARC. What I typically do for new domains is setup SPF and temporarily use this DMARC record until I am ready to tweak it:
v=DMARC1; p=quarantine; pct=100;
If you would like a more comprehensive explanation of SPF, DMARC, and DKIM I have a post here: https://www.nickjames.ca/email-spoofing-prevention/ that you can read.
Again, actual implementation instructions can be found by looking for tutorials.
PTR Records (FCrDNS)
Thanks to Lukács József for reminding me… One other consideration when either using PHP’s default mail() option or a local MTA is something called Forward Confirmed reverse DNS (FCrDNS.) In short, the hostname the server sending mail identifies itself as must resolve to an IP that likewise resolves back to the same hostname (PTR record.)
This is not something that needs to be considered with third-party relays or shared hosting but may be a factor on a dedicated host or VPS if you change the machine’s hostname but not reverse DNS. For example, Linode will give you a default hostname for any new server which will be FCrDNS compliant; However, if you change the machine’s hostname or reverse DNS without changing both you may have delivery issues if using it to send mail.
Testing and Tools
When you’re first getting started, I cannot recommend https://www.mail-tester.com/ enough. It gives you an address you send a message to and it will report on all the things wrong with it such as missing SPF, failed DKIM, etc.
Another great tool is https://mxtoolbox.com/ for checking blacklists, verifying SPF, and all sorts of other things.