The basic record
If only Exchange Online sends for the domain, the SPF record consists of a single include. spf.protection.outlook.com covers all Microsoft outbound servers, and Microsoft maintains the addresses behind it. The record is published as a TXT record at the apex of the domain, that is on example.com and not on a subdomain.
Microsoft suggests exactly this record in the admin center. Make sure you enter it without quotation marks in the panel if your DNS provider adds the quotes itself.
example.com. IN TXT "v=spf1 include:spf.protection.outlook.com -all"Combining other senders
Hardly any client sends only through Exchange Online. Newsletter tool, CRM, ticket system, web shop and the website itself also send on behalf of the domain. All of these services go into the same record, because a domain may have only one SPF record. The Microsoft include costs two DNS lookups, which leaves eight for everything else.
The web server is a case that is typically forgotten: contact forms and shop order confirmations often go straight out from the server. Add its fixed IP address via ip4 or switch the system to SMTP delivery through a service that has an include.
v=spf1 include:spf.protection.outlook.com include:servers.mcsv.net ip4:203.0.113.25 -allMistake 1: The old record is still there
When moving from a hosting provider to Microsoft 365, a new TXT record is often created instead of replacing the existing one. Two records with v=spf1 are a permerror according to RFC 7208, and the receiver treats the domain as having no SPF. The SPF checker shows you immediately whether more than one record exists.
After every migration, check all TXT records at the apex and delete the old one. If the old provider still sends for individual systems, its include belongs in the new record, not in a second one.
Mistake 2: ~all forever
Many guides recommend ~all (softfail) as a starting point so nothing gets lost during the migration. That is sensible, but only as an intermediate step. If the ~all stays, forged messages only get a mild spam signal attached, and the protective effect is small.
Once the DMARC reports have shown for a few weeks that all legitimate senders are in the record, switch to -all. Combined with DMARC p=reject, -all is the configuration that really protects a domain against spoofing.
Mistake 3: Forgetting printers, scanners and relays
The classic after a migration: the multifunction printer in the office sends scans by mail, the ERP system sends invoices, the UPS reports power failures. These devices have two ways into Microsoft 365. With SMTP AUTH client submission via smtp.office365.com and a mailbox login, the messages leave through Exchange Online and are covered by the include.
With so called direct send, the device delivers straight to the tenant's MX endpoint without authentication. The message then comes from the public IP of the client's site, and exactly that IP must be in the SPF record via ip4, otherwise the result is fail. Ask the client specifically about such devices, because in DMARC reports they show up as anonymous sources with a handful of messages per week.
v=spf1 include:spf.protection.outlook.com ip4:198.51.100.14 -all
198.51.100.14 is the fixed public IP of the office from which printers and the ERP system deliver via direct send.Hybrid and on premises relays
In hybrid environments some mailboxes still send through the local Exchange server, or a smart host in the data centre relays mail from business applications to the outside. Every one of these servers that delivers directly to external recipients needs its public IP in the SPF record. If it sends exclusively through the outbound connector to Exchange Online, the include is sufficient.
Document the IPs in the record with a short note in the client's ticket system. Otherwise nobody will know in two years what 203.0.113.40 was for, and it gets removed at the next cleanup.
Adding DKIM and DMARC
SPF alone is not enough, because it breaks on forwarding and because DMARC alignment with many services is only achievable through DKIM. Microsoft 365 signs with two selectors, selector1 and selector2, which you point to the tenant as CNAME records. After that you enable DKIM for the domain in the Defender portal.
The target hostname follows the pattern selector1-<domain-with-hyphens>._domainkey.<tenant>.onmicrosoft.com. The portal shows the exact value, so copy it rather than typing it. Then add the DMARC record, first with p=none and a rua address so you receive reports.
selector1._domainkey.example.com. CNAME selector1-example-com._domainkey.clienttenant.onmicrosoft.com.
selector2._domainkey.example.com. CNAME selector2-example-com._domainkey.clienttenant.onmicrosoft.com.
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com"How Exchange Online handles SPF failures on inbound mail
On the receiving side, Exchange Online Protection evaluates SPF, DKIM and DMARC and summarises the result in the Authentication-Results header, complemented by its own composite verdict (compauth). An SPF fail alone does not automatically send a message to the junk folder; the decision depends on the DMARC policy, the anti phishing policy and further signals. The anti spam policy also has an option to mark SPF hard fail separately.
For you as the person looking after the sending domain this means: the Authentication-Results header of a test message sent to a Microsoft mailbox is the most reliable source for whether your setup works. It shows spf=pass, dkim=pass and dmarc=pass, or it does not.
Frequently asked questions
- Do I need to maintain SPF for the onmicrosoft.com domain as well?
- No. The tenant domain belongs to Microsoft, and its SPF record is preconfigured. You only take care of the custom domains you added to the tenant.
- Is the include enough if we send through a third party filter?
- Not necessarily. If outbound mail passes through a security gateway such as Proofpoint or Mimecast, receivers see the gateway's IP addresses. Then the gateway's include must be in the record; you can often keep the Microsoft include as well in case individual system messages go out directly.
- What about mail from Power Automate or SharePoint?
- Notifications from Microsoft services usually come from Microsoft owned domains, not from yours. Only if you send flows with the "Office 365 Outlook" connector from a mailbox in your domain do they pass through Exchange Online and fall under the include.