The poison message queue and the Submission queue are two pressure points in the Exchange transport pipeline. Messages landing in the first, or piling up in the second, mean something crashed or stalled while transport was processing mail. In this post I'll explain what each queue protects you from, how to find the real cause, and how to release or remove messages without losing mail.
Errors this guide fixes
EX01\Poison (NextHopDomain: Poison Message), messages SuspendedQueue Viewer / Get-QueueEX01\Submission (NextHopDomain: Submission) not drainingGet-Queue: MessageCount up, Velocity negativePOISONMESSAGEGet-MessageTrackingLog EventIdFaulting application name: EdgeTransport.exeApplication log (Event ID 1000)Watson report about to be sent for process idApplication log (Event ID 4999)+1 more guideEvent ID 1000 (Application Error)Application logEvent ID 4999 (MSExchange Common)Application log+1 more guide
Symptoms#
- Queue Viewer or
Get-QueuelistsEX01\Poison(NextHopDomain:Poison Message), messagesSuspended. This queue only appears while it contains messages. EX01\Submission(NextHopDomain:Submission) not draining: its MessageCount keeps growing,Velocitystays negative, and mail through that server is delayed in every direction.- Message tracking shows
POISONMESSAGEevents.
When a crash is involved, the Application log shows the transport worker process failing:
Event ID 1000 (Application Error)
Faulting application name: EdgeTransport.exe, version: ...
Faulting module name: ...
Event ID 4999 (MSExchange Common)
Watson report about to be sent for process id: ..., with parameters: ...Why it happens#
The poison message queue#
When the Transport service fails while processing a message, Exchange identifies the message involved and, rather than risk another crash, isolates it in the poison message queue so the service can keep running. Microsoft describes two kinds of messages that end up there: ones that are genuinely malformed or harmful, and valid ones that triggered a badly written transport agent or a software bug.
Behaviour worth knowing: each server has one poison queue, its messages are permanently suspended, and they're never resumed or expired automatically. They stay until an administrator acts.
The Submission queue#
Every message entering the Transport service, whether from a Receive connector, the Pickup or Replay directory or the Mailbox Transport Submission service, waits in the Submission queue for the categorizer. The categorizer resolves recipients in Active Directory, works out the route and moves the message to a delivery queue or the Unreachable queue; transport agents and mail flow rules run along the way. A Submission queue that won't drain usually means:
- a transport agent (antivirus, disclaimer, signature or archiving product) is slow, hung or crashing the process;
- domain controllers or global catalogs are slow or unreachable, so recipient resolution stalls;
- the transport process keeps restarting, so processing starts over each time;
- the disk holding the queue database (
%ExchangeInstallPath%TransportRoles\data\Queueby default) is slow or nearly full, which also triggers back pressure.
How to fix it#
1. Check every transport server#
Get-TransportService | ForEach-Object { Get-Queue -Server $_.Name } |
Where-Object { $_.NextHopDomain -in 'Submission', 'Poison Message' } |
Format-Table Identity, Status, MessageCount, Velocity, IncomingRate, OutgoingRate -AutoSizeA healthy Submission queue is close to empty outside peaks, and a poison queue shouldn't be listed at all.
2. Inspect the poison messages and keep a copy#
Get-Message -Queue "EX01\Poison" | Format-List Identity, FromAddress, Subject, Size, DateReceived, LastError
Export-Message -Identity "EX01\Poison\1234" | AssembleMessage -Path "D:\PoisonExport\EX01-1234.eml"Export-Message only works on suspended messages. Poison messages already are; in other queues you'd run Suspend-Message first. Treat the .eml as potentially malicious and examine it on a protected workstation, not on the Exchange server.
3. Find what crashed or stalled transport#
Get-WinEvent -FilterHashtable @{LogName='Application'; Id=1000,4999; StartTime=(Get-Date).AddDays(-2)} |
Where-Object { $_.Message -match 'edgetransport' } | Format-List TimeCreated, Id, Message
Get-MessageTrackingLog -Server EX01 -EventId POISONMESSAGE -Start (Get-Date).AddDays(-7) |
Format-Table Timestamp, Sender, Recipients, MessageSubject -AutoSize
Get-TransportAgent | Format-Table Identity, Enabled, Priority -AutoSize
Get-TransportAgent -TransportService FrontEnd | Format-Table Identity, Enabled, Priority -AutoSizeThe Faulting module name in event 1000 is the best clue: a DLL from a third-party product points straight at its agent. Line the crash times up with the poison message's arrival and with recent changes such as a new agent version or an Exchange update.
For a stalled Submission queue, also check which directory servers Exchange is using with Get-ExchangeServer EX01 -Status | Format-List CurrentDomainControllers, CurrentGlobalCatalogs, look for MSExchange ADAccess errors in the Application log, and check back pressure with Get-ExchangeDiagnosticInfo -Server EX01 -Process EdgeTransport -Component ResourceThrottling.
4. Fix the cause#
- Third-party agent: update it to a version its vendor supports on your build, or disable it to prove the point with
Disable-TransportAgent -Identity "Contoso Disclaimer Agent"followed byRestart-Service MSExchangeTransport. Re-enable it withEnable-TransportAgentonce the vendor fix is in. - Exchange bug: install the latest cumulative update and security update. Exchange 2016 and 2019 reached end of support on 14 October 2025, so plan to be on Exchange Server SE, where fixes continue to ship.
- Active Directory: repair unhealthy or overloaded domain controllers and global catalogs in the Exchange site.
- Disk: free space on the queue database drive, or move the queue database to a dedicated volume (the
QueueDatabasePathandQueueDatabaseLoggingPathkeys inEdgeTransport.exe.config). Re-check those keys after each cumulative update, which overwrites customisations in that file.
5. Release or remove the poison messages#
# Legitimate message and the cause is fixed: release it for processing
Resume-Message -Identity "EX01\Poison\1234"
# Malformed or malicious, or you've kept an exported copy: delete it without an NDR
Remove-Message -Identity "EX01\Poison\1234" -WithNDR $falseWatch out: Resume a poison message only after the cause is fixed; if it still triggers the bug, it can take the Transport service down again. Never delete or rename mail.que to "clear" the queues, because that discards every queued message on the server. And don't suspend the Submission queue as a workaround: while it's suspended, the categorizer picks up nothing.
Verify the fix#
Get-Queue -Server EX01no longer listsEX01\Poison; the queue disappears once it's empty.Get-Queue -Identity EX01\Submission | Format-List MessageCount, Velocity, IncomingRate, OutgoingRateshows a small message count and a velocity at or above zero.- No new event 1000 or 4999 entries for the transport process over the next day.
- A test message shows
RECEIVEfollowed within seconds bySENDorDELIVER; message tracking with Get-MessageTrackingLog shows how to follow it.
Prevent it next time#
- Alert on any poison queue: schedule
Get-TransportService | ForEach-Object { Get-Queue -Server $_.Name } | Where-Object { $_.NextHopDomain -eq 'Poison Message' }and treat any result as an incident. - Keep transport agents to a minimum and re-test them after every Exchange update.
- Stay current with Exchange Server updates and run the Health Checker after changes.
- Export before you remove: the copy is your evidence for the vendor or Microsoft Support.

