Skip to content

Exchange Online Message Trace Forensics

In email security and Business Email Compromise (BEC) investigations, determining how a message traversed the transport boundary is paramount. Exchange Online Message Trace is the authoritative transport telemetry engine of Microsoft 365. It records every message ingested via SMTP, evaluated by Exchange Online Protection (EOP), routed through transport rules, delivered to mailboxes, or relayed outward to external mail transfer agents.

However, incident responders frequently misunderstand what Message Trace can—and cannot—prove. Message Trace is a transport logging mechanism: it records envelope and routing metadata, not mailbox content. Furthermore, it operates under a strict two-tier time architecture (0-10 days real-time vs 10-90 days historical search) that dictates evidence collection speed and format.


1. Transport Architecture & Telemetry Pipeline

Section titled “1. Transport Architecture & Telemetry Pipeline”

When an email enters or leaves Microsoft 365, it flows through the Exchange Online Transport Pipeline, generating granular telemetry at each state transition:

graph TD
subgraph "External Ingress"
EXT_MTA[External Sending MTA]
end
subgraph "Exchange Online Protection (EOP) Front-End"
FE_RECV[Front-End Receive & TLS Handshake<br/>OriginalClientIpAddress Recorded]
FE_AUTH[SPF / DKIM / DMARC Evaluation<br/>Authentication-Results Generated]
FE_FILTER[Antispam & Antiphishing Filter<br/>SCL, BCL, Phish Verdicts]
end
subgraph "Categorizer & Transport Routing"
ROUT_EVAL[Transport Rules & Connectors<br/>Disclaimers, Encryption, Redirects]
ROUT_EXP[Distribution List Expansion]
end
subgraph "Mailbox Delivery / Relay"
DELIV_STORE[Store Driver Delivery<br/>Status: Deliver -> Mailbox]
DELIV_EXT[Outbound Send Connector<br/>Status: Send -> External MX]
DELIV_QUAR[EOP Quarantine<br/>Status: Quarantine]
end
EXT_MTA -->|TCP 25| FE_RECV
FE_RECV --> FE_AUTH
FE_AUTH --> FE_FILTER
FE_FILTER --> ROUT_EVAL
ROUT_EVAL --> ROUT_EXP
ROUT_EXP --> DELIV_STORE
ROUT_EXP --> DELIV_EXT
FE_FILTER -->|Malicious Verdict| DELIV_QUAR

2. Real-Time Trace vs Historical Search Architecture

Section titled “2. Real-Time Trace vs Historical Search Architecture”

Microsoft 365 splits Message Trace into two distinct operational regimes based on event age:

ParameterReal-Time Message Trace (0 to 10 Days)Historical Search (10 to 90 Days)
Availability WindowEvents occurring within the last 10 days.Events occurring between 10 and 90 days ago (or extended query under 10 days).
Execution ModeSynchronous, interactive, sub-second response.Asynchronous batch job queued on Microsoft background worker nodes.
Retrieval MechanismGet-MessageTrace & Get-MessageTraceDetailStart-HistoricalSearch -> CSV download via Azure Blob SAS URL.
Maximum Record Limit5,000 records per query (PowerShell pagination available).Up to 100,000 records per exported CSV file.
Data Detail LevelSummary properties + per-hop event details on demand.Full raw transport event strings, expanded rule evaluations, and hop headers.
Completion LatencyImmediate (1 to 5 seconds).15 minutes to several hours depending on tenant size and tenant load.

3. The Cornerstone Identifier: NetworkMessageId vs MessageId

Section titled “3. The Cornerstone Identifier: NetworkMessageId vs MessageId”

In forensic email triage, identifying messages uniquely across disparate systems is critical:

  1. MessageId (RFC 5322):
    • Generated by the sending mail client or outbound MTA (e.g., <abc123.xyz@mail.sending-domain.com>).
    • Vulnerable to adversary manipulation: An attacker can forge, duplicate, or omit the RFC Message-ID header. Multiple different emails can share the same Message-ID.
  2. NetworkMessageId:
    • A unique GUID generated by the Microsoft 365 transport infrastructure upon ingestion.
    • Immutable: Preserved across all hops, transport rules, distribution list expansions, and security inspection events within the tenant.
    • Primary Forensic Pivot: Used to correlate Message Trace records with Purview UAL events (MailItemsAccessed), Defender for Office 365 alerts (EmailEvents), and eDiscovery searches.

