Event ID 2004: Message Delivery Failed - Fix Guide 2025
Complete troubleshooting guide for Exchange Server Event ID 2004 message delivery failures. Learn how to diagnose NDRs, fix routing problems, resolve connector issues, and restore email delivery in 15-30 minutes.
Table of Contents
Event ID 2004 in Exchange Server signals that a message delivery attempt has failed. Users receive Non-Delivery Reports (NDRs), and critical business communications may not reach their intended recipients. This guide shows you how to diagnose the specific failure reason and restore delivery.
Our Exchange Mail Flow Specialists troubleshoot delivery failures daily. This guide provides the same systematic approach we use to identify and resolve delivery issues quickly.
Error Overview: What Event ID 2004 Means
Event ID 2004 is logged by the MSExchangeTransport service when a message cannot be delivered to its final destination. The event contains crucial diagnostic information including the recipient address, failure reason, and error code.
Log Name: Application
Source: MSExchangeTransport
Event ID: 2004
Level: Warning
Description: Message delivery failed for the following recipient:
Recipient: john.smith@external-company.com
Reason: 550 5.1.1 The email account that you tried to reach
does not exist. Please try double-checking the recipient's
email address for typos or unnecessary spaces.Understanding the failure: Exchange categorizes delivery failures into permanent (5.x.x) and transient (4.x.x) errors. Permanent failures generate immediate NDRs, while transient failures trigger retry attempts.
Message Delivery Flow
Symptoms & Business Impact
What Users Experience:
- Non-Delivery Report (NDR) emails returned to sender
- "Your message wasn't delivered" notifications
- Emails to specific domains consistently fail
- Internal emails work but external fail (or vice versa)
- Messages show as "Sent" but never received by recipient
What Admins See:
- Event ID 2004 entries in Application event log
- Message tracking shows FAIL events
- Queues with status "Retry" or messages stuck
- Increased NDR generation load
- Help desk tickets about "bounced" emails
Business Impact:
- Customer Communication: Sales proposals and support replies not delivered
- Partner Relations: Failed B2B communications damage relationships
- Compliance: Required notifications may not reach recipients
- Revenue: Lost deals due to missed communication
Common Causes of Event ID 2004
1. Invalid Recipient Address (35% of cases)
NDR Code 5.1.1: The recipient email address doesn't exist at the destination domain. Could be a typo, deleted account, or domain that doesn't accept email.
Identified by: "User unknown" or "Mailbox not found" in NDR
2. DNS Resolution Failure (20% of cases)
NDR Code 4.4.0/5.4.4: Exchange cannot resolve the destination domain's MX records or A records for mail delivery.
Identified by: "DNS query failed" or "No MX records" in event log
3. Relay Denied (15% of cases)
NDR Code 5.7.1: Remote server refuses to relay mail from your domain. Often due to missing SPF records, blacklisting, or misconfigured authentication.
Identified by: "Relay access denied" or "Not authorized" messages
4. Recipient Mailbox Full (12% of cases)
NDR Code 5.2.2: The recipient's mailbox has exceeded its storage quota and cannot accept new messages.
Identified by: "Mailbox full" or "Over quota" in NDR
5. Network/Connectivity Issues (10% of cases)
NDR Code 4.4.1/4.4.2: Exchange cannot establish SMTP connection to destination server due to firewall, routing, or server unavailability.
Identified by: "Connection timed out" or "Unable to connect"
6. Message Size Exceeded (8% of cases)
NDR Code 5.3.4: Message exceeds size limit at sending server, receiving server, or intermediate relay.
Identified by: "Message too large" in NDR
Quick Diagnosis: Identify the Failure Reason
📌 Version Compatibility: This guide applies to Exchange 2016, Exchange 2019, Exchange 2022. Commands may differ for other versions.
Run these commands in Exchange Management Shell (as Administrator) to diagnose delivery failures:
# Find failed messages in the last 24 hours
Get-MessageTrackingLog -Start (Get-Date).AddHours(-24) -EventId FAIL |
Select-Object Timestamp, Sender, Recipients, MessageSubject, RecipientStatus |
Format-Table -AutoSize
# Search for specific recipient
Get-MessageTrackingLog -Start (Get-Date).AddDays(-7) -Recipients "john@external.com" |
Where-Object {$_.EventId -eq "FAIL"} |
Format-List Timestamp, Sender, Recipients, RecipientStatus, SourceContextWhat to look for:
RecipientStatuscontains the NDR code (e.g., 550 5.1.1)SourceContextprovides additional failure details- Pattern of failures to same domain suggests systemic issue
# View all queues with message counts
Get-Queue | Select-Object Identity, Status, MessageCount, NextHopDomain, LastError |
Where-Object {$_.MessageCount -gt 0} |
Format-Table -AutoSize
# Get details on messages in a specific queue
Get-Queue -Identity "SERVERNAME\Submission" | Get-Message -ResultSize 50 |
Select-Object DateReceived, FromAddress, Status, Recipients, LastError |
Format-Table -AutoSizePro Tip: The LastError field in Get-Queue output often contains the exact SMTP response from the remote server, which is the key to understanding why delivery failed.
# Test MX record lookup for destination domain
Resolve-DnsName -Name "external-company.com" -Type MX
# Test A record for the MX server
$mx = (Resolve-DnsName -Name "external-company.com" -Type MX).NameExchange
Resolve-DnsName -Name $mx -Type A
# Verify DNS servers Exchange is using
Get-TransportService $env:COMPUTERNAME |
Select-Object ExternalDNSServers, InternalDNSServers# Test connectivity to destination mail server
$destServer = "mail.external-company.com"
Test-NetConnection -ComputerName $destServer -Port 25
# Manual SMTP test (basic)
$smtp = New-Object Net.Sockets.TcpClient
try {
$smtp.Connect($destServer, 25)
Write-Host "Connection successful to $destServer on port 25"25"
$smtp.Close()
} catch {
Write-Host "Connection failed: $($_.Exception.Message)"
}# List all send connectors
Get-SendConnector | Select-Object Name, AddressSpaces, SmartHosts, Enabled, DNSRoutingEnabled |
Format-List
# Check connector for specific domain routing
Get-SendConnector | Where-Object {$_.AddressSpaces -like "*external-company.com*"}Quick Fix (10 Minutes) - Based on Failure Type
Fix A: DNS Resolution Issues
# Check current DNS configuration
Get-TransportService $env:COMPUTERNAME |
Select-Object ExternalDNSServers, InternalDNSServers, ExternalDNSAdapterEnabled
# Set reliable external DNS servers (Google/Cloudflare)
Set-TransportService $env:COMPUTERNAME -ExternalDNSServers 8.8.8.8,8.8.4.4 -ExternalDNSAdapterEnabled $true
# Or use custom DNS for external queries
Set-TransportService $env:COMPUTERNAME -ExternalDNSServers 1.1.1.1,9.9.9.9
# Clear DNS cache and restart transport
Clear-DnsClientCache
Restart-Service MSExchangeTransport
# Verify DNS resolution now works
Resolve-DnsName -Name "gmail.com" -Type MXFix B: Relay/Authentication Issues
# Verify SPF record exists for your domain
Resolve-DnsName -Name "company.com" -Type TXT | Where-Object {$_.Strings -like "*spf*"}
# Check if your server IP is blacklisted (manual check required)
# Visit: mxtoolbox.com/blacklists.aspx
# Verify send connector authentication
Get-SendConnector "Internet Send Connector" | Select-Object SmartHostAuthMechanism, AuthenticationCredential
# If using smart host, verify credentials
$cred = Get-Credential
Set-SendConnector "Internet Send Connector" -SmartHostAuthMechanism BasicAuth -AuthenticationCredential $credFix C: Network Connectivity
# Test outbound SMTP connectivity
Test-NetConnection -ComputerName smtp.gmail.com -Port 25
Test-NetConnection -ComputerName smtp.gmail.com -Port 587
# If blocked, check Windows Firewall
Get-NetFirewallRule | Where-Object {$_.DisplayName -like "*SMTP*"} | Format-Table
# Verify connector source IP is correct (multi-homed servers)
Get-SendConnector | Select-Object Name, SourceIPAddress, SourceTransportServers
# Set specific source IP if needed
Set-SendConnector "Internet Send Connector" -SourceIPAddress 192.168.1.50Fix D: Retry Stuck Messages
# Retry all messages in retry state
Get-Queue | Where-Object {$_.Status -eq "Retry"} | Retry-Queue
# Retry specific queue
Retry-Queue -Identity "SERVER\contoso.com"
# Force immediate retry for all queues
Get-Queue | Retry-Queue -Resubmit $trueDetailed Solution: Complex Failure Scenarios
Scenario 1: Specific Domain Failures (Blacklisting)
# Check if your IP is listed on major blacklists
# Run this from a machine with internet access
$serverIP = "YOUR.PUBLIC.IP.ADDRESS"
$blacklists = @(
"zen.spamhaus.org",
"bl.spamcop.net",
"b.barracudacentral.org",
"dnsbl.sorbs.net"
)
foreach ($bl in $blacklists) {
$reversedIP = ($serverIP -split '\.' | ForEach-Object {$_})[-1..-4] -join '.'
$lookup = "$reversedIP.$bl"$bl"
try {
$result = Resolve-DnsName $lookup -ErrorAction Stop
Write-Host "LISTED on $bl" -ForegroundColor Red
} catch {
Write-Host "Not listed on $bl" -ForegroundColor Green
}
}
# If listed, request delisting from the blacklist provider
# Also investigate WHY you were listed (spam, compromised account, etc.)Scenario 2: TLS/Certificate Failures
# Check TLS configuration on send connector
Get-SendConnector | Select-Object Name, RequireTLS, TlsAuthLevel, TlsDomain
# Check if remote server requires TLS
# If connection fails due to certificate issues:
Set-SendConnector "Internet Send Connector" -RequireTLS $false -IgnoreSTARTTLS $true
# Better: Create domain-specific connector with proper TLS
New-SendConnector -Name "Secure Partner Connector" `
-AddressSpaces "SMTP:partner.com;1" `
-RequireTLS $true `
-TlsAuthLevel DomainValidation `
-TlsDomain "mail.partner.com"
# Verify Exchange certificate is valid
Get-ExchangeCertificate | Where-Object {$_.Services -like "*SMTP*"} |
Select-Object Thumbprint, Subject, NotAfter, ServicesScenario 3: Smart Host Configuration Issues
# Check current smart host configuration
Get-SendConnector | Where-Object {$_.SmartHosts} |
Select-Object Name, SmartHosts, SmartHostAuthMechanism
# Configure smart host with authentication
$cred = Get-Credential -Message "Enter SMTP relay credentials"
Set-SendConnector "Internet Send Connector" `
-SmartHosts "smtp-relay.example.com" `
-SmartHostAuthMechanism BasicAuth `
-AuthenticationCredential $cred `
-Port 587 `
-RequireTLS $true
# Test smart host connectivity
Test-NetConnection -ComputerName smtp-relay.example.com -Port 587
# If ISP blocks port 25, use submission port
Set-SendConnector "Internet Send Connector" -Port 587Scenario 4: Message Size Limit Issues
# Check organization-wide limits
Get-TransportConfig | Select-Object MaxReceiveSize, MaxSendSize
# Check send connector limits
Get-SendConnector | Select-Object Name, MaxMessageSize
# Check receive connector limits
Get-ReceiveConnector | Select-Object Name, MaxMessageSize
# Increase limits organization-wide (example: 50MB)
Set-TransportConfig -MaxReceiveSize 50MB -MaxSendSize 50MB
# Increase on specific connector
Set-SendConnector "Internet Send Connector" -MaxMessageSize 50MB
# Note: Remote server may still reject large messages
# Check their bounce message for their limitPro Tip: When increasing message size limits, also check the IIS request limits for OWA/EWS. Large messages sent via web clients may hit IIS limits before Exchange limits.
Verify the Fix
After applying fixes, confirm message delivery is working:
# 1. Send test message to previously failing recipient
Send-MailMessage -From "admin@company.com" -To "test@external.com" `
-Subject "Delivery Test $(Get-Date)" -Body "Testing after Event ID 2004 fix" `
-SmtpServer localhost
# 2. Track the test message
Start-Sleep -Seconds 30
Get-MessageTrackingLog -Start (Get-Date).AddMinutes(-5) -MessageSubject "Delivery Test*" |
Select-Object Timestamp, EventId, Source, Recipients, RecipientStatus |
Format-Table -AutoSize
# 3. Check queues are draining
Get-Queue | Select-Object Identity, Status, MessageCount | Format-Table
# 4. Verify no new FAIL events
Get-MessageTrackingLog -Start (Get-Date).AddMinutes(-30) -EventId FAIL |
Measure-Object | Select-Object Count
# 5. Check Event Viewer for new 2004 events2004 events
Get-EventLog -LogName Application -Source MSExchangeTransport -Newest 50 |
Where-Object {$_.EventID -eq 2004}Success Indicators:
- Test message tracking shows
DELIVERorSENDevent - Queue message counts decreasing
- No new Event ID 2004 entries
- Users confirm emails delivered successfully
- NDR complaints stop from affected recipients
Prevention: Stop Delivery Failures From Recurring
1. Implement Email Authentication (SPF, DKIM, DMARC)
# Check SPF record
Resolve-DnsName -Name "company.com" -Type TXT | Where-Object {$_.Strings -like "*spf*"}
# Should return: "v=spf1 include:_spf.company.com ip4:YOUR.IP.ADDRESS ~all"
# Check DKIM selector
Resolve-DnsName -Name "selector1._domainkey.company.com" -Type TXT
# Check DMARC policy
Resolve-DnsName -Name "_dmarc.company.com" -Type TXT
# Should return: "v=DMARC1; p=quarantine; rua=mailto:dmarc@company.com"2. Monitor Mail Flow Health
# Schedule this to run hourly
$failedMessages = Get-MessageTrackingLog -Start (Get-Date).AddHours(-1) -EventId FAIL
$queueDepth = (Get-Queue | Measure-Object -Property MessageCount -Sum).Sum
if ($failedMessages.Count -gt 10 -or $queueDepth -gt 500) {
$body = "Mail Flow Alert on $env:COMPUTERNAME`n"
$body += "Failed messages (last hour): $($failedMessages.Count)`n"
$body += "Total queue depth: $queueDepth`n"
$body += "`nTop failure reasons:`n"
$body += ($failedMessages | Group-Object RecipientStatus | Sort-Object Count -Descending |
Select-Object -First 5 | Out-String)
Send-MailMessage -To "admin@company.com" -From "alerts@company.com" `
-Subject "Mail Flow Alert - Delivery Failures" -Body $body `
-SmtpServer "backup-smtp.company.com"
}3. Configure Redundant DNS
- Use at least 2 external DNS servers
- Mix providers (e.g., Google 8.8.8.8 + Cloudflare 1.1.1.1)
- Test DNS resolution weekly
4. Proactively Monitor Blacklists
- Sign up for blacklist monitoring (MXToolbox, etc.)
- Get alerts if your IP is listed
- Investigate and remediate within 24 hours
5. Regular Connector Health Checks
# Verify all send connectors are enabled and healthy
Get-SendConnector | Select-Object Name, Enabled, AddressSpaces, DNSRoutingEnabled, SmartHosts
# Check connector statistics
Get-SendConnector | ForEach-Object {
$queue = Get-Queue -Filter "NextHopConnector -eq '$($_.Identity)'"$_.Identity)'"
[PSCustomObject]@{
Connector = $_.Name
Enabled = $_.Enabled
QueuedMessages = ($queue | Measure-Object -Property MessageCount -Sum).Sum
}
}Persistent Delivery Failures? We Can Help.
If messages continue failing despite these troubleshooting steps, you may have complex routing issues, blacklisting requiring negotiation, or hybrid configuration problems. Our mail flow experts resolve these issues daily.
Exchange Mail Delivery TroubleshootingAverage Response Time: 15 Minutes
Frequently Asked Questions
Related Exchange Server Errors
Error 451 4.4.0: DNS Query Failed - Fix Guide 2025
DNS lookup failure preventing email delivery. Fix DNS configuration, MX records, and name resolution.
Error 554 5.4.14: Hop Count Exceeded - Fix Guide 2025
Mail loop detected in Exchange routing. Identify circular routes, fix connectors, stop mail loops.
Event ID 1009: Can't Contact Hub Transport - Fix Guide 2025
Cannot reach Hub Transport server. Fix network connectivity, firewall rules, and service issues.
Can't Resolve Event ID 2004?
Exchange errors can cause data loss or extended downtime. Our specialists are available 24/7 to help.
Emergency help - Chat with usMedha Cloud Exchange Server Team
Microsoft Exchange Specialists
Our Exchange Server specialists have 15+ years of combined experience managing enterprise email environments. We provide 24/7 support, emergency troubleshooting, and ongoing administration for businesses worldwide.