📝 Email Security2 Jul, 2020 — 8 min
To combat spam there are three methods that email uses nowadays for verification. These measures prevent spammers from impersonating you and getting you in trouble (such as ending up on a blocklist). Let’s look at what they are and how to safely implement them.
- Sender Policy Framework (SPF) - defines which servers, by IP Address, are allowed to send messages on your behalf
- DomainKeys Identified Mail (DKIM) - a cryptographic signature which can be used to verify the sender
- Domain-based Message Authentication, Reporting, and Conformance (DMARC) - defines the policy for how to handle messages using SPF and DKIM
Here are a couple other terms that are relevant:
- Domain Name System (DNS) - converts text names (like ctmartin.me) into IP Addresses so a computer knows where to send data. Entries are called “records” and here are a few types that are relevant:
- Mail eXchange (MX) - Defines which server(s) incoming mail should be sent to. We aren’t going to be looking at this today.
- Canonical Name (CNAME) - Defines a different location to look for this data (like an alias or pointer).
- Text (TXT) - Literally text, certain syntaxes define functions. For example, starting with
v=spf1will define an SPF policy. SPF, DKIM, and DMARC are all based on TXT records.
Also, as a note, this is trying to cover the baseline of these practices; I’m not getting into policies for subdomains and subdomain alignment.
Another important note is that DNS records can take up to 72 hours to propogate (although really good services can do it in ~30 seconds). If your records seem to be set up correctly but aren’t being detected or applied correctly, they might still be propogating to other DNS servers.
SPF, DKIM, and DMARC allow you to ease-in so that you don’t start blocking anything you forgot about. However, the end goal is enforcement, where any services you didn’t specify are actively blocked.
The first thing to do is determine what programs you’re already using to send messages. This includes whatever you use to send email, any mailing lists, and other servers that might send emails.
Here is documentation for a few providers that may be useful throughout this process:
- G Suite: SPF, DKIM, DMARC
- Microsoft 365: SPF, DKIM, DMARC
- Mailgun: SPF & DKIM, DMARC
- SendGrid: SPF, DKIM, DMARC
After identifying your initial services you want to create a policy that defines them as valid. However, at this point you likely don’t want to turn on enforcement yet because that would block anything you might have forgotten. Let’s start by creating records that are neutral or soft-fail (fail but do not block), which is close to the default.
Most services have instructions and also check that at least their part is set up correctly before allowing you to start using them (however, that’s not always the case and many also only check SPF).
SPF policies are created as TXT records at the root of the domain you want them to apply to (sometimes referred to as
Here is a soft-fail SPF record:
This tells any receiving servers that messages will fail but not to block them.
You can allow services, for example with an
include statement. Here’s an example including G Suite:
v=spf1 include:_spf.google.com ~all
You can only have one policy per domain, but you can include multiple services. For example, here’s G Suite and Microsoft 365:
v=spf1 include:_spf.google.com include:spf.protection.outlook.com ~all
DKIM gives a list of valid keys; it doesn’t define policy.
So all we need to do is add keys for any allowed services.
Each key has an identifier, formally called a selector.
Selectors are part of the DNS record’s name.
selector1._domainkey (in long form, using
Some services (like G Suite) give you a TXT record to copy. Others (like Microsoft 365) give you a CNAME that points at their own servers. Both are valid methods. Follow the instructions for the service you use to add your keys.
If the service uses a CNAME, they’ll tell you where to point it. If they give you a TXT record, you’ll add something like this:
Microsoft 365 is a little complicated, so I’m going to write out the instructions here.
This is a combination of the documentation on how to connect to the Exchange server and how to create a DKIM key.
At time of writing, these commands can be copy-pasted, but this may change in the future.
This also works with PowerShell on Linux.
New-DkimSigningConfig for each domain you want DKIM enabled on, replacing
<domain> with the domain name (e.g.
$UserCredential = Get-Credential $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection Import-PSSession $Session -DisableNameChecking New-DkimSigningConfig -DomainName <domain> -KeySize 2048 -Enabled $True Remove-PSSession $Session
Then create a CNAME record for
selector1._domainkey pointing to
domainGUID is your domain, replacing periods with dashes;
initialDomain is the subdomain you got from Microsoft (visible in the Domains section of the Admin panel).
To create a basic DMARC policy that does nothing, add the following as a TXT record with the name
For DMARC to pass, it needs either SPF to pass or a valid DKIM signature. However, you really should have both.
If you send an email to an email on a different domain (such as a personal email), you can look at the headers to see if it passed.
In Gmail/G Suite (on the web), click the
... icon (next to reply and print) and click “View original message”.
In Outlook online, click the
... (also next to reply), and click “View > View message details”.
Gmail/G Suite will show you at the top summary if SPF and DKIM passed.
For Exchange (but also works in Gmail/G Suite and others), look for the text
Authentication-Results, which will be followed by the results of SPF, DKIM, and DMARC.
Here is an example with some details removed and formatted for readability:
Authentication-Results: spf=pass (sender IP is ...) smtp.mailfrom=...; dkim=pass (signature was verified) header.d=v...; dmarc=pass action=none header.from=...
As you can see, this email passed SPF, DKIM, and DMARC.
Sometimes though, mailing list software that forwards your email to a group can break DKIM signatures if it modifies the body. A good, modern mailing list might use (technically “experimental”) ARC signing to combat this, but not all do. If you have this issue, it should only affect the mailing list recipients and there’s not much you can do about it.
If this happens, or if you don’t have SPF or DKIM set up correctly for a service, you might see something like the following:
Authentication-Results: ... dkim=neutral (body hash did not verify) header.i=... header.s=... header.b=...; arc=fail (body hash mismatch); spf=pass (google.com: domain of ... designates ... as permitted sender) smtp.mailfrom=...
Since DKIM doesn’t specify policy (only specifies allowed keys), the result is “neutral” instead of “pass.” However, this is effectively the same as a “fail” and Gmail/G Suite will say that in its summary. While the DMARC result wasn’t listed, it passed DMARC because SPF passed, but ended up throwing a warning still.
TL;DR, you might not always have control over DKIM if you’re using a mailing list, but you want all of SPF, DKIM, and DMARC to pass. They don’t guarantee getting past a spam filter, but not passing might get you caught in the spam filter.
Once you’ve set up a soft-fail system, the next step is watching to see what happens.
DMARC has a mechanism for aggregate reports on the pass/fail results using the
However, these reports are annoying to read, so let’s use a free (as in cost) service to parse them and show us the results in an easy-to-read manner.
I’m currently trying out Valimail, which was the only free offering I found linked from the Microsoft Information Security Alliance website.
You’ll change your DMARC record to look like the following:
v=DMARC1; p=none; rua=mailto:[email protected];
Any mail servers that participate in DMARC aggregate reporting will send their reports to Valimail daily, which you can then see in the app (it’s also supposed to send a monthly summary, but I haven’t been using it long enough to test that yet). If you find anything that should be valid but is not passing DMARC, add the relevant SPF and DKIM records. Once the SPF and DKIM records exist, they should be passing.
Once all the services you want to have passing are passing, it’s time to move to the enforcement phase. This is where spam is actually blocked. To do this, we modify the SPF and DMARC policies to start failing (and thus start blocking) services which do not pass.
For SPF, change
~all (soft-fail; fail but do not block) to
-all (fail and block).
For DMARC, change
These are all public anyway, so here are the records for
ctmartin.me (formatted as
NAME TYPE VALUE with quotes added around TXT values and
@ representing the root):
selector1._domainkey CNAME selector1-ctmartin-me._domainkey.ctmartinme.onmicrosoft.com selector2._domainkey CNAME selector2-ctmartin-me._domainkey.ctmartinme.onmicrosoft.com @ TXT "v=spf1 include:spf.protection.outlook.com -all" _dmarc TXT "v=DMARC1; p=reject; rua=mailto:[email protected];"
In ISC BIND (RFC 1035) format these look like the following:
selector1._domainkey.ctmartin.me. 1 IN CNAME selector1-ctmartin-me._domainkey.ctmartinme.onmicrosoft.com. selector2._domainkey.ctmartin.me. 1 IN CNAME selector2-ctmartin-me._domainkey.ctmartinme.onmicrosoft.com. ctmartin.me. 1 IN TXT "v=spf1 include:spf.protection.outlook.com -all" _dmarc.ctmartin.me. 1 IN TXT "v=DMARC1; p=reject; rua=mailto:[email protected];"
If you don’t send email
Even if you aren’t sending emails it’s important to provide policies to disallow using your domain for email. Just because you aren’t using for email doesn’t mean spammers can’t impersonate it and get you on a blocklist.
To do this, don’t add any DKIM keys and add the following policies:
This says no IP Addresses are allowed to send emails for your domain, and any email that don’t pass (which will be all of them) should be rejected.