Exchange Common Issues and Troubleshooting
Quick Checklist
When encountering Exchange issues, check in order:
1. Service Status
# Check critical Exchange services
Get-Service MSExchangeTransport, MSExchangeFrontEndTransport, MSExchangeIS, MSExchangeADTopology | Format-Table Name, Status, StartType
# Expected output: all should be "Running" and "Automatic"
2. Event Logs
# Check recent errors in Application log (Exchange-related)
Get-EventLog -LogName Application -Source "MSExchange*" -EntryType Error -Newest 20 | Format-Table TimeGenerated, Source, Message -AutoSize
# Check for specific error IDs
Get-EventLog -LogName Application -Source "MSExchangeTransport" -InstanceId 1035 -Newest 10
3. Certificate Validity
# Check all certificates and their expiration
Get-ExchangeCertificate | Where-Object {$_.NotAfter -lt (Get-Date).AddDays(30)} | Format-Table Thumbprint, Subject, NotAfter -AutoSize
# Check certificate binding
Get-ExchangeCertificate | Where-Object {$_.Services -ne "None"} | Format-List FriendlyName, Services, Thumbprint
4. Database Mount Status
# Check database mount status
Get-MailboxDatabase -Status | Format-Table Name, Server, Mounted, DatabaseSize
# Check for dismounted databases
Get-MailboxDatabase | Where-Object {$_.Mounted -eq $false}
Mail Transport Issues
Mail Queue Buildup
Symptoms:
- Mail delays
- Users report unable to send mail
Diagnosis:
# View all queues
Get-Queue | Format-Table Identity, DeliveryType, Status, MessageCount -AutoSize
# View messages in specific queue
Get-Queue -Identity "servername\queuename" | Get-Message | Format-Table Subject, FromAddress, Status
# Example output showing queue issues:
# Identity DeliveryType Status MessageCount
# -------- ------------ ------ ------------
# EX01\contoso.com SmtpRelay Retry 450
# EX01\Submission Undefined Ready 0
Common Causes and Solutions:
1. DNS Resolution Failure
# Test DNS resolution
Resolve-DnsName mx.contoso.com
# If DNS fails, check:
# - Server's DNS settings
# - External DNS availability
# - Check if using correct DNS server
# Retry queue
Retry-Queue -Identity "EX01\contoso.com" -Resubmit $true
2. TLS Certificate Issues
# Check Send Connector TLS settings
Get-SendConnector | Format-List Name, RequireTLS, TlsAuthLevel, TlsCertificateName
# Common issue: Certificate name mismatch
# Fix: Update TlsCertificateName (see cert-tls.md for details)
3. Target Server Rejecting Connection
# Get detailed error from queue
Get-Queue -Identity "EX01\contoso.com" | Format-List *Error*
# Example error:
# LastError: 451 4.4.0 Primary target IP address responded with: "550 5.7.1 Relaying denied"
# Solution: Check SPF/DKIM/DMARC, IP reputation
Manually Clear Poison Queue:
# View poison queue
Get-Queue -Filter {Status -eq "Suspended"}
# Remove messages from poison queue (use with caution)
Get-Queue -Identity "EX01\Poison" | Get-Message | Remove-Message -WithNDR $false
Message Tracking
# Track specific message by sender
Get-MessageTrackingLog -Start (Get-Date).AddHours(-24) -Sender user@contoso.com | Format-Table Timestamp, EventId, Source, Recipients -AutoSize
# Track by Message-ID (from email header)
Get-MessageTrackingLog -MessageId "<abc123@contoso.com>" | Format-List
# Common EventId values:
# RECEIVE - Message received
# SEND - Message sent to next hop
# DELIVER - Message delivered to mailbox
# FAIL - Delivery failed
# DEFER - Delivery deferred (retry later)
Real Example: Tracking Unreceived Mail
# User reports not receiving email from external@example.com sent today
Get-MessageTrackingLog -Start (Get-Date).Date -Sender external@example.com -Recipients user@contoso.com | Format-Table Timestamp, EventId, Source, MessageSubject
# If no results:
# 1. Check MX record → mail should route to your server
# 2. Check firewall → port 25 inbound
# 3. Check sender's logs → did they actually send?
# If shows RECEIVE but no DELIVER:
# 1. Check transport rules
# 2. Check anti-spam quarantine
# 3. Check mailbox rules
Client Connection Issues
Outlook Cannot Connect
Symptoms:
- Outlook shows "Trying to connect"
- Repeated password prompts
Troubleshooting Steps:
1. Check Autodiscover
# Check Autodiscover service
Test-OutlookWebServices -Identity user@contoso.com | Format-List
# Check Autodiscover virtual directory
Get-AutodiscoverVirtualDirectory | Format-List Server, InternalUrl, ExternalUrl
# Expected:
# InternalUrl: https://mail.contoso.com/Autodiscover/Autodiscover.xml
# ExternalUrl: https://mail.contoso.com/Autodiscover/Autodiscover.xml
Test Autodiscover from Client:
1. Hold Ctrl + Right-click Outlook icon in system tray
2. Select "Test E-mail AutoConfiguration"
3. Uncheck "Use Guessmart" and "Secure Guessmart Authentication"
4. Check "Use Autodiscover"
5. Click "Test"
Look for errors in:
- Autodiscover XML response
- HTTP response codes (should be 200)
2. Check MAPI/HTTP
# Check if MAPI/HTTP is enabled (Exchange 2013 SP1+)
Get-OrganizationConfig | Format-List MapiHttpEnabled
# Should be: True (recommended)
# Check mailbox MAPI connectivity
Test-MapiConnectivity -Identity user@contoso.com
3. Check Certificates
# Common issue: Certificate name mismatch
# Outlook connects to: mail.contoso.com
# Certificate Subject/SAN must include: mail.contoso.com
Get-ExchangeCertificate | Where-Object {$_.Services -match "IIS"} | Format-List Subject, CertificateDomains, NotAfter
OWA/ECP Inaccessible
# Check IIS application pools
Get-WebAppPoolState "MSExchangeOWAAppPool", "MSExchangeECPAppPool"
# If stopped, start them:
Start-WebAppPool "MSExchangeOWAAppPool"
Start-WebAppPool "MSExchangeECPAppPool"
# Check virtual directories
Get-OwaVirtualDirectory | Format-List Server, InternalUrl, ExternalUrl
Get-EcpVirtualDirectory | Format-List Server, InternalUrl, ExternalUrl
# Test OWA
Test-OwaConnectivity -URL https://mail.contoso.com/owa
Database Issues
Database Cannot Mount
Example Error Message:
An error occurred while mounting database "Mailbox Database 01". Error: MapiExceptionDatabaseError: Unable to mount database.
Troubleshooting Steps:
# 1. Check database status
Get-MailboxDatabase "Mailbox Database 01" -Status | Format-List Name, Mounted, MountedOnServer, LastFullBackup
# 2. Check event log for specific error
Get-EventLog -LogName Application -Source "MSExchangeIS" -EntryType Error -Newest 10 | Format-List
# Common errors and solutions:
# Error -1018 (JET_errReadVerifyFailure) → Database corruption
# Solution: Run eseutil /g to check, then eseutil /p to repair (LAST RESORT)
# Error -1216 (JET_errAttachedDatabaseMismatch) → Log file mismatch
# Solution: Replay logs or restore from backup
Database Repair (Very Dangerous, Last Resort Only):
# 1. Dismount database (if not already)
Dismount-Database "Mailbox Database 01" -Confirm:$false
# 2. Check database integrity
eseutil /g "E:\Databases\DB01\DB01.edb"
# If integrity check fails:
# 3. (DANGEROUS) Repair database - THIS WILL CAUSE DATA LOSS
eseutil /p "E:\Databases\DB01\DB01.edb"
# 4. Defragment
eseutil /d "E:\Databases\DB01\DB01.edb"
# 5. Try to mount
Mount-Database "Mailbox Database 01"
Warning
eseutil /p will cause data loss! Only use when no backup is available and data loss is acceptable. Restoring from backup should be the priority.
Database Low on Space
# Check database size and available space
Get-MailboxDatabase -Status | Select-Object Name, Server, DatabaseSize, AvailableNewMailboxSpace | Format-Table -AutoSize
# Check drive space
Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3" | Select-Object DeviceID, @{Name="Size(GB)";Expression={[math]::Round($_.Size/1GB,2)}}, @{Name="Free(GB)";Expression={[math]::Round($_.FreeSpace/1GB,2)}}
# If space is low:
# 1. Run full backup (enables log truncation)
# 2. Remove old log files (only AFTER successful backup)
# 3. Consider circular logging (NOT recommended for production)
Performance Issues
High CPU Usage
# Identify process consuming CPU
Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 ProcessName, CPU, WorkingSet
# Common culprits:
# - Microsoft.Exchange.Store.Worker.exe (Store process)
# - EdgeTransport.exe (Transport service)
# - w3wp.exe (IIS worker process)
# If Store.Worker is high:
# 1. Check for specific problematic mailbox
Get-StoreUsageStatistics -Server EX01 | Sort-Object -Property LogRecordBytes -Descending | Select-Object -First 10
# 2. Consider moving problematic mailbox to another database
New-MoveRequest -Identity problematicuser@contoso.com -TargetDatabase "Mailbox Database 02"
Slow Mail Transport
# Check message latency
Get-Queue | Measure-Object -Property MessageCount -Sum
# Check transport config
Get-TransportServer | Format-List MaxOutboundConnections, MaxPerDomainOutboundConnections
# Increase concurrent connections (if needed)
Set-TransportServer EX01 -MaxOutboundConnections 5000 -MaxPerDomainOutboundConnections 50
Tools and Logs
Important Log Locations
Transport Logs:
%ExchangeInstallPath%TransportRoles\Logs\MessageTracking\
Protocol Logs (SMTP):
%ExchangeInstallPath%TransportRoles\Logs\FrontEnd\ProtocolLog\
IIS Logs:
%SystemDrive%\inetpub\logs\LogFiles\W3SVC1\
Event Logs:
Application (Source: MSExchange*)
Useful Diagnostic Tools
# Exchange Best Practice Analyzer (ExBPA) - for 2010/2013
# Deprecated, replaced by:
# Test Exchange health
Test-ServiceHealth
Test-SystemHealth
# Test replication health (DAG)
Test-ReplicationHealth
# Collect diagnostic data
Get-ServerHealth EX01 | Format-List
# Export all Exchange config for documentation
Get-ExchangeServer | Export-Clixml C:\Backup\ExchangeConfig.xml
Emergency Rollback Procedures
If Issues Occur After CU Update
1. Verify backup integrity
2. Uninstall CU (Control Panel → Programs and Features → Microsoft Exchange Server → Uninstall)
3. Restart server
4. Verify service status
5. Test mail flow and client connectivity
Note: CU uninstallation requires restart, plan maintenance window
Database Restore
# Example: Restore from Windows Server Backup
wbadmin get versions -backupTarget:D:
wbadmin start recovery -version:<VersionIdentifier> -itemType:App -items:Exchange -recoverytarget:E:\Databases\Restored\
# After restore, mount as recovery database
New-MailboxDatabase -Name "RecoveryDB" -EdbFilePath "E:\Databases\Restored\DB01.edb" -LogFolderPath "E:\Databases\Restored\" -Recovery
Mount-Database "RecoveryDB"
# Extract mailbox from recovery database
New-MailboxRestoreRequest -SourceDatabase "RecoveryDB" -SourceStoreMailbox "user" -TargetMailbox user@contoso.com
Preventive Maintenance
Regular Checks
- Daily: Check event log errors
- Weekly: Check database backup success
- Weekly: Check mail queue status
- Monthly: Check certificate expiration
- Monthly: Check disk space
- Quarterly: Check CU update status
- Annually: Test disaster recovery procedures
Automated Monitoring Script Example
# Save as: Check-ExchangeHealth.ps1
param(
[string]$Server = $env:COMPUTERNAME,
[string]$EmailTo = "admin@contoso.com"
)
$issues = @()
# Check services
$services = "MSExchangeTransport", "MSExchangeFrontEndTransport", "MSExchangeIS"
foreach ($svc in $services) {
$status = Get-Service $svc -ErrorAction SilentlyContinue
if ($status.Status -ne "Running") {
$issues += "Service $svc is $($status.Status)"
}
}
# Check queues
$queues = Get-Queue | Where-Object {$_.MessageCount -gt 100}
if ($queues) {
$issues += "High queue count: $($queues.Identity) has $($queues.MessageCount) messages"
}
# Check disk space
$disks = Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3" | Where-Object {($_.FreeSpace/$_.Size)*100 -lt 15}
foreach ($disk in $disks) {
$issues += "Low disk space on $($disk.DeviceID): $(([math]::Round(($disk.FreeSpace/$disk.Size)*100,2)))% free"
}
# Send alert if issues found
if ($issues) {
$body = $issues -join "`r`n"
Send-MailMessage -To $EmailTo -From "exchange-monitor@contoso.com" -Subject "Exchange Health Alert - $Server" -Body $body -SmtpServer "mail.contoso.com"
}