Best Practices for Sending Email

How to setup a website to send email using SPF, DKIM and DMARC authentication mechanisms which improve security and deliverability.

If you are creating a website, you probably want to be able to receive and reply to email using your domain name. You will also probably want to send email programmatically based on certain triggers. For example, to welcome a new user who signed up. If you want your emails to arrive in your customer's inbox instead of their spam folder, you will need to implement several protocols for email authentication. This article will explain all of these protocols and then walk you through setting them up.

Email

If you just want to check your DNS records to see if they are configured correctly for sending email, enter your domain name here and run a free test.

This article assumes that you know what DNS is and how to create and edit DNS records. If you already know SPF, DKIM, DMARC and BIMI then you might want to check out our Automatic Generator for these settings. Just enter a few values and it will create all the records for you automatically.

Implementing all of these protocols will improves your website's digital reputation, help your emails evade spam filters and avoid having your customers receive phishing emails or spam from your domain.

SPF (Sender Policy Framework)

SPF is a method for authenticating email. By publishing an SPF record, you are declaring who is allowed to send valid email from your website. Without this protection, anyone can send an email and put your domain name in the "from address" field which can trick customers into believing the email is from you. Implementing a strong SPF policy can help prevent forged emails and protects your customers from getting spam and phishing emails from your website.

An SPF record is a DNS TXT record at the root level of your domain. To make an SPF record, go to the place where you configure your DNS records and make a new TXT record. Leave the record name blank, because we want it to be at the root level. For the value, you will enter a string of text as explained below. Your domain should only have one of these records. All SPF records start with "v=spf1" and then follow with a series of space separated mechanisms. Here is an example:

v=spf1 a mx ip4:123.123.123.123 include:amazonses.com ~all

Each space separated mechanism in the SPF record gives permission for something to send email on behalf of your domain. Here is an explanation of the most commonly used mechanisms.

a
The receiver will do a DNS query for the A record on your domain. If the email originated from this IP address, then it is valid. Include this in your SPF record if your webserver directly sends email.

a:<hostname>
The receiver will do a DNS query for the A record of the specified hostname. If the email originated from this IP address, then it is valid. Include this if a different hostname directly sends email for you.

mx
The receiver will do a DNS query for the MX record on your domain. If the email originated from this location, then it is valid. Include this if the MX server that you use for receiving email also sends email. You may not need this if you are using a 3rd party email provider.

ip4:<ip address>
The receiver will check that the email was sent from this IP address. Only use this if you send mail from a specific IP address that isn't included in another mechanism.

ip6:<ip6 address>
The receiver will check that the email was sent from this IPv6 address. Only use this if you send mail from a specific IPv6 address that isn't included in another mechanism.

include:<hostname>
The receiver will look up the SPF record for the hostname listed here and add its mechanisms to your own. Lookup the documentation for the email provider that you are using for instructions on what to include here.

all
Matches any server (not recommended). Including "all" is worse than not having an SPF record, because you are explicitly giving permission for everyone to send email on your behalf.

-all
Matches no servers and instructs email recipients to reject emails that don't match any of the previous mechanisms. This is called the "fail" mechanism.

~all
Matches no servers and instructs email recipients to be suspicious of emails that don't match any of the previous mechanisms. This is called the "softfail" mechanism. It is recommended to use softfail until you are confident that you have allowed all of your valid senders, then switch to fail.

The SPF record is evaluated from left to right so try to put your most frequently used senders first. There is a limit of 10 DNS queries allowed, so try to keep it concise. Also, keep in mind that if you use a 3rd party service to send email, they may change their IP addresses without notifying you, so avoid hard coding their IP addresses in your SPF record. Use the include mechanism instead.

You can easily inspect your SPF record by running either of these unix commands from your terminal:

nslookup -type=txt example.com
dig -t txt example.com

SPF has some flaws. For example, it breaks automated email forwarding. If your customer has all of their email forwarded from one email address to another, then the SPF validation will fail because their first email address is not a valid sender for your domain. Also, it is possible for a malicious sender to spoof your IP address, thus allowing them to pass the SPF check. It's still important to have a valid SPF record, but you should also use DKIM, described in the next section.