Each step in the delivery lifecycle emits a discrete event in Get-MessageTraceDetail:

Event StatusTechnical ActionForensic Significance
ReceiveMessage accepted by EOP front-end servers via SMTP.Captures the true external source IP (OriginalClientIpAddress).
SubmitMessage submitted by Mailbox transport submission service.Indicates internal origination (an authenticated user or script sent a mail).
DeliverSuccessfully handed off to the user’s mailbox store.Proves delivery to the mailbox (does not prove user read it).
SendMessage transmitted out of the tenant via external SMTP connector.Vital in BEC investigations to verify outbound invoice fraud or data leakage.
FailPermanent delivery failure (NDR 5xx returned).Evaluates invalid recipient reconnaissance or dead drop accounts.
DropMessage dropped silently without generating an NDR.Usually triggered by DLP rules or malware filters.
DeferTemporary delivery delay (4xx response from remote MTA).Shows connection throttling or greylisting.
RedirectMessage rerouted to an alternative recipient address.Key persistence indicator: triggered by mail flow forwarding rules.
ExpandDistribution list expanded to individual recipient members.Maps the blast radius of mass phishing sent to internal alias lists.
QuarantineSent to EOP admin/user quarantine store.Message neutralized prior to inbox delivery.

5. Operational PowerShell Extraction Workflows

Section titled “5. Operational PowerShell Extraction Workflows”
Terminal window
Connect-ExchangeOnline -UserPrincipalName dfir-analyst@defense-corp.org
# Define UTC boundaries within the 10-day window
$startDate = (Get-Date).AddDays(-3).ToUniversalTime()
$endDate = (Get-Date).ToUniversalTime()
# 1. Scoping all messages from a suspected threat actor domain
$traces = Get-MessageTrace `
-SenderAddress "*@adversary-phish.com" `
-StartDate $startDate `
-EndDate $endDate `
-ResultSize 5000
# 2. Extract detailed hop-by-hop delivery progression for each message
$forensicReport = foreach ($msg in $traces) {
$details = Get-MessageTraceDetail `
-MessageTraceId $msg.MessageTraceId `
-RecipientAddress $msg.RecipientAddress
[PSCustomObject]@{
ReceivedTime = $msg.Received
NetworkMessageId = $msg.NetworkMessageId
Sender = $msg.SenderAddress
Recipient = $msg.RecipientAddress
Subject = $msg.Subject
Status = $msg.Status
SenderIP = $msg.FromIP
SizeKB = [Math]::Round($msg.Size / 1024, 2)
Hops = ($details | ForEach-Object { "$($_.Event): $($_.Detail)" }) -join " -> "
}
}
$forensicReport | Format-Table -AutoSize

Phishing Campaign Blast Radius Reconstruction

Section titled “Phishing Campaign Blast Radius Reconstruction”

When a single malicious email is reported by an employee, the investigator must quickly identify all other recipients across the tenant:

Terminal window
# Pivot using the unique NetworkMessageId extracted from the reported message
$reportedNetMsgId = "8a32f10b-412e-4b92-8012-bc91a45920a1"
$allImpacted = Get-MessageTrace `
-NetworkMessageId $reportedNetMsgId `
-StartDate (Get-Date).AddDays(-10) `
-EndDate (Get-Date)
# Identify which users had the email delivered vs quarantined
$allImpacted | Group-Object Status | Select-Object Name, Count

BEC Outbound Fraud & Exfiltration Tracking

Section titled “BEC Outbound Fraud & Exfiltration Tracking”

In BEC scenarios, attackers frequently abuse access to send modified wire instructions to external partners or forward inbound client communications to personal drop accounts:

// Hunting for anomalous outbound email spikes via Defender XDR (EmailEvents)
EmailEvents
| where Timestamp > ago(30d)
| where SenderFromAddress == "cfo@defense-corp.org"
| where DeliveryLocation == "External" or InternetMessageId has "outbound"
| summarize
RecipientCount = dcount(RecipientEmailAddress),
Recipients = make_set(RecipientEmailAddress, 10),
TotalEmails = count()
by bin(Timestamp, 1d)
| order by Timestamp desc

7. Forensic Gotchas & Investigation Boundaries

Section titled “7. Forensic Gotchas & Investigation Boundaries”