Microsoft Exchange Server — Complete Guide
Architecture Overview
Modern Exchange (2013+) uses a simplified two-role architecture (Edge Transport is separate):
Mailbox Server Role (the core — runs everything in Exchange 2016/2019):
- Hosts mailbox databases (.edb files) — stores all email, calendar, contacts
- Runs the Transport Service (internal mail routing and processing)
- Runs Client Access services (handles all client protocol connections)
- Provides High Availability via Database Availability Groups (DAGs)
Client Access Services (sub-component of Mailbox role, not a separate server role since Exchange 2016):
- MAPI over HTTP — Outlook client protocol
- Exchange Active Sync (EAS) — mobile device email
- Exchange Web Services (EWS) — programmatic access (calendaring, tasks)
- OWA (Outlook Web App/Access) — browser-based email
- IMAP4 / POP3 — legacy protocols (disabled by default in modern installs)
- AutoDiscover — client configuration endpoint
Edge Transport Server (optional, deployed in the perimeter/DMZ):
- Receives inbound mail from the internet before it reaches Mailbox servers
- Sends outbound mail to the internet
- Runs anti-spam and anti-malware filtering at the perimeter
- Not domain-joined — uses EdgeSync to receive configuration from internal Exchange
Database Availability Groups (DAG)
DAGs provide mailbox database high availability through continuous replication (log shipping) and automatic failover. Up to 16 members per DAG.
# DAG overview
Get-DatabaseAvailabilityGroup -Status | Select Name, Servers, WitnessServer, OperationalServers
Get-MailboxDatabase -Status | Select Name, Mounted, Server, DatabaseSize, AvailableNewMailboxSpace
# Database copy health — check replication status
Get-MailboxDatabaseCopyStatus -Server EX01 | Select Name, Status, CopyQueueLength, ReplayQueueLength, ContentIndexState
# Red flags: Status = Failed, CopyQueueLength > 0 (replication lag), ContentIndexState = Failed
# Suspend and resume a database copy (for maintenance)
Suspend-MailboxDatabaseCopy -Identity "DB01\EX02" -SuspendComment "Planned maintenance"
Resume-MailboxDatabaseCopy -Identity "DB01\EX02"
# Manual failover — move active database to another DAG member
Move-ActiveMailboxDatabase -Identity DB01 -ActivateOnServer EX02 -Confirm:$false
# Test DAG replication health
Test-ReplicationHealth -Server EX01
Core Mailbox Management
# Get mailbox details
Get-Mailbox [email protected]
Get-Mailbox [email protected] | Select * # All properties
Get-Mailbox -ResultSize Unlimited | Select DisplayName, PrimarySmtpAddress, Database, RecipientTypeDetails
# Create new mailbox (creates AD user + mailbox)
New-Mailbox -UserPrincipalName [email protected] -Alias jsmith -Name "Jane Smith" `
-Database DB01 -Password (ConvertTo-SecureString "P@ssword1!" -AsPlainText -Force) `
-ResetPasswordOnNextLogon $true
# Mailbox quotas
Set-Mailbox [email protected] `
-IssueWarningQuota 9GB `
-ProhibitSendQuota 9.5GB `
-ProhibitSendReceiveQuota 10GB
# Mailbox statistics
Get-MailboxStatistics [email protected] | Select DisplayName, TotalItemSize, ItemCount, LastLogonTime
# Find the largest mailboxes in the org
Get-Mailbox -ResultSize Unlimited | Get-MailboxStatistics | `
Sort TotalItemSize -Descending | Select -First 20 DisplayName, TotalItemSize, ItemCount, Database
# Disable vs Remove mailbox
Disable-Mailbox [email protected] # Disconnects mailbox from AD user, retains database object for 30 days
Remove-Mailbox [email protected] -Confirm:$false # Disables + marks AD user for deletion
# Reconnect a disconnected mailbox to a user
Connect-Mailbox -Identity "Jane Smith" -Database DB01 -User "corp\jsmith" -Alias jsmith
# Client access settings (protocols per mailbox)
Set-CASMailbox [email protected] -OWAEnabled $true -ActiveSyncEnabled $false -IMAPEnabled $false
Get-CASMailbox [email protected] | Select OWAEnabled, ActiveSyncEnabled, MAPIEnabled, IMAPEnabled, POPEnabled
Transport Rules
Transport rules (mail flow rules) apply to email as it passes through the transport pipeline.
# List all transport rules
Get-TransportRule | Select Name, State, Priority | Sort Priority
# Create a disclaimer rule (appended to all outbound email)
New-TransportRule -Name "External Disclaimer" `
-SentToScope NotInOrganization `
-ApplyHtmlDisclaimerText "<p>This email is confidential...</p>" `
-ApplyHtmlDisclaimerLocation Append `
-ApplyHtmlDisclaimerFallbackAction Wrap
# Block external email forwarding (common security control)
New-TransportRule -Name "Block External Auto-Forward" `
-MessageTypeMatches AutoForward `
-SentToScope NotInOrganization `
-RejectMessageReasonText "Auto-forwarding email outside the organization is not permitted." `
-RejectMessageEnhancedStatusCode 5.7.1
# Flag external sender in subject (email client visual warning)
New-TransportRule -Name "External Sender Warning" `
-FromScope NotInOrganization `
-PrependSubject "[EXTERNAL] "
# Enable/disable/remove a rule
Enable-TransportRule -Identity "External Disclaimer"
Disable-TransportRule -Identity "Block External Auto-Forward"
Remove-TransportRule -Identity "Old Rule" -Confirm:$false
Mail Flow Tracking and Queue Management
# Message tracking — find where a message went
Get-MessageTrackingLog -Sender [email protected] -Start (Get-Date).AddDays(-1) `
-EventId DELIVER | Select Timestamp, Sender, Recipients, MessageSubject, Source
Get-MessageTrackingLog -Recipients [email protected] -Start (Get-Date).AddHours(-6) `
| Select Timestamp, Sender, MessageSubject, EventId
# Test internal mail flow (sends a test message between mailboxes)
Test-Mailflow -TargetMailboxServer EX01
# Transport queue management
Get-Queue # View all queues
Get-Queue -Server EX01 | Where MessageCount -gt 0 # Queues with messages
Get-Message -Queue EX01\Submission | Select FromAddress, Subject, Status
Retry-Queue -Identity "EX01\Unreachable" # Force retry a stuck queue
Suspend-Queue -Identity "EX01\Poison" # Suspend a queue for investigation
Get-Message -Queue "EX01\Contoso.com" | Remove-Message -WithNDR $false # Drain a queue
OWA and Client Access
# OWA virtual directories
Get-OwaVirtualDirectory -Server EX01 | Select Name, InternalUrl, ExternalUrl, *Authentication*
Set-OwaVirtualDirectory -Identity "EX01\OWA (Default Web Site)" `
-ExternalUrl "https://mail.corp.com/owa" -InternalUrl "https://mail.corp.local/owa"
# EWS virtual directory
Get-WebServicesVirtualDirectory | Select Server, InternalUrl, ExternalUrl
Set-WebServicesVirtualDirectory -Identity "EX01\EWS (Default Web Site)" `
-ExternalUrl "https://mail.corp.com/EWS/Exchange.asmx"
# Force Outlook Anywhere settings
Get-OutlookAnywhere | Select Server, ExternalHostname, InternalHostname, *Authentication*
# Certificate binding (after importing a new SSL cert)
Get-ExchangeCertificate | Select Thumbprint, Subject, NotAfter, Services
Enable-ExchangeCertificate -Thumbprint "ABCDEF123..." -Services SMTP, IIS, IMAP -Force
Health Monitoring
# Service health check — all Exchange services on all servers
Get-ExchangeServer | Test-ServiceHealth
# Detailed health report per server
Get-HealthReport -Server EX01
# Exchange diagnostic info
Get-ExchangeDiagnosticInfo -Server EX01 -Process EdgeTransport -Component ResourceThrottling
# Database mount status (critical daily check)
Get-MailboxDatabase -Status | Select Name, Mounted, Server | Where Mounted -eq $false
# DAG replication health
Test-ReplicationHealth -Server EX01 | Where Result -ne "Passed"
# Component state (throttling, maintenance mode)
Get-ServerComponentState -Identity EX01 | Where State -ne "Active"
Certificate Management
# List all Exchange certificates
Get-ExchangeCertificate | Select Thumbprint, Subject, Issuer, NotAfter, Services
# Check for expiring certs (within 30 days)
Get-ExchangeCertificate | Where { $_.NotAfter -lt (Get-Date).AddDays(30) } `
| Select Subject, NotAfter, Services
# Generate a new certificate request (CSR) for a CA
New-ExchangeCertificate -GenerateRequest -SubjectName "CN=mail.corp.com" `
-DomainName mail.corp.com, autodiscover.corp.com, owa.corp.com `
-PrivateKeyExportable $true `
-Path C:\cert-request.req
# After receiving the signed cert from CA, import it
Import-ExchangeCertificate -FileData ([Byte[]]$(Get-Content -Path C:\signed-cert.p7b -Encoding byte -ReadCount 0))
# Bind to Exchange services
Enable-ExchangeCertificate -Thumbprint "NEWTHUMBPRINT" -Services SMTP, IIS -Force
Security — Critical Vulnerabilities
Exchange has been heavily targeted. Every Exchange admin must know these:
ProxyLogon — CVE-2021-26855, 26857, 26858, 27065 (March 2021)
Exploited in the wild by HAFNIUM (Chinese state actor) and rapidly weaponized by others. CVE-2021-26855 is a Server-Side Request Forgery (SSRF) flaw in the Exchange frontend allowing pre-authentication access to backend services. Combined with CVE-2021-26857 (insecure deserialization), CVE-2021-26858, and CVE-2022-27065 (post-auth file write) attackers achieved unauthenticated RCE and dropped webshells. Patched March 2021 — apply immediately if unpatched.
ProxyShell — CVE-2021-34473, 34523, 31207 (August 2021)
Three-bug chain: URL path confusion for auth bypass (34473) + privilege escalation via EWS (34523) + remote code execution via PowerShell backend (31207). Allowed unauthenticated RCE on all unpatched Exchange servers exposed to the internet. Exploited within days of public disclosure. Patched July 2021.
ProxyNotShell — CVE-2022-41040, 41082 (November 2022)
Requires valid credentials (lower bar in orgs with password spray). CVE-2022-41040 is SSRF via autodiscover; CVE-2022-41082 is RCE via PowerShell backend. Similar attack chain to ProxyShell but post-authentication. Patched November 2022.
Post-compromise check — look for webshells:
# Check known webshell drop locations
Get-ChildItem -Path "C:\inetpub\wwwroot\aspnet_client\" -Recurse -Include *.aspx, *.ashx
Get-ChildItem -Path "C:\Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\" -Recurse -Include *.aspx
Get-ChildItem -Path "C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\OWA\auth\" -Include *.aspx
# Check IIS logs for exploitation indicators (ProxyLogon path)
Select-String -Path "C:\inetpub\logs\LogFiles\W3SVC1\*.log" `
-Pattern "autodiscover|/owa/auth.*\.js$|X-AnonResource-Backend" | Select -First 50
Security Hardening
# Enable audit logging (required — off by default in older versions)
Set-AdminAuditLogConfig -AdminAuditLogEnabled $true -AdminAuditLogCmdlets * -AdminAuditLogParameters *
# Search admin audit log
Search-AdminAuditLog -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) `
| Select RunDate, Caller, CmdletName, ObjectModified | Sort RunDate -Descending
# Enable mailbox audit logging for specific users or all mailboxes
Set-Mailbox -Identity [email protected] -AuditEnabled $true `
-AuditOwner MailboxLogin, HardDelete, SoftDelete `
-AuditDelegate SendAs, SendOnBehalf, MoveToDeletedItems `
-AuditAdmin Copy, MessageBind
# Disable legacy authentication (Basic auth for OWA — use Modern Auth/OAuth instead)
# Enforce via authentication policy:
New-AuthenticationPolicy -Name "Block Legacy Auth" -AllowBasicAuthOWA $false `
-AllowBasicAuthActiveSync $false -AllowBasicAuthWebServices $false
Set-OrganizationConfig -DefaultAuthenticationPolicy "Block Legacy Auth"
# Enable Extended Protection on virtual directories (hardens auth against relay)
Get-VirtualDirectory | Set-VirtualDirectory -ExtendedProtectionTokenChecking Require
# Restrict EAC (Exchange Admin Center) access by IP via IIS IP restrictions or WAF
# Disable POP3 and IMAP if not required
Stop-Service -Name MSExchangeIMAP4, MSExchangePOP3 -Force
Set-Service -Name MSExchangeIMAP4, MSExchangePOP3 -StartupType Disabled
Exchange Online (Microsoft 365)
Most new deployments are Exchange Online. Key differences for admins:
# Connect
Install-Module ExchangeOnlineManagement -Scope CurrentUser
Connect-ExchangeOnline -UserPrincipalName [email protected]
# Same cmdlets work: Get-Mailbox, Set-Mailbox, Get-MessageTrackingLog (→ Get-MessageTrace in EXO)
Get-MessageTrace -SenderAddress [email protected] -StartDate (Get-Date).AddDays(-1) -EndDate (Get-Date)
# Security is managed via Microsoft Defender for Office 365 (MDO)
# Anti-phishing, safe links, safe attachments configured via Security & Compliance Center
# Modern Auth enforced by default; disable Basic auth via authentication policies
Admin portals: Exchange Admin Center at admin.exchange.microsoft.com, Microsoft 365 Admin Center at admin.microsoft.com, Defender for Office 365 at security.microsoft.com.