Exchange

Message trace and mail flow troubleshooting in Exchange Online, with real cases

"The mail never arrived" is not a diagnosis. Every message leaves traces: in the message trace, in its headers, in the connector it used. Reading them in a fixed order turns guessing into evidence.

The order I work in

  1. Did Exchange Online see the message at all? Message trace.
  2. What happened to it? Message trace details: delivered, failed, quarantined, filtered as spam, forwarded.
  3. Why? The headers of a delivered copy, or the NDR of a failed one.
  4. Which path did it take? Connectors, accepted domains, gateways, on-premises servers.
  5. What is the fix, and how do we test it? Write down cause, evidence, correction and test.

Step 1 and 2: message trace

The Exchange admin center has a message trace view, but PowerShell is faster to repeat and to share. Get-MessageTraceV2 replaces the older Get-MessageTrace; it searches the last 90 days, at most 10 days per query.

Connect-ExchangeOnline
# Everything from one sender to one recipient in the last two days
Get-MessageTraceV2 -SenderAddress "billing@vendor.example" -RecipientAddress "ap@example.com" `
  -StartDate (Get-Date).AddDays(-2) -EndDate (Get-Date) |
  Select-Object Received, SenderAddress, RecipientAddress, Subject, Status, FromIP, MessageTraceId
# The event history of one message
Get-MessageTraceDetailV2 -MessageTraceId "<MessageTraceId>" -RecipientAddress "ap@example.com" |
  Select-Object Date, Event, Action, Detail

The Status already narrows it down: Delivered, Failed, Quarantined, FilteredAsSpam, Pending. If the trace shows nothing, the message never reached Exchange Online. Then look at the sender's side, at MX records, at a gateway in front, or at an on-premises server in a hybrid setup.

For "everything to this mailbox looks odd since Monday", group instead of reading line by line:

Get-MessageTraceV2 -RecipientAddress "ap@example.com" -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) |
  Group-Object Status, FromIP | Sort-Object Count -Descending | Select-Object Count, Name

Step 3: read the headers

For a delivered message, the headers say why it landed where it did. Copy them from Outlook (File, Properties) and paste them into the Message Header Analyzer of the Microsoft Remote Connectivity Analyzer, or read the key lines directly:

HeaderWhat it tells you
Authentication-ResultsSPF, DKIM and DMARC results, and compauth: Microsoft's composite verdict with a reason code
X-Forefront-Antispam-ReportSpam confidence level (SCL), filter verdict (SFV) and category (CAT, for example SPOOF or PHSH)
X-MS-Exchange-Organization-AuthAsInternal, Partner or Anonymous: whether Exchange Online trusted the connection the message came in on
Received linesThe path, from the bottom up, with host names and times
ARC-*Authentication results preserved by intermediaries such as gateways or mailing lists

For a failed message, the NDR code points to the area: 5.1.10 recipient not found, 5.4.1 relay access denied or recipient not found during directory-based edge blocking, 5.4.14 hop count exceeded, usually a routing loop, 5.7.1 delivery not authorised, often a restriction or a transport rule.

Step 4: check the path

Get-AcceptedDomain | Format-Table DomainName, DomainType, Default
Get-InboundConnector  | Format-List Name, Enabled, ConnectorType, SenderIPAddresses, TlsSenderCertificateName, RestrictDomainsToCertificate, EFSkipIPs, EFSkipLastIP
Get-OutboundConnector | Format-List Name, Enabled, ConnectorType, RecipientDomains, SmartHosts, TlsSettings, IsTransportRuleScoped

Accepted domain type matters: Authoritative means every recipient must exist in Exchange Online, InternalRelay means unknown recipients are routed on, for example to on-premises. A wrong type here explains many "some recipients work, some do not" cases.

Cases from projects, anonymised

Internal mail goes missing after a partial migration

Symptom: after part of the mailboxes moved to Exchange Online, mail between on-premises and cloud mailboxes disappeared, sporadically and not reproducibly. Cause: a connector that took precedence, combined with an outdated accepted domain. Fix: connector scope and accepted domain corrected, routing documented, a runbook for the team. The point: the cause was provable in the trace and the connector configuration, not just plausible.

Internal mail suddenly treated as external

A typical pattern: after the certificate on the on-premises hybrid server is renewed, internal mail arrives in Exchange Online with external tags and higher spam scores. In the headers, AuthAs says Anonymous. Cause: the inbound connector still expects the old certificate name in TlsSenderCertificateName. Fix: update the connector or rerun the Hybrid Configuration Wizard, then check AuthAs on a new test message.

Newsletters land in junk after DMARC is tightened

Symptom: after moving to p=quarantine, newsletters to customers landed in junk. Cause: the newsletter tool used its own Return-Path and its own DKIM domain, so neither SPF nor DKIM was aligned. In one project, three undocumented systems sent in the domain's name this way. Fix: custom sending domain and DKIM in each tool, then the next DMARC step. See DMARC to p=reject.

Everything fails SPF behind a gateway

Symptom: with a third-party gateway in front of Exchange Online, Microsoft's filter flags legitimate mail as spoofed. Cause: Exchange Online sees the gateway's IP as the source, so SPF fails for every sender. Fix: Enhanced Filtering for Connectors on the inbound connector, so Exchange Online evaluates the original source, and an inbound connector restricted to the gateway's IPs or certificate so nobody can bypass the gateway.

Checklist

  • Message trace first: did Exchange Online see the message?
  • Trace details read: which event, which action, which detail?
  • Headers of a delivered copy analysed: authentication, SCL, AuthAs, path
  • NDR code mapped to an area
  • Accepted domains and connectors checked against the intended path
  • Cause, evidence, correction and test written down
  • Runbook updated, so the next person starts at step 1, not at a guess

Hiring for Microsoft 365, identity or email security in Singapore?

Permanent role, contract or a first conversation: write to me. I answer personally.