Start with the message and its route
“Email did not arrive” may mean rejection before Exchange Online, a transport rule, full mailbox, quarantine, or downstream-server failure. These ten commands locate the relevant stage and support a precise correction.
Record inbound/outbound direction, exact addresses, time and zone, complete Message-ID, NDR, and SMTP code. Preserve original headers. contoso.com and example.com values are fictional; commands read configuration or traces and do not send messages.
This guide complements DMARC and junk-email articles by focusing on routing, connectors, and restrictions. It does not replace a complete mail-flow investigation or security assessment.
Prepare the session and permissions
Use a supported ExchangeOnlineManagement module exposing both V2 cmdlets and verify them after connecting. Follow Microsoft release notes and prerequisite matrices for upgrades; versions 3.5.0 through 3.9.2 on PowerShell 7 require PowerShell 7.4.x. Validate the combination on your administration workstation before an incident.
Use interactive MFA with a named identity. Message Trace uses Exchange RBAC: delegate Message Tracking with V2 entries available in your tenant. For other commands, have the RBAC administrator identify necessary Get entries and parameters using Microsoft's procedure and apply the useful recipient scope. Global Administrator is unnecessary for these diagnostics.
Recipient or configuration read rights do not necessarily permit tracing. Missing commands and denied access mean not evaluated. Exchange Online and mailbox features need appropriate licensing; this guide does not itself require Defender for Office 365 Plan 2. Additional Defender investigations may have separate prerequisites.
# Preparation and connection, outside the 10 diagnostic commands.
$ErrorActionPreference = 'Stop'
Get-Module -ListAvailable ExchangeOnlineManagement | Select-Object Name,Version
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName admin@contoso.com
Get-Command Get-MessageTraceV2,Get-MessageTraceDetailV2 -ErrorAction Stop
# Use DateTime values to avoid ambiguous regional date strings.
$end = [datetime]::UtcNow
$start = $end.AddHours(-2)Understand Message Trace V2 limits
V2 searches the previous 90 days with at most ten days per request. Get-MessageTraceV2 returns 1,000 results by default and at most 5,000. At the cap, narrow the window or follow documented continuation using EndDate and StartingRecipientAddress; old Page/PageSize parameters do not apply.
Output timestamps are UTC and examples explicitly create UTC DateTime values. Respect throttling instead of querying details across the entire tenant. A trace is not a user read log.
1. Find the message with Get-MessageTraceV2
Start with a two-hour window and exact addresses. Results are per recipient. Retain the original Message-ID separately from MessageTraceId. No result may reflect ingestion delay, time range, an alias, or a message that never reached the service.
$trace = @(Get-MessageTraceV2 -SenderAddress 'alex@contoso.com' -RecipientAddress 'sam@example.com' -StartDate $start -EndDate $end -ResultSize 5000 -ErrorAction Stop)
$trace | Select-Object Received,SenderAddress,RecipientAddress,Subject,Status,MessageTraceId,MessageId2. Read events with Get-MessageTraceDetailV2
Follow events and failure codes. Delivered is not a read receipt: for external recipients, corroborate delivery with the receiving system; internally, investigate rules, junk, and quarantine too. Retain the full object when selected detail is insufficient.
# Replace with the exact trace ID AND recipient from check 1.
Get-MessageTraceDetailV2 -MessageTraceId '11111111-1111-1111-1111-111111111111' -RecipientAddress 'sam@example.com' -StartDate $start -EndDate $end -ErrorAction Stop |
Select-Object Date,Event,Detail,Data3. Check recipient type and addresses
Mailboxes, contacts, mail users, and groups have different delivery paths. Check aliases and external targets, especially in hybrid deployments. The primary address must be known; use an appropriate targeted search for aliases. Access errors do not prove a recipient is absent.
Get-EXORecipient -PrimarySmtpAddress 'alex@contoso.com' -Properties EmailAddresses,ExternalEmailAddress -ErrorAction Stop |
Select-Object DisplayName,RecipientTypeDetails,PrimarySmtpAddress,EmailAddresses,ExternalEmailAddress4. Read mailbox restrictions and quotas
Match the NDR to actual limits. Requiring authenticated senders may explain external rejection; allow lists and moderation also matter. This check targets a mailbox; use the correct object-type cmdlet for groups. Unlimited does not remove other service limits.
Get-Mailbox -Identity 'alex@contoso.com' -ErrorAction Stop |
Select-Object PrimarySmtpAddress,MaxSendSize,MaxReceiveSize,IssueWarningQuota,ProhibitSendQuota,ProhibitSendReceiveQuota,RequireSenderAuthenticationEnabled,AcceptMessagesOnlyFromSendersOrMembers,RejectMessagesFromSendersOrMembers,ModerationEnabled5. Compare mailbox size with quota
Compare size against check 4 without naive string comparisons. Primary mailbox, archive, and Recoverable Items have separate limits. Size is evidence, not an explanation without a matching event or NDR. Do not delete messages as a diagnostic test.
Get-EXOMailboxStatistics -Identity 'alex@contoso.com' -ErrorAction Stop |
Select-Object DisplayName,ItemCount,TotalItemSize,TotalDeletedItemSize6. Inspect inbound connectors
Compare configuration with the actual public source IP and sending server certificate. NAT or certificate changes can break relay. Do not broaden to all IPs to restore flow. Correct configuration does not prove the connector handled this message.
Get-InboundConnector -ErrorAction Stop |
Select-Object Identity,Name,Enabled,ConnectorType,SenderDomains,SenderIPAddresses,RequireTls,TlsSenderCertificateName,RestrictDomainsToIPAddresses,RestrictDomainsToCertificate7. Inspect outbound connectors
Check destination, smart host, and TLS, then correlate selection with transport rules. With centralized hybrid routing, failure may occur after Exchange Online. A Get validates neither remote certificate nor connectivity; use EAC connector validation and an authorized test message.
Get-OutboundConnector -ErrorAction Stop |
Select-Object Identity,Name,Enabled,ConnectorType,RecipientDomains,SmartHosts,UseMXRecord,TlsSettings,TlsDomain,RouteAllMessagesViaOnPremises,IsTransportRuleScoped8. Read transport rule order and actions
Order, exceptions, and StopRuleProcessing may explain differences between recipients. Read Description and full candidate-rule details. Do not disable all rules; reproduce using fictional content and a pilot scope. An existing rule may be disabled or in test mode.
Get-TransportRule -ResultSize Unlimited -ErrorAction Stop |
Sort-Object Priority |
Select-Object Identity,Name,State,Mode,Priority,Description,StopRuleProcessing9. Read the mailbox SMTP AUTH override
True disables SMTP AUTH for this mailbox; False enables it at this level; Null inherits the organization setting. Other controls can still block connections. This read proves neither Basic Authentication nor OAuth usage. First identify authenticated submission, relay, or direct send.
Get-CASMailbox -Identity 'device-mail@contoso.com' -ErrorAction Stop |
Select-Object PrimarySmtpAddress,SmtpClientAuthenticationDisabled10. Read organization SMTP AUTH configuration
Correlate with check 9, authentication policies, Security Defaults, and relevant Entra logs. Do not re-enable Basic Authentication as remediation. Document the application's supported OAuth or relay method, then validate internal and external sending separately.
Get-TransportConfig -ErrorAction Stop |
Select-Object SmtpClientAuthenticationDisabledTurn results into a diagnosis
Fictional example: a printer sends internally but gets 5.7.64 externally after an ISP change. Compare its current public IP against inbound connector scope and the NDR before changes. This guides investigation without claiming every 5.7.64 has the same cause.
| Finding | Next check | Avoid concluding |
|---|---|---|
| No trace | Window, alias, NDR, sender logs | Exchange lost the message |
| SMTP failure | Per-recipient details and restrictions | Retry without investigating |
| Delivered but missing | Inbox rules, junk, quarantine, downstream server | User read the message |
| Device relay denied | Method, public IP, certificate | Open relay to all IPs |
| SMTP AUTH blocked | Effective settings and authentication method | Re-enable Basic |
Correct a pilot scope and validate
The ten commands change no tenant settings. Connector, rule, quota, or authentication changes need their own plan: owner, preserved initial state, justification, pilot scope, window, and rollback. Preserve rule conditions, actions, exceptions, and priority before removal.
Validate fictional-content messages in each required direction: internal, external inbound, and external outbound. Retain NDRs, new trace, and recipient-side results. Sending tests is a separate action authorized through your process; do not use real sensitive content.
After changes, reread the setting and monitor legitimate flows. Rollback restores documented previous values. DNS changes may remain cached for the TTL, so restoring an old value is not instantly effective everywhere.
Keep collector, tenant, UTC period, module versions, and errors in protected storage with defined retention. Traces may expose subjects, addresses, and sensitive routing detail. Close the session afterward.
Microsoft 365 consulting can correlate this evidence with hybrid routing, applications, and security controls and prepare remediation that respects business workflows.
Disconnect-ExchangeOnline -Confirm:$false