The header line
In any message received by Microsoft 365 (including Exchange Online and outlook.com mailboxes), the Authentication-Results header ends with Microsoft's own verdict:
Authentication-Results: spf=fail (sender IP is 203.0.113.10)
smtp.mailfrom=mailer.example.net; dkim=none (message not signed)
header.d=none; dmarc=fail action=none header.from=contoso.com;
compauth=fail reason=001
compauth is short for composite authentication. It is not part of SPF, DKIM, or DMARC. It is Microsoft's combined judgment of all three plus other signals from the message, evaluated against the domain in the visible From: address. The reason code tells you which rule produced the verdict, and that code is the fastest route to the fix.
To read a header without hand-parsing it, paste it into the email header analyzer. It runs entirely in your browser, so the headers never leave your machine.
Why Microsoft adds a verdict of its own
SPF, DKIM, and DMARC only say what they measured. A domain with no DMARC record gets dmarc=none, which is technically not a failure, yet a spoofed message from that domain is still dangerous. Composite authentication closes that gap: when explicit authentication is absent or inconclusive, Microsoft falls back to implicit checks (sending history, infrastructure reputation, PTR alignment) and still renders a pass or fail.
One consequence surprises people: a compauth=fail does not automatically junk the message. Microsoft applies what it calls a holistic evaluation, so a failing verdict on an otherwise clean message can still reach the inbox. The verdict becomes decisive when other signals also look suspicious.
The four compauth values
| Value | Meaning |
|---|---|
compauth=pass |
Explicit or implicit authentication passed (reason codes 1xx and 7xx). |
compauth=fail |
Explicit or implicit authentication failed (reason codes 000, 001, 002, 010, 6xx). |
compauth=softpass |
Implicit authentication passed with lower confidence (reason codes 2xx). |
compauth=none |
The message was not checked, or the check was bypassed (reason codes 3xx, 4xx, 9xx). |
Reason codes, decoded
These are the codes Microsoft documents for the reason field, grouped by what they mean for you:
| Code | Meaning |
|---|---|
000 |
Explicit failure: the message failed DMARC and the domain's policy is p=quarantine or p=reject. |
001 |
Implicit failure: the sending domain published no authentication records, or only weak ones (SPF ~all or ?all, DMARC p=none). |
002 |
An admin in the recipient organization explicitly blocked this sender/domain pair from spoofing. |
010 |
The message failed DMARC under p=reject or p=quarantine, and the sending domain belongs to the recipient organization (intra-org spoofing). |
1xx (100, 101, 102, 109, ...) |
Passed. 100 is the standard aligned pass. 109 means the domain has no DMARC record but would pass. 130 means a trusted ARC sealer overrode a DMARC failure. |
2xx |
Soft pass from implicit signals, such as PTR records aligning with the From domain. |
3xx, 4xx, 9xx
|
Not checked or bypassed, for example by an allow rule. 905 covers complex routing through an on-premises or non-Microsoft hop. |
501, 502
|
DMARC not enforced because the message is a valid bounce (non-delivery report). |
601 |
Implicit failure: the sending domain is one of the recipient organization's own accepted domains (self-to-self spoofing). |
701–704
|
Passed implicitly: the organization has a history of legitimate mail from this sending infrastructure. |
Three of these account for nearly every troubleshooting session: 000, 001, and 601.
reason=000: your DMARC policy did its job, on you
The message explicitly failed DMARC and your policy says quarantine or reject. If the message was legitimate, some service is sending as your domain without aligned SPF or DKIM. The diagnosis and per-cause fixes are the same as for a Microsoft rejection bounce, covered in 550 5.7.509: sending domain does not pass DMARC verification. Depending on the anti-phishing policy, the same failure appears as a 550 5.7.509 bounce, a quarantined message, or a junked message with this header.
reason=001: the domain has nothing (or too little) published
Implicit failure. The From domain either publishes no SPF, DKIM, or DMARC at all, or publishes only weak signals: an SPF record ending in ~all or ?all with no DKIM alignment, or a DMARC policy of p=none. Microsoft could not authenticate the message explicitly, ran its implicit checks, and the message failed them.
If this is your domain, the fix is to authenticate properly:
- Publish SPF covering every service that sends as your domain.
- Enable DKIM signing with your own domain at each service.
- Publish a DMARC record, starting with
p=noneplus aruareporting address, and use the reports to move to enforcement. If you have never published one, start with no DMARC record found.
Note the asymmetry: p=none is listed among the weak signals. Merely having a DMARC record does not make mail pass composite authentication; aligned SPF or DKIM does.
reason=601: your own domain, arriving from outside
The recipient tenant recognized the sending domain as one of its own accepted domains, but the message arrived unauthenticated from outside. Classic triggers:
- A cloud service (survey tool, scanner, notification platform) sends mail as
yourdomain.comto your own staff, without SPF authorization or DKIM signing for your domain. - Mail routes through an on-premises relay or filtering appliance before reaching Microsoft 365, so the original source IP is hidden and SPF evaluates against the relay.
- An actual phishing attempt impersonating your domain against your own users.
For the first case, authenticate the service like any other sender: SPF include or DKIM key for your domain. For the relay case, Microsoft's Enhanced Filtering for Connectors lets Exchange Online see the true source IP so SPF evaluates correctly. The third case is compauth working as designed.
What to do with a compauth=fail, step by step
- Extract the full
Authentication-Resultsheader from the affected message. - Note the
reasoncode and match it in the table above. - Compare
header.fromwithsmtp.mailfromandheader.d. For explicit failures (000, 010) at least one of the two must pass and align. For implicit failures (001, 601) the domain needs real SPF, DKIM, and DMARC published in the first place. - Fix the sending service or the DNS, send a fresh test, and confirm the new header shows
compauth=pass reason=100(or109until your DMARC record is published).
Then verify the domain end to end with the DMARC checker: record present, SPF valid, DKIM selectors resolving.
Composite authentication verdicts are only visible on messages you can open. Your DMARC aggregate reports show the same alignment failures across every receiver, including the mail you never see bounce. DMARCTrust reads those reports for you, free for one domain, so the service that just earned a reason=000 shows up in your dashboard with its IP and volume.
Related fixes
- Microsoft bounced the message outright: 550 5.7.509: sending domain does not pass DMARC verification.
- SPF and DKIM pass but nothing aligns: DMARC alignment issues.
- No DMARC record published yet: no DMARC record found.
- Forwarded mail failing authentication: email forwarding, mailing lists, and ARC.
- Gmail and Yahoo's equivalent rejection: 550 5.7.26 unauthenticated email.