Type to search 66 articles.

    Practical engineering guidance

    SPF, DKIM and DMARC as an operational sequence

    Three DNS records that only work in a specific order. Publishing a strict DMARC policy before the inventory is complete is how organisations stop their own invoices arriving.

    Series: Exchange and Microsoft 365

    • Exchange Online
    • Email authentication
    • DNS

    Email authentication is three records that answer three different questions, and they only produce a useful result when combined in the right order. Almost every failure I have seen came from doing them in the wrong one — usually publishing a rejecting DMARC policy before knowing who legitimately sends as the domain.

    The order matters more than the syntax, so this article is organised around the sequence.

    Requirements: what each record actually does

    SPF answers: is this server allowed to send for this domain? It is a TXT record listing authorised sending sources, checked against the envelope sender — the 5321.MailFrom address, not the address the recipient sees.

    DKIM answers: was this message signed by the domain, and is it unmodified? The sending system signs headers and body with a private key; the public key is published in DNS under a selector. A valid signature proves origin and integrity, and unlike SPF it survives a straightforward forward.

    DMARC answers: what should the recipient do when the visible From address is not backed up by an aligned, passing SPF or DKIM result? It is the policy layer, and it is the only one of the three that protects the address users actually see — the 5322.From header.

    That last distinction is the point of the whole exercise. SPF and DKIM on their own validate things the recipient never looks at. DMARC ties them to the visible sender through alignment:

    • DMARC passes via SPF when the 5321.MailFrom domain aligns with the 5322.From domain.
    • DMARC passes via DKIM when the DKIM signing domain aligns with the 5322.From domain.

    Only one needs to pass. But alignment is required, which is why a domain with a passing SPF record can still fail DMARC — the sending service authenticated its own domain, not yours.

    Step one: the inventory, which is the actual work

    Before publishing anything, list every system that sends email using your domain in the visible From address. This is where the project succeeds or fails, and it always takes longer than the DNS work.

    The list normally includes, and is rarely limited to:

    • Microsoft 365 itself.
    • Marketing and newsletter platforms.
    • The finance system sending invoices and remittances.
    • The HR and payroll systems.
    • Ticketing and service desk tools.
    • Monitoring and alerting systems.
    • Multifunction devices that scan to email.
    • Applications relaying through an on-premises Exchange server.
    • Anything a department signed up for without telling you.

    That last category is why the inventory cannot be built from a document. It has to be built from evidence, and DMARC’s own reporting is the best source of it — which is why the sequence starts with a monitoring-only policy rather than ending with one.

    Step two: SPF, published carefully

    Publish one SPF record per domain. Exactly one — multiple SPF TXT records is a permanent error condition, not a merge.

    v=spf1 include:spf.protection.outlook.com include:_spf.example-service.com -all

    Two constraints decide most SPF problems:

    The ten DNS lookup limit. Each include, a, mx, ptr and exists mechanism costs lookups, and nested includes count too. Exceed ten and the evaluation returns a permanent error, which typically means DMARC cannot pass via SPF at all. Large organisations hit this routinely, and the answer is consolidation or an SPF flattening service — not another include.

    The final mechanism. -all is a hard fail; ~all is a soft fail. Start with ~all while you are still discovering senders, and move to -all once the inventory is stable. Going straight to -all on an incomplete inventory produces exactly the outage this article exists to prevent.

    SPF does not survive most forwarding, because the forwarding server becomes the sender. That is not a fault in your configuration — it is why DKIM matters.

    Step three: DKIM, enabled and rotated

    For Microsoft 365, enable DKIM signing per custom domain and publish the two CNAME records for selector1 and selector2. The two selectors exist so that key rotation can happen without an interruption: signing moves between them.

    Points worth attention:

    • Enable it for every custom domain you send from, not just the primary. An unsigned subdomain is a gap.
    • Third-party senders need their own DKIM setup, signing with your domain. A service that signs with its own domain gives you nothing for DMARC alignment, and this is the most common reason a well-configured domain still fails DMARC for one particular sender.
    • Rotate keys. Microsoft 365 handles rotation for its own signing; anything you operate yourself needs a rotation schedule with an owner.

    Step four: DMARC, in three stages

    This is the part that must be staged. Publish at _dmarc.contoso.com.

    Stage one — monitor. Publish p=none with an aggregate reporting address:

    v=DMARC1; p=none; rua=mailto:dmarc-reports@contoso.com; fo=1

    p=none asks recipients to take no action and send reports. Nothing changes for your mail flow, and within days you begin receiving aggregate reports naming every source sending as your domain. This is how the inventory gets completed.

    Use a dedicated mailbox or a reporting service. Raw aggregate reports are XML, and at any scale they need parsing rather than reading.

    Stage two — quarantine, with a percentage. Once the reports show your legitimate senders authenticating and aligning, move to quarantine — and use pct to phase it:

    v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc-reports@contoso.com

    Raise the percentage as confidence grows. Watch the reports at each step, not just the service desk.

    Stage three — reject. Only when the reports are clean:

    v=DMARC1; p=reject; rua=mailto:dmarc-reports@contoso.com

    Consider sp= for subdomain policy, and publish a restrictive record on domains you own but never send from — a parked domain with p=reject and an SPF record of v=spf1 -all is a cheap, complete win.

    Why this is no longer optional

    The large consumer mail providers now require authentication from high-volume senders rather than merely preferring it. Microsoft defines a high-volume sender as one sending 5,000 or more messages to its consumer mail services using the same domain in the 5322.From address, and requires SPF, DKIM and a valid DMARC record for those domains.

    Two details in that requirement catch people out:

    • The threshold is sticky. Once a domain has crossed it, the requirements apply even if the daily volume later falls below 5,000.
    • Enforcement is per message. An individual message that does not meet the requirements can be rejected even though other messages from the same domain pass.

    Confirm the current thresholds and requirements at the time you plan the work — this is an area the providers have been changing.

    Validation

    Check the records resolve and parse before trusting them:

    Resolve-DnsName -Type TXT -Name contoso.com
    Resolve-DnsName -Type TXT -Name _dmarc.contoso.com
    Resolve-DnsName -Type CNAME -Name selector1._domainkey.contoso.com

    Then validate behaviour rather than syntax:

    • Send from each inventoried system to a mailbox you control at a different provider, and read the authentication results in the message headers. spf=pass, dkim=pass and dmarc=pass — and check that DMARC passed through alignment, not that SPF merely passed.
    • Read the aggregate reports for at least a full month before tightening the policy. Monthly processes send email too.
    • Confirm your SPF record is under the lookup limit using a checker, and re-check after any vendor change — a provider altering their own include can push you over without you touching your record.

    Where a message failed, the trace and the headers together give the answer. The approach in tracing a message through Exchange Online mail flow covers the Exchange Online side.

    Operations

    Forwarding will break SPF, and sometimes DKIM. Mailing lists that modify subject lines or add footers break DKIM signatures. ARC exists to let a trusted forwarder assert the original authentication result, and Microsoft 365 lets you designate trusted ARC sealers. Configure this where you have a legitimate forwarding relationship rather than weakening the policy.

    Every new sending service is a change to this configuration. Put email authentication on the checklist for onboarding any service that will send as your domain. Without that, the inventory decays and someone eventually publishes a service that is rejected on day one.

    Keep reading the reports after reaching p=reject. They are how you notice both a legitimate sender breaking and somebody attempting to spoof you.

    Rollback

    Each stage is reversible by editing one TXT record, subject to DNS time-to-live. Keep the TTL low while you are moving through the stages so a rollback takes minutes rather than hours, and raise it once the policy is stable.

    The irreversible part is the mail that was rejected while a policy was too strict. That is the argument for the staged sequence and for pct, and it is the reason I would never move a production domain straight to p=reject.

    Verification and limits

    SPF mechanics including the ten-lookup limit, DKIM selector-based rotation in Microsoft 365, DMARC policy values and alignment rules, and Microsoft’s high-volume sender requirements — including the 5,000-message definition, the sticky threshold and per-message enforcement — were checked against current Microsoft documentation on 20 September 2026.

    No records were published or tested for this article. DNS changes to these records affect whether your email is delivered: stage the DMARC policy, keep TTLs low during the transition, and complete the sender inventory through p=none reporting before tightening anything.

    References