If you want to read all the technical details you can read the SPF RFC which contains the complete specifications.

DKIM (DomainKeys Identified Mail)

DKIM is another way to authenticate email and prevent forged messages from being sent from your domain name. When you send email using this method, you cryptographically sign the email with your private key. The receiver can verify that this cryptographic signature is valid by using the public key that you publish via a DNS record.

v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfmnnq5zODLDSMqv2me7VLKjhJvVthJO819L8j6DV+5/EEYZt0i8R3XLVXzlvcZxjkfkmomWRJmCh4Sm6cQ9Aaww9WUnvGmGOKYPk73+bbQpFovPo+O1EY8enlT3u6Q8NKrxFbUxneY4C59sAsBfqFr/uwr2xngnrnlvX4RCSHRwIDAQAB

The DNS record with your public key is a specially formatted TXT record (example above). If you send email from your own email server, you will need to generate a private and public key and use the private key to sign emails that you send. This is outside the scope of this article. For now, we are assuming that you are using a 3rd party service to send email on your behalf. In most cases they will manage the private and public keys for you.

If you send email from multiple providers then you can have multiple DKIM records. Each one will have a different name (called a selector). When you send an email, it will include the selector name that corresponds to the private key that was used to sign the email. The email recipient uses the selector name to fetch the public key to verify the signature.

When using a 3rd party email provider, you will likely implement DKIM by making some DNS CNAME records that point from your domain to your provider. They will then handle the rest. For example, if you use Amazon SES, you would add three CNAME records that look something like this (the letters in front will be specific to your domain):

abcdefg._domainkey.example.com CNAME abcdefg.dkim.amazonses.com
hijklmn._domainkey.example.com CNAME hijklmn.dkim.amazonses.com
opqrstu._domainkey.example.com CNAME opqrstu.dkim.amazonses.com

If you use Fastmail, it will look like this:

fm1._domainkey.example.com CNAME fm1.example.com.dkim.fmhosted.com
fm2._domainkey.example.com CNAME fm2.example.com.dkim.fmhosted.com
fm3._domainkey.example.com CNAME fm3.example.com.dkim.fmhosted.com

Some email providers will give you the TXT record to publish yourself. If this is the case then, instead of creating a CNAME record, you would create a TXT record instead. For example, if you use Google Workspace, it will look something like this:

google._domainkey.example.com TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfmnnq5zODLDSMqv2me7VLKjhJvVthJO819L8j6DV+5/EEYZt0i8R3XLVXzlvcZxjkfkmomWRJmCh4Sm6cQ9Aaww9WUnvGmGOKYPk73+bbQpFovPo+O1EY8enlT3u6Q8NKrxFbUxneY4C59sAsBfqFr/uwr2xngnrnlvX4RCSHRwIDAQAB"

When a receiver gets an email from your domain, they will fetch the CNAME record that is specified in the email. Then they will fetch the DKIM TXT record from your provider and verify the signature. If the signature matches, then the email is valid. An attacker should not have your private key, so they will not be able to forge an email with a matching cryptographic signature. To examine your DKIM record you can use one of these unix commands.

nslookup -type=txt selector._domainkey.example.com
dig -t txt selector._domainkey.example.com

DKIM fixes most of the problems with SPF. However, there is one weakness in DKIM. It is vulnerable to a "replay attack". If a malicious actor is able to see a copy of an email as it whizzes around the internet, they can use the cryptographic signature in that email to send a duplicate email with some modifications. Since this modified email has a valid signature it will pass the validation. A newer standard called DMARC aims to fix this problem. Read on...

DMARC (Domain-based Message Authentication, Reporting and Conformance)

DMARC takes SPF and DKIM and wraps them up into a package that adds another layer called "alignment". It also adds the ability to receive reports about the delivery status of the emails you send and the ability to specify what to do with emails that don't pass all of the authentication steps. This can help with diagnosing email delivery problems.

Alignment means that the domain used in the "From" field of the email matches the domain in the "Return-Path" and matches the domain in the DKIM signature. This closes the loophole in SPF and DKIM that allows malicious senders to send mail from a different domain.

