Exchange Web Services (EWS) still carries many on-premises integrations: CRM and calendar sync, room booking, backup, archiving and migration tools. When they fail, the error is usually a 401, a 503, a throttling response or an impersonation refusal, and each points at a different layer. In this post I'll map each error to its cause, show where Exchange logs it, and fix it from the Exchange Management Shell.
Errors this guide fixes
The remote server returned an error: (401) Unauthorized.App log / integration error+1 more guideThe remote server returned an error: (503) Server Unavailable.App log / integration errorErrorServerBusy: The server cannot service this request right now. Try again later.EWS responseErrorExceededConnectionCountEWS responseErrorImpersonateUserDenied: The account does not have permission to impersonate the requested user.EWS response+1 more guideErrorExceededSubscriptionCountEWS response
Note: Microsoft's EWS retirement covers Exchange Online, not EWS on Exchange Server. If your apps also talk to Exchange Online, see EWS switch-off in Exchange Online.
Symptoms#
The application's log or error dialog shows one of these:
The remote server returned an error: (401) Unauthorized.
The remote server returned an error: (503) Server Unavailable.
ErrorServerBusy: The server cannot service this request right now. Try again later.
ErrorExceededConnectionCount
ErrorImpersonateUserDenied: The account does not have permission to impersonate the requested user.- 401 and 503 are HTTP status codes and show up in the IIS log against
POST /EWS/Exchange.asmx. - EWS errors such as
ErrorServerBusyandErrorImpersonateUserDeniedarrive inside a SOAP response that can carry HTTP 500, so a 500 for EWS usually means "read the response body", not "the server crashed". - Throttling errors cluster at busy times; impersonation errors hit some mailboxes and not others.
Why it happens#
| Error | Layer | Usual causes |
|---|---|---|
| 401 | Authentication | Wrong, expired or locked service account; app needs Basic but it's off on the EWS virtual directory; Windows authentication through a TLS-terminating device with Extended Protection on; expired Auth certificate for OAuth |
| 503 | Availability | EWS app pool stopped or crashing; server left in maintenance mode; load balancer sending traffic to a drained server |
ErrorServerBusy, ErrorExceededConnectionCount | Throttling | App exceeds its budget or concurrent connections; Exchange also slows EWS callers while a resource such as a mailbox database is unhealthy |
ErrorImpersonateUserDenied | Permissions | Service account lacks the ApplicationImpersonation role, or the mailbox is outside its scope |
How to fix it#
1. Find the failing requests#
$ews = Join-Path $env:ExchangeInstallPath "Logging\Ews"
Get-ChildItem $ews | Sort-Object LastWriteTime | Select-Object -Last 3 | Select-String "svc-crm" | Select-Object -Last 20
Get-ChildItem C:\inetpub\logs\LogFiles\W3SVC1\*.log | Sort-Object LastWriteTime | Select-Object -Last 1 |
Select-String "/EWS/Exchange.asmx" | Select-Object -Last 20The EWS log on the server that processed the request records the calling account and the outcome, so searching for the service account or an error code finds failures quickly; Logging\HttpProxy\Ews holds the front-end view. In the IIS log, a 401 followed by a 200 is the normal authentication handshake. Repeated 401s with an empty username mean the app never authenticates.
2. Fix 401 Unauthorized#
Get-WebServicesVirtualDirectory -Server EX01 | Format-List Server, InternalUrl, ExternalUrl, *Authentication*- Keep Windows authentication enabled, and OAuth if you use hybrid features. If an app can only do Basic, it fails until you run
Set-WebServicesVirtualDirectory "EX01\EWS (Default Web Site)" -BasicAuthentication $true; do that only if you must, and only over HTTPS. - Check the service account for lockouts, expired passwords and "must change password" flags, then test it with the request in Verify the fix.
- If the app reaches Exchange through a load balancer or proxy that terminates TLS, Extended Protection breaks Windows authentication.
- OAuth-based apps and hybrid features fail once the Auth certificate expires; see renewing the Auth certificate.
3. Fix 503 Server Unavailable#
Get-ServerComponentState EX01 | Where-Object State -ne "Active" | Format-Table Component, State
Import-Module WebAdministration
Get-ChildItem IIS:\AppPools | Where-Object { $_.Name -like "MSExchange*" } | Select-Object Name, State
Get-HealthReport EX01 | Where-Object { $_.HealthSet -like "EWS*" } | Format-Table HealthSet, AlertValueForwardSyncDaemon and ProvisioningRps are normally Inactive. Anything else Inactive, such as ServerWideOffline, means the server is still in maintenance mode; bring it back with the exit steps in DAG maintenance mode. Restart-WebAppPool MSExchangeServicesAppPool recycles the back-end EWS app pool. On the load balancer, probe /ews/healthcheck.htm so a server with a broken EWS stack leaves the pool.
4. Fix throttling errors#
Get-ThrottlingPolicyAssociation svc-crm | Format-List
Get-ThrottlingPolicy | Format-Table Name, IsDefault, ThrottlingPolicyScope, EwsMaxConcurrency, EwsMaxSubscriptions -AutoSize
New-ThrottlingPolicy -Name "EWS-svc-crm" -ThrottlingPolicyScope Regular -EwsMaxConcurrency 50 -EwsMaxSubscriptions 500
Set-ThrottlingPolicyAssociation -Identity svc-crm -ThrottlingPolicy "EWS-svc-crm"ErrorExceededConnectionCount maps to EwsMaxConcurrency and ErrorExceededSubscriptionCount to EwsMaxSubscriptions. ErrorServerBusy means Exchange is pushing back; since Exchange 2013 the response suggests a wait time (BackOffMilliseconds) that a well-behaved app honours. The values above are examples: size them with the vendor, apply the policy only to the service account, and leave the default policy protecting everyone else. If the errors coincide with database or disk problems, higher limits won't help; fix the resource.
5. Fix ErrorImpersonateUserDenied#
Get-ManagementRoleAssignment -Role ApplicationImpersonation -GetEffectiveUsers |
Format-Table EffectiveUserName, CustomRecipientWriteScope -AutoSize
New-ManagementScope -Name "CRM mailboxes" -RecipientRestrictionFilter "MemberOfGroup -eq 'CN=CRM Users,OU=Groups,DC=contoso,DC=com'"
New-ManagementRoleAssignment -Name "Impersonation-svc-crm" -Role ApplicationImpersonation -User svc-crm `
-CustomRecipientWriteScope "CRM mailboxes"The error means the assignment is missing or the target mailbox is outside its scope. Allow for AD replication after a change. Exchange Online has retired this role, but Exchange Server still uses it. Ask the vendor to send an X-AnchorMailbox header with the impersonated address, which Microsoft recommends for impersonation.
Verify the fix#
Send one real request as the service account. Remove the ExchangeImpersonation element to test the credentials alone:
$soap = @'
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
<soap:Header>
<t:RequestServerVersion Version="Exchange2013_SP1" />
<t:ExchangeImpersonation><t:ConnectingSID><t:PrimarySmtpAddress>jane@contoso.com</t:PrimarySmtpAddress></t:ConnectingSID></t:ExchangeImpersonation>
</soap:Header>
<soap:Body>
<m:GetFolder>
<m:FolderShape><t:BaseShape>IdOnly</t:BaseShape></m:FolderShape>
<m:FolderIds><t:DistinguishedFolderId Id="inbox" /></m:FolderIds>
</m:GetFolder>
</soap:Body>
</soap:Envelope>
'@
$r = Invoke-WebRequest -Uri https://mail.contoso.com/EWS/Exchange.asmx -Method Post -Body $soap -UseBasicParsing `
-ContentType "text/xml; charset=utf-8" -Credential (Get-Credential contoso\svc-crm) -Headers @{ "X-AnchorMailbox" = "jane@contoso.com" }
([xml]$r.Content).Envelope.Body.GetFolderResponse.ResponseMessages.GetFolderResponseMessage.ResponseCode- Good is
NoError. A mailbox outside the scope should fail withErrorImpersonateUserDenied, which proves the scope works. (Windows PowerShell treats that HTTP 500 as an error; in PowerShell 7, add-SkipHttpErrorCheckto read the body.) - The IIS log shows the service account's requests returning 200, and the EWS log shows no new
ErrorServerBusyentries at peak times.
Prevent it next time#
- Use one service account per app and record its impersonation scope and throttling policy.
- Probe
/ews/healthcheck.htmon the load balancer, and check component states after every update. - Track the Auth certificate's expiry date.
- Inventory EWS apps before you move mailboxes to Exchange Online.

