The DMARC Failure Was The First Clue
The email looked convincing.
The sender appeared to be a trusted supplier. The logo was familiar. The request sounded urgent, but not unusual.
Then Microsoft Defender recorded one small detail that changed the investigation: DMARC = Fail.

Briefing summary
A payment update email looked legitimate to the user, but authentication telemetry told a different story. Agent Foskett follows DMARC, SPF, DKIM, Composite Authentication and sender identity evidence to determine whether the message deserved trust.
The email looked trustworthy
Why DMARC mattered
The first KQL question
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
EmailEvents
| where Timestamp > ago(30d)
| where AuthenticationDetails has "DMARC"
| where AuthenticationDetails has "fail"
| project
Timestamp,
NetworkMessageId,
SenderFromAddress,
SenderMailFromAddress,
RecipientEmailAddress,
Subject,
ThreatTypes,
DeliveryAction,
DeliveryLocation,
AuthenticationDetails
The sender identities did not line up
Compare visible sender and mail-from sender
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
EmailEvents
| where Timestamp > ago(30d)
| where Subject has_any ("payment", "invoice", "account", "bank")
| extend SenderFromDomain = tostring(split(SenderFromAddress, "@")[1])
| extend SenderMailFromDomain = tostring(split(SenderMailFromAddress, "@")[1])
| where SenderFromDomain != SenderMailFromDomain
| project
Timestamp,
SenderFromAddress,
SenderMailFromAddress,
SenderFromDomain,
SenderMailFromDomain,
RecipientEmailAddress,
Subject,
AuthenticationDetails,
DeliveryAction,
DeliveryLocation
What the failure could mean
Was the email delivered?
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
EmailEvents
| where Timestamp > ago(30d)
| where AuthenticationDetails has "DMARC"
| where AuthenticationDetails has "fail"
| summarize
TotalMessages = count(),
Recipients = dcount(RecipientEmailAddress),
FirstSeen = min(Timestamp),
LastSeen = max(Timestamp)
by SenderFromAddress, SenderMailFromAddress, DeliveryAction, DeliveryLocation, ThreatTypes
| order by TotalMessages desc
Check for links and clicks
Follow the URL evidence
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
let SuspiciousMessages =
EmailEvents
| where Timestamp > ago(30d)
| where AuthenticationDetails has "DMARC"
| where AuthenticationDetails has "fail"
| project NetworkMessageId, SenderFromAddress, RecipientEmailAddress, Subject;
EmailUrlInfo
| join kind=inner SuspiciousMessages on NetworkMessageId
| project
Timestamp,
SenderFromAddress,
RecipientEmailAddress,
Subject,
Url,
UrlDomain
