---
title: "EWS retirement: migrate to Microsoft Graph · Workwae"
description: "Exchange Online EWS retirement: the October 2026 and April 2027 dates, EWSEnabled and the AppID allow list, EWS to Microsoft Graph mapping, permissions and gaps."
url: https://workwae.com/blog/ews-retirement-microsoft-graph
---

Blog

# Exchange Web Services is being retired: moving to Microsoft Graph.

EWS in Exchange Online is being switched off tenant by tenant. This is the timeline, how to tell if it is your integration, and what moves where in Graph.

October 30, 2026 · 9 min read

- [Microsoft Graph](https://workwae.com/blog/tag/microsoft-graph)
- [Migration](https://workwae.com/blog/tag/migration)

Microsoft started turning off Exchange Web Services (EWS) in Exchange Online on October 1, 2026. Tenants that never set `EWSEnabled` are being switched to `False` as the rollout reaches them, and an integration that was working last week now gets `403 Forbidden`. Admins can still switch EWS back on until April 1, 2027, and then it is gone for good. This post is for the developer who owns that integration: what was announced, how to tell whether it is yours, how EWS operations, permissions and notifications map to Microsoft Graph, and where Graph still falls short. Dates and limits are as of October 30, 2026 and come from Microsoft’s own pages, linked inline.

## What Microsoft announced.

- **2018 and 2023.** EWS stopped receiving feature updates in 2018, and in 2023 Microsoft said it would be disabled in Exchange Online in October 2026 ([Deprecation of EWS in Exchange Online](https://learn.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/deprecation-of-ews-exchange-online)).
- **October 1, 2026.** Phased, tenant-by-tenant disablement starts. A tenant with `EWSEnabled` still `Null` is changed to `False` as the rollout reaches it, which blocks EWS for every application in the tenant. A tenant that set an AppID allow list and `EWSEnabled=True` by the end of September was excluded from that change ([Exchange Online EWS, Your Time is Almost Up](https://techcommunity.microsoft.com/blog/exchange/exchange-online-ews-your-time-is-almost-up/4492361)).
- **April 1, 2027.** EWS is disabled for good and tenant admins lose the switch. Microsoft’s FAQ says there will be no exceptions past that date.

The retirement covers Exchange Online in all environments. Exchange Server on premises keeps EWS: “there are no changes to EWS in Exchange Server,” and on-premises mailboxes can keep using it while cloud mailboxes must move to Graph. These pages give no separate EWS date for sovereign clouds. Microsoft’s parity roadmap does list “Sovereign Cloud availability” of the Exchange APIs needed for EWS migration as a Q4 2026 target, so check that a Graph feature exists in your tenant’s cloud before you rely on it.

## Check whether you are affected.

A blocked EWS request returns `403 Forbidden` with an `X-EWS-Policy-Reason` header, which says why ([Control access to EWS](https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-control-access-to-ews-in-exchange)):

| Header value | Meaning |
| --- | --- |
| `EWS is disabled for this user or tenant` | The organization or mailbox `EwsEnabled` setting blocks the request. |
| `EWS is blocked by policy for this user or tenant` | An application access policy blocks it: the app ID is not in `EwsAllowedAppIDs`, or its user agent fails the older allow or block list. The header does not say which. |

A 403 alone does not prove EWS was the cause, since other access restrictions also return it. Clients that do not read the header show other symptoms; Microsoft lists repeated credential prompts and an error that EWS is unavailable ([EWS application stopped working? Do this.](https://techcommunity.microsoft.com/blog/exchange/exchange-online-ews-application-stopped-working-do-this-/4566215)).

The tenant admin sees the change in the Message Center, in posts titled “Action may be required: EWS will be disabled in your tenant in 7 days” or “EWS has been disabled in your tenant.” The admin center also has an EWS usage report that lists the app IDs calling EWS. If you ship software to other companies, you cannot see their tenants, so expect support tickets from admins who can.

## The tenant controls.

Two settings decide whether EWS works for an app. The organization-level `EWSEnabled` is `True`, `False` or `Null` (the default, which behaves as `True`), and `EWSAllowedAppIDs` is a list of application IDs ([Introducing EWSAllowedAppIDs](https://techcommunity.microsoft.com/blog/exchange/introducing-ewsallowedappids-preparing-for-the-final-phase-of-ews-retirement/4529471)). Since October 2026:

| `EWSEnabled` | AppID allow list | Result |
| --- | --- | --- |
| `Null` | Ignored | All EWS allowed, until Microsoft changes the tenant to `False` |
| `True` | Empty | All EWS blocked |
| `True` | Populated | Only listed apps allowed |
| `False` | Any | All EWS blocked |

Cross-tenant organization relationships keep working in the blocked rows. Microsoft said it would fill the allow list for tenants that had none, from each tenant’s EWS use over the last 60 days, and an admin who builds their own list keeps it unchanged. Changes to the list can take up to 24 hours to apply.

If a customer asks you to get their integration working again today, the admin has two routes, and Microsoft support cannot do either for them. In the admin center’s Baseline Security Mode page, clear and then re-apply “Block your entire organization from using EWS,” or in Exchange Online PowerShell run `Set-OrganizationConfig -EWSEnabled $true`. It usually takes under an hour and can take 4. Both are stopgaps that end in April 2027, and the older user-agent `EwsAllowList` is a separate gate: a request has to pass both.

## EWS to Graph, operation by operation.

Microsoft publishes a direct [EWS to Graph mapping](https://learn.microsoft.com/en-us/graph/migrate-exchange-web-services-api-mapping). The common mail and sync operations:

| EWS | Microsoft Graph |
| --- | --- |
| `FindItem`, `GetItem` | [List messages](https://learn.microsoft.com/en-us/graph/api/user-list-messages), [get message](https://learn.microsoft.com/en-us/graph/api/message-get) |
| `CreateItem`, `UpdateItem`, `DeleteItem` | [Create](https://learn.microsoft.com/en-us/graph/api/user-post-messages), [update](https://learn.microsoft.com/en-us/graph/api/message-update), [delete message](https://learn.microsoft.com/en-us/graph/api/message-delete) |
| `MoveItem`, `CopyItem` | [Move](https://learn.microsoft.com/en-us/graph/api/message-move), [copy message](https://learn.microsoft.com/en-us/graph/api/message-copy) |
| `SendItem` | [Send message](https://learn.microsoft.com/en-us/graph/api/message-send) or [send mail](https://learn.microsoft.com/en-us/graph/api/user-sendmail) |
| `CreateFolder`, `GetFolder`, `UpdateFolder`, `MoveFolder` | [Mail folder](https://learn.microsoft.com/en-us/graph/api/user-post-mailfolders) create, get, update and move |
| `CreateAttachment`, `GetAttachment` | [Add](https://learn.microsoft.com/en-us/graph/api/message-post-attachments) and [get attachment](https://learn.microsoft.com/en-us/graph/api/attachment-get) |
| `SyncFolderItems` | [Get messages delta](https://learn.microsoft.com/en-us/graph/api/message-delta) |
| `SyncFolderHierarchy` | [Get mail folder delta](https://learn.microsoft.com/en-us/graph/api/mailfolder-delta) |
| `GetEvents` (pull notifications) | Messages delta |
| `Subscribe` (push notifications) | [Create subscription](https://learn.microsoft.com/en-us/graph/api/subscription-post-subscriptions) |
| `GetUserAvailability` | [Get free/busy schedule](https://learn.microsoft.com/en-us/graph/api/calendar-getschedule) |
| `GetUserOofSettings`, `SetUserOofSettings` | [Get](https://learn.microsoft.com/en-us/graph/api/user-get-mailboxsettings) and [update mailbox settings](https://learn.microsoft.com/en-us/graph/api/user-update-mailboxsettings) |
| `ConvertId` | [Translate Exchange IDs](https://learn.microsoft.com/en-us/graph/api/user-translateexchangeids) |

Calendar items and contacts are `CreateItem` and `FindItem` calls in EWS, too. In Graph they are their own resources: [events](https://learn.microsoft.com/en-us/graph/api/user-list-events), [create event](https://learn.microsoft.com/en-us/graph/api/user-post-events), [contacts](https://learn.microsoft.com/en-us/graph/api/user-list-contacts) and [create contact](https://learn.microsoft.com/en-us/graph/api/user-post-contacts). Sync for each has a delta function, as [`calendarView/delta`](https://learn.microsoft.com/en-us/graph/api/event-delta) and [contact delta](https://learn.microsoft.com/en-us/graph/api/contact-delta).

## Permissions change shape.

An EWS app asks for one broad permission. Delegated apps request `EWS.AccessAsUser.All` on the Exchange resource, and daemon apps use `full_access_as_app` and name the mailbox to impersonate ([Authenticate an EWS application by using OAuth](https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth)). Graph splits the same access by data type:

- **Delegated:** `Mail.ReadWrite` and `Mail.Send`, `Calendars.ReadWrite`, `Contacts.ReadWrite`, and `MailboxSettings.Read` when you need the mailbox time zone. Shared mailboxes need the `.Shared` variants. Read-only integrations can ask for less, such as `Mail.Read` or `Calendars.Read` ([permissions reference](https://learn.microsoft.com/en-us/graph/permissions-reference)).
- **Application:** the same names as application permissions, consented by an administrator, calling `/users/{id or upn}` because a client-credentials token has no `/me`. Unscoped, they reach every mailbox in the tenant, so limit them with [RBAC for Applications in Exchange Online](https://learn.microsoft.com/en-us/exchange/permissions-exo/application-rbac), which replaces Application Access Policies.

The token audience changes too: an EWS token is issued for `outlook.office365.com` and a Graph token for `graph.microsoft.com`. The new permissions are separate entries on the consent screen, so plan on every user or admin consenting again, unless your app registration already holds them.

## Notifications: from streams to webhooks and delta.

EWS offers three subscription types: streaming, pull and push ([Notification subscriptions in EWS](https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/notification-subscriptions-mailbox-events-and-ews-in-exchange)). Microsoft’s mapping sends pull to a [delta query](https://workwae.com/glossary#delta-query) and push to a [Graph subscription](https://workwae.com/glossary#graph-subscription), and its mapping has no entry for streaming. In practice a streaming consumer ends up with the same pair as everyone else: a subscription that wakes you, and a delta query that reads the change.

That changes the shape of the service. A streaming client held an outbound connection open and needed no public address. A Graph subscription POSTs to an HTTPS endpoint you expose, validates it with a handshake, expires in under seven days and needs renewing, and says only where to look. [Microsoft Graph change notifications for mail and calendar sync](https://workwae.com/blog/microsoft-graph-change-notifications) covers the handshake, lifecycle events, delta tokens and throttling. A pull client is the easiest port, as `SyncFolderItems` and `GetEvents` both become one delta call per folder.

## Where the port bites.

- **Stored ids stop matching.** EWS and Graph ids are different formats. Translate stored ids with `translateExchangeIds`, and ask for immutable ids with `Prefer: IdType="ImmutableId"` on requests and when creating subscriptions. An immutable id survives a move between folders, but changes if the item moves to an archive mailbox or is exported and imported again ([immutable identifiers](https://learn.microsoft.com/en-us/graph/outlook-immutable-id)).
- **Paging is explicit.** Messages come ten at a time by default; `$top` takes 1 to 1,000 ([list messages](https://learn.microsoft.com/en-us/graph/api/user-list-messages)).
- **Large attachments need a session.** A file under 3 MB is one POST; from 3 MB to 150 MB you create an upload session and PUT byte ranges ([large attachments](https://learn.microsoft.com/en-us/graph/outlook-large-attachments)).
- **MIME sending exists, MIME editing does not yet.** `sendMail` accepts base64 MIME with a `text/plain` body ([send mail](https://learn.microsoft.com/en-us/graph/api/user-sendmail)), but creating or updating a non-draft message from MIME is on the roadmap rather than shipped.
- **Throttling is per app and mailbox.** Outlook allows four concurrent requests and 10,000 requests in 10 minutes ([Outlook service limits](https://learn.microsoft.com/en-us/graph/throttling-limits#outlook-service-limits)). An EWS client that fanned out requests per item needs a queue.

## What Graph does not cover.

Microsoft tracks the remaining gaps on its [deprecation page](https://learn.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/deprecation-of-ews-exchange-online) and warns that a capability missing from the roadmap should not be expected before EWS ends. Targeted for Q3 or Q4 2026, and subject to change: notes, contact lists, extra contact properties, mark-all-as-read, report message, user configuration objects, MIME create and update for non-draft messages, in-place archive access, full-fidelity import and export for archives, public folders and groups, and Exchange Admin API folder permissions. Three capabilities are confirmed as never coming: generic public folder CRUD, generic Microsoft 365 group mailbox CRUD and discovery mailbox access. If your integration depends on one of those, the remaining choices are the Purview eDiscovery APIs for discovery work, or a redesign.

## How Workwae handles Microsoft 365.

Workwae has no EWS connector, so none of its Microsoft 365 accounts depend on EWS. Mailboxes connect through Microsoft Graph, and your code calls Workwae’s API instead of Graph.

- **Delegated sign-in** asks for `User.Read`, `offline_access`, then `Mail.ReadWrite` and `Mail.Send` for mail, `Calendars.ReadWrite` and `MailboxSettings.Read` for calendar and `Contacts.ReadWrite` for contacts, each only when that data is switched on. The `.Shared` permissions are added only when shared mailboxes are turned on.
- **[App-only access](https://workwae.com/glossary#app-only-access)** is an organization connection. Its Entra app needs `Mail.ReadWrite` and `Mail.Send`, and optionally `Calendars.ReadWrite`, `MailboxSettings.Read`, `Contacts.ReadWrite` and `User.Read.All`.
- **Sync** uses delta queries for messages, folders, events and contacts, with subscriptions on `me/messages`, `me/events` and `me/contacts` and a backstop poll, as described in the [notifications article](https://workwae.com/blog/microsoft-graph-change-notifications).
- **Government clouds:** [GCC High](https://workwae.com/glossary#gcc-high) accounts call `graph.microsoft.us` and [DoD](https://workwae.com/glossary#dod) accounts `dod-graph.microsoft.us`, each with its own app registration ([GCC High and DoD email API](https://workwae.com/blog/gcc-high-email-api)). 21Vianet mailboxes connect over IMAP and SMTP instead, because Graph mail sync does not run there yet ([Microsoft 365 provider](https://workwae.com/providers/microsoft-365)).
- **Your side** receives signed webhooks such as `message.created`, `message.updated` and the `calendar_event.*` and `contact.*` events, never a Graph notification ([webhooks guide](https://docs.workwae.com/guides/webhooks)).

## Limits.

- **Users sign in again.** Workwae connects through Graph scopes. An EWS grant, which carries `EWS.AccessAsUser.All`, is a different permission, so users sign in through hosted connect, or an admin consents for an organization connection. Plan for that in the move ([Move an EWS integration to Workwae](https://workwae.com/migrate/ews)).
- **No EWS connector, and no on-premises Exchange over EWS.** A server that allows IMAP and SMTP connects as an IMAP account.
- **Workwae’s own model, not Graph’s.** It has no public folders, archive mailboxes, inbox rules, out-of-office settings or MailTips. If you need those, the gaps above apply to you either way.
- **Alpha SDKs.** `@workwae/sdk` is at 0.1.0-alpha and `workwae` at 0.1.0a2.

## More from the blog.

### [Sending email from your users’ mailboxes: limits, bounces, tracking and merges.](https://workwae.com/blog/sending-email-from-your-users-mailboxes)

November 4, 2026 · 15 min read

Daily limits, authentication, the 5,000-a-day rules, bounces, suppression, validation, tracking, merges and retries.

Tags: Sending, Gmail, Microsoft Graph

### [Calendar time zones and DST: Google, Microsoft Graph and CalDAV.](https://workwae.com/blog/calendar-time-zones-and-dst)

November 2, 2026 · 6 min read

Windows versus IANA zone names, all-day and floating events, recurring events across DST, and times that do not exist or happen twice.

Tags: Calendar, Microsoft Graph

### [Sending mail as your users without breaking their mailbox.](https://workwae.com/blog/sending-mail-as-your-users)

October 19, 2026 · 6 min read

Sent copies, Message-IDs, In-Reply-To, References, Gmail threadId rules and drafts across SMTP, Gmail and Graph.

Tags: Sending, Gmail, Microsoft Graph
