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.

 · 9 min read

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).
  • 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).
  • 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):

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.).

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). 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. The common mail and sync operations:

EWS Microsoft Graph
FindItem, GetItem List messages, get message
CreateItem, UpdateItem, DeleteItem Create, update, delete message
MoveItem, CopyItem Move, copy message
SendItem Send message or send mail
CreateFolder, GetFolder, UpdateFolder, MoveFolder Mail folder create, get, update and move
CreateAttachment, GetAttachment Add and get attachment
SyncFolderItems Get messages delta
SyncFolderHierarchy Get mail folder delta
GetEvents (pull notifications) Messages delta
Subscribe (push notifications) Create subscription
GetUserAvailability Get free/busy schedule
GetUserOofSettings, SetUserOofSettings Get and update mailbox settings
ConvertId Translate Exchange IDs

Calendar items and contacts are CreateItem and FindItem calls in EWS, too. In Graph they are their own resources: events, create event, contacts and create contact. Sync for each has a delta function, as calendarView/delta and 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). 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).
  • 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, 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). Microsoft’s mapping sends pull to a delta query and push to a 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 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).
  • Paging is explicit. Messages come ten at a time by default; $top takes 1 to 1,000 (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).
  • MIME sending exists, MIME editing does not yet. sendMail accepts base64 MIME with a text/plain body (send mail), 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). 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 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 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.
  • Government clouds: GCC High accounts call graph.microsoft.us and DoD accounts dod-graph.microsoft.us, each with its own app registration (GCC High and DoD email API). 21Vianet mailboxes connect over IMAP and SMTP instead, because Graph mail sync does not run there yet (Microsoft 365 provider).
  • Your side receives signed webhooks such as message.created, message.updated and the calendar_event.* and contact.* events, never a Graph notification (webhooks guide).

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).
  • 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.