Security & identity

Someone is sending email from your domain: how to stop it with DMARC

Confirm whether your domain is being spoofed or your account is compromised, read the evidence in headers and DMARC reports, then lock the domain down with SPF, DKIM and DMARC p=reject.

By EpiFive Editorial TeamReviewed/updated 14 min readHow we check articles
On this page

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=000

That 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 showsMost likely causeNext step
dmarc=fail, smtp.mailfrom and header.d in someone else's domainSpoofing from outsideContinue 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 senderTreat as an account incident: reset passwords, enforce MFA, review the sending system
dmarc=bestguesspass or dmarc=noneYou have no DMARC record at allPublish one in step 3
spf=fail with -all, but the message was still deliveredThe receiver doesn't enforce, or DMARC isn't setPublish 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 Strings

Check the SPF record the same way, against the domain itself:

Resolve-DnsName -Name "contoso.com" -Type TXT | Select-Object -ExpandProperty Strings

You 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, Selector2CNAME

Enabled 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 _dmarc is required, and there must be only one _dmarc TXT record.
  • p=none takes no action on failing mail but still produces reports.
  • pct defaults 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._dmarc with the value v=DMARC1;. Without it receivers don't deliver the reports.
  • Microsoft 365 doesn't send forensic reports even if your record has a ruf address, 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:

ElementWhat 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:

  1. Known and aligned. Your Microsoft 365 tenant, with SPF aligned. Healthy; no action.
  2. Known but not aligned. A legitimate service where authentication passes but alignment fails. The page's example: SPF pass in auth_results but fail in policy_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.
  3. 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 -all

For 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 -all

Keep these rules in mind:

  • One SPF record per domain or subdomain.
  • Fewer than 10 DNS lookups. include, a, mx, exists and redirect each count, and so do nested includes; ip4, ip6 and all don't. If you exceed the limit, see fixing an SPF record that is too long.
  • Use -all. Microsoft notes that DMARC treats -all and ~all both as SPF failures, but a ~all failure 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

SymptomLikely causeFix
dmarc=fail but SPF and DKIM both passNeither domain aligns with the From addressMake the service sign with your domain or use your domain in MAIL FROM
dmarc=temperror or dmarc=permerrorDNS timeout, or a DMARC record with a syntax errorCheck syntax with Resolve-DnsName, and keep exactly one _dmarc TXT record
No reports arriveWrong rua address, or external report address without the _report._dmarc recordFix the address or publish contoso.com._report._dmarc in the receiving domain
Legitimate mail from a vendor is rejected after p=rejectThe vendor isn't alignedAdd its DKIM signing with your domain; move it to a subdomain
Forwarded messages failForwarding breaks SPF; body changes can break DKIMExpect some failures; the receiving side can use trusted ARC sealers
You still see forged mail in some inboxesThe receiving provider doesn't enforce DMARC, or you're still at p=noneConfirm 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-Results header of a sample message and decide spoofing or compromised account.
  • Check that exactly one SPF record and a _dmarc record 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, then p=reject, using pct steps, subdomains first.
  • Publish v=spf1 -all and p=reject for 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/reject rollout order, the pct steps 10, 25, 50, 75 and 100, and the parked-domain record v=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 record v=spf1 -all, and the 10-lookup rules.
  • Cross-checked the Authentication-Results fields (smtp.mailfrom, header.d, header.from, dmarc, action) between the DMARC page and the "Anti-spam message headers" page; both describe dmarc=fail action=oreject the same way.
  • Documented output: the sample Authentication-Results header in step 1 is quoted from Microsoft's DMARC troubleshooting section, with compauth=fail reason=000. The reason code table on the headers page defines 000 as a DMARC fail where the sender's policy is p=quarantine or p=reject.
  • Confirmed on the DMARC page that Microsoft 365 doesn't send forensic reports and that cross-domain report addresses need a _report._dmarc TXT 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

Questions people ask

Can I stop someone from sending email that appears to come from my domain?

You can't stop a stranger from typing your address in the From field, because SMTP doesn't check it. You can make receivers reject those messages by publishing SPF, DKIM signing and a DMARC record with p=reject. Receivers that honor DMARC then reject or junk mail that fails authentication and alignment.

How do I tell spoofing from a hacked mailbox?

Open the full message headers and read the Authentication-Results header. A spoofed message normally fails DMARC because neither SPF nor DKIM aligns with your From domain. A message that really left your tenant passes SPF or DKIM with your domain, so it points to a compromised account, a misconfigured app or an authorized sender that needs review.

Will DMARC p=reject block my own legitimate email?

It can, if a legitimate sender such as a newsletter tool, scanner or billing system doesn't pass SPF or DKIM with your domain. That is why Microsoft recommends starting at p=none, reading aggregate reports, then moving to p=quarantine and p=reject in steps, using pct to limit the share of failing mail at first.

Why am I not getting DMARC reports?

Check that the rua address is spelled correctly and the mailbox exists. If the report address is in a different domain, that domain must publish a TXT record at contoso.com._report._dmarc with the value v=DMARC1; or receivers won't deliver reports. Reports are typically sent once a day, and not every receiver sends them.

DMARCSPFDKIMMicrosoft 365Exchange Online
  1. Block legacy authentication in Microsoft 365 without breaking printers

    Find every device and app that still signs in with legacy authentication, move printers and scanners to a supported sending method, then block legacy auth with Conditional Access.

  2. Find and remove malicious inbox and forwarding rules after a BEC

    After a compromised mailbox, find hidden inbox rules, SMTP forwarding and delegate access in Exchange Online, remove them safely and block external auto-forwarding so the attacker can't come back.

  3. A Microsoft 365 tenant security baseline you can apply in a day

    Harden a new or existing Microsoft 365 tenant in one working day: emergency access, admin roles, MFA and legacy auth, app consent, email protection, external forwarding, audit logging and Secure Score.

  4. Build Purview DLP policies for Exchange, SharePoint, Teams and devices

    Step-by-step Microsoft Purview DLP setup that stops card numbers and PII leaking through email, SharePoint, OneDrive, Teams chat and Windows or macOS devices, with a safe simulation rollout.

  5. Compromised Microsoft 365 account runbook: contain, investigate, recover

    A step-by-step runbook for a confirmed Microsoft 365 account takeover: disable and revoke, remove attacker persistence, scope the breach with audit logs and restore the user safely.

  6. Fix Entra Connect AttributeValueMustBeUnique and duplicate proxy addresses

    Find which object already holds the duplicated proxyAddresses or userPrincipalName value, remove it from the right side, and confirm the next Entra Connect sync exports cleanly.