To use DMARC, you must already have SPF and DKIM setup correctly. Once this is done, you need to configure your 3rd party email provider to set the Return-Path or "MailFrom" field correctly to your domain. This may require you to create a DNS MX record or another TXT record. Follow the directions from your provider.

You will then need to add a DNS TXT record with a record name of "_dmarc". The value of the record always starts with "v=DMARC1" and then contains a semicolon delimited list of commands. It will look something like this:

v=DMARC1; p=reject; rua=mailto:admin@example.com; ruf=mailto:admin@example.com; fo=1

p=<value>
Values of "reject", "quarantine" and "none" are supported. Use "none" during setup to receive reports without blocking any email delivery. Once you are confident that everything is setup correctly, increase the level. A value of "quarantine" means that mail that doesn't validate will likely end up in the spam folder. A value of "reject" means that mail that doesn't pass will be rejected. It won't even make it into the user's spam folder.

rua=mailto:<email address>
The email address where aggregate reports will be sent in XML format.

ruf=mailto:<email address>
The email address where individual failure reports will be sent in XML format. Most email providers have stopped sending failure reports.

fo=<integer>
This specifies when you want to receive a failure report. A value of 1 means a report will be sent if either SPF or DKIM fails alignment. There are other values, but since most email providers have stopped sending failure reports it doesn't really matter.

You can lookup your DMARC record with either of these terminal commands:

nslookup -type=txt _dmarc.example.com
dig -t txt _dmarc.example.com

Once you have finished all of these steps, you will start receiving XML reports once a day from each email receiver that you send mail to. The XML report will contain information on how emails received from your domain have been validated. If you see failures inside this report, it can be one of two things. One, you have misconfigured something and your legitimate emails are being blocked. Two, your DMARC record is successfully blocking malicious emails that are being sent to your users. If it's the later you may be able to get enough information from the report to try to take action against the forger, but it's probably not worth it.

BIMI (Brand Indicators for Message Identification)

BIMI is a new standard that allows your brand logo to appear on your email in your customer's inbox. This helps improve brand recognition and trust with your users. A spam email pretending to be from your domain will not display your logo. This is not yet widely supported, but it doesn't hurt to prepare because it will probably become more common in the near future.

To implement BIMI, there are number of prerequisites.

  1. You must implement SPF, DKIM and DMARC and you must have your DMARC policy set to "quarantine" or "reject".

  2. You must have a registered trademark with a recognized government agency. The USPTO trademark process takes many months and at least $250, so you may want to get started early.

  3. You must purchase a Verified Mark certificate from a Certificate Authority. This will be similar to an SSL certificate. It will not be cheap, and as of the writing of this article there are no CAs that are issuing certificates. It's invite only.

  4. You must create an SVG version of your logo saved in a specific format.

  5. You must create a DNS TXT record pointing to your logo and certificate.

You can do the last two steps if you want, but it won't do anything until the previous steps are implemented. Here is how:

First, create an SVG of your logo and save it in the "SVG P/S" format. This is a new format that is not yet widely supported, but you can download a conversion tool on the BIMI website.

You then need to create yet another DNS TXT record. The record name will be "default._bimi.example.com" and the value should be something similar to what you see below. Update the URLs to point to your SVG and certificate.

v=BIMI1; l=https://www.example.com/bimi.svg; a=https://www.example.com/bimi.pem

You can check your BIMI record by running either of these commands from your terminal.

nslookup -type=txt default._bimi.example.com
dig -t txt default._bimi.example.com
ValidBot can test your website

Test Your Site

Now that you know how to authenticate email, you may want to use our SPF, DKIM and DMARC Wizard to automatically generate the records for you, based on your input.

To verify that you have everything set up correctly, type your domain name into the box below and run a free ValidBot Test. Look in the "Email" section of the report for your results on the things that we have discussed here. You can also read about our email tests if you want to learn more about what we look for.

Another way to test your settings is to send a test email to yourself and then use the "show original" or "show raw" option to see all of the headers. Look through the headers for "spf=pass", "dkim=pass" and "dmarc=pass" which will confirm that your mail host was able to authenticate the email correctly.

If you have implemented all of this then you should be able to send and receive email manually through your preferred email client. You should also be able to send email programmatically through your selected service provider. In both cases, your email will arrive, having passed all of the currently used email authentication protocols.