If someone is sending email that appears to come from your domain, the fix is to publish SPF, turn on DKIM signing for your own domain, and move your DMARC policy to p=reject so receivers that enforce DMARC refuse the forged mail. Before you change anything, confirm that the mail really is forged: read the Authentication-Results header of a sample message. If it fails DMARC, it is spoofing; if it passes with your domain, it left your own systems and you have a different problem.
Who this is for and what you will have at the end
This guide is for owners and administrators of a small or mid-sized business who have received a report that fake invoices, payment requests or phishing messages are going out in the company's name. It assumes you manage DNS for the domain and, ideally, use Microsoft 365, although the DNS records apply to any mail provider.
At the end you will have:
- A way to tell forged mail from mail sent by your own accounts and apps.
- DMARC reports arriving in a mailbox you control, and a method for reading them.
- SPF, DKIM and DMARC records that tell receivers to reject mail that fails.
- Locked-down records for parked domains and subdomains that never send mail.
- A short list of what to do while you wait for the policy to take effect.
Why anyone can send mail as your domain
SMTP, the protocol behind internet email, doesn't validate that a sender is who they claim to be. A message carries two sender values. The MAIL FROM address (also called 5321.MailFrom, the envelope sender or Return-Path) is used between mail servers and for bounces. The From address (5322.From) is what the recipient sees in their mail app. They can be in different domains, and an attacker controls both.
Microsoft's documentation gives the classic example: the envelope sender is [email protected] while the visible From address is [email protected]. The transmission is valid SMTP, yet it deceives the recipient. SPF checks only the MAIL FROM domain, and DKIM checks only the domain that signed the message, so an attacker can pass both with a domain they own while showing yours in the From line. DMARC closes that gap by requiring that the domain SPF or DKIM validated aligns with the From domain, and by telling receivers what to do when it doesn't.
This means two things for you. You can't stop someone typing your address into a From field. You can make every receiver that honors DMARC reject the message, and you can see how much of it is happening.
Step 1: Confirm it is spoofing and not a compromised account
Ask the person who received the message to send it to you as an attachment, or to copy the full headers. Outlook's menu paths for viewing headers are on Microsoft's support page, "View internet message headers in Outlook", linked in the references. Paste the headers into Microsoft's Message Header Analyzer if you want them parsed.
Find the Authentication-Results header. The three fields that matter are smtp.mailfrom= (the envelope domain SPF checked), header.d= (the domain that signed the message with DKIM) and header.from= (the visible From domain).
Microsoft's DMARC troubleshooting page shows this header, from a message where SPF and DKIM pass individually but neither aligns with the From address:
Authentication-Results: spf=pass (sender IP is 198.51.100.10)
smtp.mailfrom=bounces.adatum.com; dkim=pass (signature was verified)
header.d=adatum.com; dmarc=fail action=oreject
header.from=contoso.com;compauth=fail reason=000That is documented output from learn.microsoft.com, not output from your tenant. Read it like this: header.from=contoso.com is the forged domain, while smtp.mailfrom and header.d belong to a different domain, so dmarc=fail.
Use the result to decide what you are dealing with:
| What the header shows | Most likely cause | Next step |
|---|---|---|
dmarc=fail, smtp.mailfrom and header.d in someone else's domain | Spoofing from outside | Continue with steps 2 to 6 |
SPF or DKIM passes and the domain is yours (for example header.d=contoso.com, dmarc=pass) | Mail left a system you authorize: a compromised mailbox, a stolen app credential or a forgotten sender | Treat as an account incident: reset passwords, enforce MFA, review the sending system |
dmarc=bestguesspass or dmarc=none | You have no DMARC record at all | Publish one in step 3 |
spf=fail with -all, but the message was still delivered | The receiver doesn't enforce, or DMARC isn't set | Publish DMARC; enforcement depends on the receiver |
The second row is an inference from how alignment works rather than a rule Microsoft states in one sentence: a message aligned with your domain by SPF or DKIM can only have been sent by a source that SPF authorizes or that holds your DKIM key. If that describes your spam, tighten account security first. The small business MFA rollout checklist covers that side.
Step 2: Check what your domain publishes today
Before you change records, look at what exists. In PowerShell, Resolve-DnsName (also used in Microsoft's own troubleshooting page) shows the DMARC record:
Resolve-DnsName -Name "_dmarc.contoso.com" -Type TXT | Select-Object -ExpandProperty StringsCheck the SPF record the same way, against the domain itself:
Resolve-DnsName -Name "contoso.com" -Type TXT | Select-Object -ExpandProperty StringsYou are looking for three things. A single record starting v=spf1, because two SPF records cause permerror. A _dmarc TXT record starting v=DMARC1;, and its p= value. And whether the SPF record ends in -all. If no _dmarc record exists, Microsoft 365 reports dmarc=bestguesspass or dmarc=none for your mail when it receives it, and nobody is told to reject forgeries.
If you use Microsoft 365, you can also check DKIM:
Get-DkimSigningConfig | Format-List Domain, Enabled, Selector1CNAME, Selector2CNAMEEnabled should be True for your custom domain. The full procedure for publishing the CNAME records and enabling signing is in SPF, DKIM and DMARC for Microsoft 365, so this article doesn't repeat it.
Step 3: Publish DMARC at p=none with reporting
Don't jump to p=reject yet. If a legitimate sender such as a billing tool or newsletter service isn't aligned, p=reject makes receivers refuse your real mail. Start with monitoring, which also gives you evidence of how much forged mail exists.
First create a place for reports. Microsoft recommends a dedicated mailbox or a Microsoft 365 Group, not a person's inbox, and says to start with rua only because forensic (ruf) reports can be high volume. Then add one TXT record at your DNS host:
Hostname: _dmarc
Type: TXT
Value: v=DMARC1; p=none; pct=100; rua=mailto:[email protected]Microsoft's rollout example uses the same structure, with rua and ruf addresses. A few details from the documentation:
- The hostname
_dmarcis required, and there must be only one_dmarcTXT record. p=nonetakes no action on failing mail but still produces reports.pctdefaults to 100 if you leave it out.- Aggregate reports are typically sent once a day and describe the previous day.
- If the report address is in a different domain from the one you're monitoring, that other domain must publish a TXT record named
contoso.com._report._dmarcwith the valuev=DMARC1;. Without it receivers don't deliver the reports. - Microsoft 365 doesn't send forensic reports even if your record has a
rufaddress, so other providers' reports are the only source.
The reports are XML, often compressed. You can read them by hand while the volume is small, or use a DMARC reporting service listed in the Microsoft Intelligent Security Association catalog.
Step 4: Read the aggregate reports
Give the record at least a few days so that receivers send their summaries. Then look at each <record> in the XML. Microsoft's page explains the fields that matter:
| Element | What it tells you |
|---|---|
<source_ip> | The server that sent mail using your domain |
<count> | How many messages came from that IP |
<disposition> | What the receiver did: none, quarantine or reject |
<dkim> and <spf> under <policy_evaluated> | Whether DKIM or SPF aligned with your From domain |
<domain> under <auth_results> | The domain SPF or DKIM actually validated |
Sort the sources into three groups:
- Known and aligned. Your Microsoft 365 tenant, with SPF aligned. Healthy; no action.
- Known but not aligned. A legitimate service where authentication passes but alignment fails. The page's example: SPF
passinauth_resultsbutfailinpolicy_evaluated. The service uses its own domain in MAIL FROM or signs with its own domain. Fix it at the service: have it sign DKIM with your domain, or change its MAIL FROM to your domain or a subdomain. - Unknown, high volume, everything failing. Microsoft's table describes this pattern as a potential spoofing or phishing campaign and says no action is needed because your DMARC policy protects recipients once it is enforced. This is the group you are trying to stop.
Don't skip group 2. Every legitimate sender you leave unaligned becomes a bounce the day you reach p=reject. Common examples named in Microsoft's table are services that use their own MAIL FROM, forwarded mail and mailing lists. Forwarding is the exception: it breaks SPF and can break DKIM when the body changes, so a share of failures from forwarders is normal.
Step 5: Fix SPF and DKIM for the legitimate senders
For each legitimate sender from group 2, use the vendor's documentation to find its include: value or its DKIM setup. For Microsoft 365 as the only sender, Microsoft's documented SPF record is:
v=spf1 include:spf.protection.outlook.com -allFor a domain with an on-premises server and a bulk mailer on a subdomain, the same page gives:
contoso.com TXT v=spf1 ip4:192.168.0.10 include:spf.protection.outlook.com -all
marketing.contoso.com TXT v=spf1 include:servers.adatum.com include:spf.protection.outlook.com -allKeep these rules in mind:
- One SPF record per domain or subdomain.
- Fewer than 10 DNS lookups.
include,a,mx,existsandredirecteach count, and so do nested includes;ip4,ip6andalldon't. If you exceed the limit, see fixing an SPF record that is too long. - Use
-all. Microsoft notes that DMARC treats-alland~allboth as SPF failures, but a~allfailure is effectively ignored by DMARC when the message has no DKIM signature. - Put services you don't control, such as bulk mail platforms, on a subdomain. Each subdomain needs its own SPF record and DKIM setup, because unlike DMARC they don't inherit from the parent.
After each change, watch the next day's reports and confirm that the sender moved from group 2 to group 1.
Step 6: Move to quarantine, then reject
Once the legitimate senders are aligned and the only failing traffic is unknown sources, tighten the policy in stages. Microsoft's recommended order is p=none, then p=quarantine, then p=reject, starting with a subdomain that has low mail volume and saving the parent domain for last. You can step pct through 10, 25, 50, 75 and 100 to limit the share of failing mail that gets the policy at first.
Hostname: _dmarc
Type: TXT
Value: v=DMARC1; p=quarantine; pct=25; rua=mailto:[email protected]When the reports stay clean at 100, finish with:
Hostname: _dmarc
Type: TXT
Value: v=DMARC1; p=reject; pct=100; rua=mailto:[email protected]What "reject" means depends on the receiver. Microsoft's page says the messages are typically discarded, and that a Microsoft 365 recipient with Honor DMARC record policy turned on rejects a failing message during SMTP with 550 5.7.1 and stamps dmarc=fail action=oreject. With p=quarantine, the message goes to Junk Email by default. Other providers make their own decisions, which is why DMARC lowers the volume of spoofing instead of removing it.
One side effect to know about: outbound mail from a Microsoft 365 domain that fails DMARC at the destination is routed through the high-risk delivery pool if your policy is p=quarantine or p=reject, and there is no override. Align your senders first, so that doesn't catch legitimate mail.
Step 7: Lock down domains and subdomains that don't send mail
Attackers don't need your main domain. Old domains, typo-protection domains and unused subdomains are all usable for forgeries if nothing is published. For a registered domain that sends no mail, Microsoft documents two records:
Hostname: @ (contoso.net)
Type: TXT
Value: v=spf1 -all
Hostname: _dmarc (contoso.net)
Type: TXT
Value: v=DMARC1; p=reject;The pct, rua and ruf values are arguably unnecessary here because no valid mail should come from the domain. Microsoft's note also applies to your *.onmicrosoft.com domain: if you don't use it for email, add a DMARC record for it, which you do in the Microsoft 365 admin center under Settings > Domains, then the DNS records tab and Add record, with the TXT name _dmarc and the value v=DMARC1; p=reject. DMARC on your main domain also covers subdomains that have no record of their own, including ones that don't exist, unless a subdomain publishes its own _dmarc record.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
dmarc=fail but SPF and DKIM both pass | Neither domain aligns with the From address | Make the service sign with your domain or use your domain in MAIL FROM |
dmarc=temperror or dmarc=permerror | DNS timeout, or a DMARC record with a syntax error | Check syntax with Resolve-DnsName, and keep exactly one _dmarc TXT record |
| No reports arrive | Wrong rua address, or external report address without the _report._dmarc record | Fix the address or publish contoso.com._report._dmarc in the receiving domain |
Legitimate mail from a vendor is rejected after p=reject | The vendor isn't aligned | Add its DKIM signing with your domain; move it to a subdomain |
| Forwarded messages fail | Forwarding breaks SPF; body changes can break DKIM | Expect some failures; the receiving side can use trusted ARC sealers |
| You still see forged mail in some inboxes | The receiving provider doesn't enforce DMARC, or you're still at p=none | Confirm the published policy; enforcement is the receiver's decision |
If the spoofed mail targets your own users, a Microsoft 365 tenant can also deal with inbound forgeries of your domain. The Tenant Allow/Block List guide explains the spoofed sender entries, and Microsoft documents the anti-phishing setting Honor DMARC record policy when the message is detected as spoof.
What to do while you wait
DNS changes and receivers' enforcement take time, and DMARC doesn't recall mail that was already sent. In the meantime:
- Tell customers and staff that you will never change bank details by email, and agree how payment changes are verified, for example by calling a known number.
- Report the phishing to the people it targeted, so they can block it on their side.
- Keep the sample headers and message copies so you can show which domain and IP the mail came from.
Checklist
- Read the
Authentication-Resultsheader of a sample message and decide spoofing or compromised account. - Check that exactly one SPF record and a
_dmarcrecord exist. - Publish
v=DMARC1; p=none; rua=...and confirm reports arrive. - Sort the aggregate report sources and align every legitimate sender.
- Move to
p=quarantine, thenp=reject, usingpctsteps, subdomains first. - Publish
v=spf1 -allandp=rejectfor parked domains. - Review reports weekly at first and monthly once stable.
What we checked
- Opened "Set up DMARC to validate email in Microsoft 365" on learn.microsoft.com on 2026-11-12 (page dated 2026-07-03): the record syntax,
p=none/quarantine/rejectrollout order, thepctsteps 10, 25, 50, 75 and 100, and the parked-domain recordv=DMARC1; p=reject;. - Opened the SPF configuration page on 2026-11-12 and confirmed the Microsoft 365 record
v=spf1 include:spf.protection.outlook.com -all, the parked-domain recordv=spf1 -all, and the 10-lookup rules. - Cross-checked the
Authentication-Resultsfields (smtp.mailfrom,header.d,header.from,dmarc,action) between the DMARC page and the "Anti-spam message headers" page; both describedmarc=fail action=orejectthe same way. - Documented output: the sample
Authentication-Resultsheader in step 1 is quoted from Microsoft's DMARC troubleshooting section, withcompauth=fail reason=000. The reason code table on the headers page defines 000 as a DMARC fail where the sender's policy isp=quarantineorp=reject. - Confirmed on the DMARC page that Microsoft 365 doesn't send forensic reports and that cross-domain report addresses need a
_report._dmarcTXT record. - Not checked hands-on: we did not run any command or change DNS on a live tenant or domain, and the second row of the step 1 table is our own reading of how alignment works. Steps follow Microsoft's documentation as of 2026-11-12.
Last tested: 2026-11-12
References
- Set up DMARC to validate email in Microsoft 365: https://learn.microsoft.com/en-us/defender-office-365/email-authentication-dmarc-configure
- Set up SPF to identify valid email sources: https://learn.microsoft.com/en-us/defender-office-365/email-authentication-spf-configure
- How email authentication works in Microsoft 365: https://learn.microsoft.com/en-us/defender-office-365/email-authentication-about
- Anti-spam message headers (Authentication-Results and compauth reason codes): https://learn.microsoft.com/en-us/defender-office-365/message-headers-eop-mdo
- View internet message headers in Outlook: https://support.microsoft.com/office/cd039382-dc6e-4264-ac74-c048563d212c
Comments
Questions and tips are welcome. Comments are checked by the EpiFive team before they appear; please do not share passwords, phone numbers or other private details.