Skip to content

6.2SPF, DKIM and DMARC

These three records protect your email. They help other mail servers decide if an email from your domain is genuine. If one breaks, your email can go to spam or be rejected.

  • SPF (Sender Policy Framework) is the TXT record that lists which servers may send email for your domain.
  • DKIM (DomainKeys Identified Mail) is a public key in DNS. Receivers use it to check your email's signature.
  • DMARC is the TXT record at _dmarc.<domain>. It tells receivers what to do with email that fails the checks.

Choose SPF, DKIM or DMARC as the record type. The form changes to match:

Record typeField labelWhat to enter
SPFdomainThe domain you send email from, such as acme.io.
DKIMkey nameThe key's full name, <selector>._domainkey.<domain>, such as google._domainkey.acme.io.
DMARCdomainYour domain, such as acme.io. obsrvly reads _dmarc.acme.io. You can also enter _dmarc.acme.io yourself.

In the API, the field is always domain, also for DKIM.

Expected values for mail checks#

Here expected values are optional. They work differently from 6.1:

  • Every expected value must be in the record, not just one.
  • Each value can be the whole record, or one of its parts (terms), such as -all, include:_spf.google.com or p=reject.
  • Upper and lower case do not matter. Extra spaces do not matter, so p=reject also matches p = reject;.

The dashboard says: "optional — each must stay in the record, as the whole record or one of its terms; alerts when one goes".

When an expected value goes missing, the check is down. The message shows the record as it is now:

SPF changed: expected "-all",
record is now "v=spf1 include:_spf.google.com ~all"

These messages can appear for all three types. <kind> is SPF, DKIM or DMARC, and <name> is the name obsrvly read:

MessageWhat to do
<kind>: no record at <name>Publish the record at your DNS provider.
<kind>: <n> records at <name>; there must be exactly one, so receivers ignore them allMerge the records into one.
<kind> <name>: <lookup error>Check the name and your DNS provider.
<kind> changed: expected "<value>", record is now "<record>"Restore the record. If you changed it on purpose, update the expected value.

SPF#

The form hint says: "Down if there is no SPF record, more than one, one ending in +all, or one needing over 10 DNS lookups."

An SPF record is a list of terms. Two kinds matter most:

  • include: adds another provider's list of servers. For example, include:_spf.google.com allows Google's mail servers.
  • The all term at the end covers every other server. -all, ~all and ?all pass. all or +all fails, because it lets any server send email as you.

A record counts as SPF only if it starts with v=spf1 followed by a space or nothing. So v=spf10 ... is not an SPF record.

An SPF record may need at most 10 DNS lookups. The terms include:, a, mx, ptr, exists and redirect= each count. Terms inside included records count too.

The check is down when…Message
The record ends in all or +all.SPF: ends in +all, which lets any server send as acme.io
The record needs more than 10 DNS lookups.SPF: needs 12 DNS lookups, over the limit of 10, so receivers treat it as an error
An included record points back to one already included.SPF: include:<target> loops back to a record already included
An included record is missing or there are two of them.SPF: include:<target> is broken: <message>

The same two messages appear with redirect: in place of include:.

Good expected values: -all or ~all, plus any include: you rely on.

DKIM#

The key's name is made of a selector and your domain: <selector>._domainkey.<domain>. The selector is a short label, such as google. Your email provider gives it to you.

The form hint says: "<selector>._domainkey.<domain>. Down if the key is missing, revoked or malformed."

ProblemMessage
The name is not a key name. You cannot save the monitor.a DKIM monitor's domain is the key's name, <selector>._domainkey.<domain>
No key is published (no TXT record with a p= term).DKIM: no key at google._domainkey.acme.io
The key is revoked (the p= term is empty).DKIM: the key at <name> is revoked (empty p=)
The key is not valid base64 text.DKIM: the key at <name> is not valid base64, so no signature can verify

Good expected values: k=rsa, or the full p= term if you want to know when the key changes.

DMARC#

The form hint says: "Reads _dmarc.<domain>. Down if there is no record or no valid p= policy." A record counts as DMARC only if it starts with v=DMARC1 followed by ; or nothing.

The check is down when…Message
There is no p= policy.DMARC: no p= policy in "<record>", so receivers ignore the record
The policy is not none, quarantine or reject.DMARC: p=<value> is not a policy; it must be none, quarantine or reject
Create a DMARC monitor (uses SVC and OBSRVLY_KEY from the first example)
bash
curl -s $SVC/CreateDnsMonitor \
  -H "Authorization: Bearer $OBSRVLY_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "DMARC acme.io", "domain": "acme.io",
       "recordType": "DMARC",
       "expectedValues": ["p=reject"],
       "intervalSeconds": 3600}'

Last updated