Chuyển tới nội dung chính

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"
}