Fixing this for a Microsoft 365 domain

Two of the three records live in DNS rather than in Microsoft 365. Here's what goes where.

Worth knowing before you start: most of this is not done in Microsoft 365. Two of the three records live purely in DNS, wherever your nameservers point, which may be a completely different company. Only DKIM involves the Microsoft admin portal.

Where each change is made

  • SPF — a TXT record at your DNS provider. Nothing to do in Microsoft 365.
  • DMARC — a TXT record at your DNS provider. Nothing to do in Microsoft 365.
  • DKIM — Microsoft gives you two CNAME records rather than a TXT one. You publish those at your DNS provider, then go back to the admin portal to switch signing on.

The check tells you who hosts your DNS. It's often not the company you bought the domain from.

1. Turn on DKIM

In the Microsoft 365 Defender portal, open Email & collaboration → Policies & rules → Threat policies → Email authentication settings → DKIM, then select your domain. Microsoft shows you two CNAME records to publish. Copy those exact host and target values — do not reconstruct them by hand. Newer domains use a dkim.mail.microsoft target rather than the older onmicrosoft.com shape, and the two formats cannot coexist for the same selector.

Once both records are live, come back to the same screen and switch DKIM signing on for the domain.

It's first for a reason. When a message is forwarded on — by a role address like finance@ that points at whoever currently holds the job, or an old alumni address that redirects — SPF generally breaks, because the message now reaches the recipient from the forwarder's server rather than from Microsoft's, while a DKIM signature survives that trip intact. So DKIM is what keeps that mail passing once you tighten the policy, and a domain relying on SPF alone has nothing protecting it.

Mailing lists are the harder case, and DKIM does not rescue them: most lists add a footer or tag the subject, which invalidates the signature as well. That is why list software rewrites the From: header, and why the advice further down is to stop at quarantine.

2. Check SPF

A single TXT record at your domain root. If you already have one, edit it rather than adding a second — two SPF records break SPF entirely, and replacing an existing record wholesale drops whatever senders were already listed in it.

v=spf1 include:spf.protection.outlook.com ~all

Anything else that sends as your domain needs adding to this same record.

The record above ends ~all, which tells receivers that mail from anywhere unlisted is suspect without asking them to refuse it. There is a stricter ending, -all, which does ask them to refuse it.

~all is a perfectly reasonable place to stay. The reason is forwarding again: when a message is forwarded on, SPF fails because it now arrives from the forwarder's server, and a receiver can act on an SPF hard fail during delivery — before it ever looks at the DKIM signature that survived the trip. Those refusals don't appear in your DMARC reports either, so you wouldn't find out. With ~all that mail still gets through on DKIM, which is what you set up in step 1. Your protection against forgery comes from the DMARC policy below, and DMARC treats a soft fail and a hard fail identically.

-all is worth it if you are confident every legitimate sender is listed and nobody forwards your mail — a domain used only for bulk sending, say. It also takes effect the moment you publish it, with no monitoring stage of the kind DMARC gives you.

Microsoft's own documentation gives -all in its example while also describing ~all while you are still discovering senders. For a small organisation whose mail gets forwarded, staying on ~all is the safer of the two.

3. Add DMARC, then tighten it

TXT record with the host _dmarc:

v=DMARC1; p=none; rua=mailto:[email protected];

Use a mailbox that exists, or an address from a reporting service. On a domain with no DMARC policy in force, p=none changes nothing about delivery.

One thing to check before publishing it. If the check says this exact name is already inheriting quarantine or reject from a parent domain, then publishing a weaker policy here replaces that inherited protection — and you don't want this record. p=none turns it off entirely; p=quarantine weakens inherited reject. Inheriting a parent's p=none, or a parent whose sp= already sets none for its subdomains, is a different case — there is nothing to lose and the record is fine to add. Go by the effective policy the check reports for this name, not by what the parent's record says on its own.

Reports arrive only from receivers that choose to send them, and if the address is on someone else's domain that domain has to authorise it first — so a quiet period means "check the address" rather than "nobody is forging you". The ones that do arrive are zipped XML files built for software rather than people, so you'll need something to summarise them. See making DMARC reports readable.

Then, once the reports show every legitimate sender passing, move to p=quarantine. A short clean window can still miss senders that only go out quarterly or once a year — ask who uses the domain before you tighten.

Quarantine is the right place to stop for most organisations. The stricter p=reject refuses forged mail outright, but the current DMARC standard advises against it for ordinary organisations: a mailing list relays your message from its own servers while leaving your address in the From line, so genuine mail sent that way is refused too, and people can be dropped from the list without noticing.

If another organisation sends email as you

This is common where a management company or fiscal sponsor handles some of your mail. Their DKIM signs as their domain, which fails DMARC alignment even though their own setup is fine.

The fix is on their side: they add your domain to their tenant and publish DKIM records for it, so the signature carries your domain rather than theirs. Find those senders during the monitoring period — under p=quarantine their mail goes to spam, and under p=reject it is refused, until their DKIM is aligned to your domain.

Re-check your domain