If you are porting EWS Managed API code to Microsoft Graph, you will find a Graph call for most EWS operations. Many of those calls behave differently from what your EWS code expects.
How we test
Each of our 186 test scenarios is a real piece of EWS Managed API code. We run every scenario on Exchange Online twice, once through EWS and once through Microsoft Graph v1.0, and compare the two answers field by field.
Which of these affect your code
Start from the EWS operations your application calls. The EWS usage report in the Microsoft 365 admin center lists them per application. Our free tool ews-scan (MIT license) reads them from the compiled assemblies and prints the Graph call and what to watch for next to each one:
dotnet tool install --global Sunsetless.EwsScan
ews-scan C:\path\to\the\application
Sending mail
The sent copy goes to Sent Items
EWS lets the caller choose where the copy of a sent message is saved (SendAndSaveCopy with a folder) or save none (SendOnly). In Graph, sending a draft with send puts the copy in Sent Items. sendMail can skip the copy with saveToSentItems: false, and neither call takes a folder. To file the copy elsewhere, move it after Exchange has saved it, which takes a moment.
Sending returns no ID
Both Graph calls answer 202 with an empty body. Microsoft's documented way to find the sent message is to create the draft with the header Prefer: IdType="ImmutableId", send it, and read the message by the same ID afterwards. The copy may not be there right away.
Read receipts cannot be suppressed
Marking a message as read through Graph sends the read receipt its sender asked for. EWS has SuppressReadReceipts for that case. We found no Graph switch for it.
Meetings
Attendees are always notified
With EWS an organizer can save, change or delete a meeting without telling anyone (SendInvitationsMode.SendToNone, SendCancellationsMode.SendToNone). Calendar sync code relies on that. Graph sends the invitation, the update or the cancellation whenever the organizer creates a meeting with attendees, changes its time, place, subject, body or attendees, or deletes it, and no request parameter turns this off. Glen Scales describes workarounds.
Responses take fewer fields
accept, decline, tentativelyAccept and cancel in Graph take a comment and a flag that says whether to send the response. The extra fields of the EWS response objects (Cc, Bcc, sensitivity, receipt requests, the folder for the saved copy) cannot be passed.
The change key of a new meeting is stale
Graph saves a meeting first and sends it afterwards, and sending changes the item. The change key you get back from the create call no longer matches on the next read. Code that updates with ConflictResolutionMode.NeverOverwrite right after creating has to read the item again first.
Finding items
Filter and sort order are tied together
When a request has both $filter and $orderby, Microsoft documents three rules: the properties you sort by must also appear in the filter, in the same order, and before any other property. A request that breaks them fails with InefficientFilter. An EWS FindItem with both a restriction and a sort order translates only when you add conditions that are always true for the sort properties.
Search cannot be filtered or sorted
An AQS query string becomes $search. Microsoft documents that a search returns at most 1,000 results, sorted by the date the message was sent. In our tests it could not be combined with $filter or $orderby. An EWS call that passes both a query string and a restriction has to be split, or one half evaluated in your own code. For contacts, events and tasks we found no server-side text search at all.
What Graph does not filter or sort
These work in an EWS restriction or sort order, and we found no Graph counterpart for them: the body text, the size, an item class matched by prefix, DisplayTo and DisplayCc, bit masks on extended properties, and sorting by an extended property. The choices are to page through the folder and evaluate them yourself, or to change what the feature does.
Small things that change results
- Sorting by subject: Graph ignores prefixes such as RE: and FW:, while EWS sorts by the full subject.
- A filter that only asks whether an extended property exists needs a condition on its value, for example
ep/value ne null. - Binary extended properties cannot be used in a filter.
- Results of
$searchcome without usable change keys and ignore$expand, so reading extended properties takes a second request by ID.
Items that are not mail
In EWS every item is reached the same way. In Graph each kind has its own API, and /messages shows mail only.
- Calendar items, tasks and contact groups do not appear under
/messages. Attachments of a meeting are reached through/events. - Events, contacts and tasks have no
moveorcopy. Moving one means creating it again in the new folder, with a new ID and a new creation time. - Tasks live in Microsoft To Do. A To Do task has no extended properties, and its progress is a status, so a percent complete of 25 has nowhere to go.
- Contact groups (personal distribution lists) have no API in Graph v1.0. Microsoft's roadmap lists them as planned.
- A post (
IPM.Post) cannot be created; Graph answersErrorObjectTypeChanged. - Contacts, events and tasks in Deleted Items do not show up in their own APIs, and
/messagesdoes not list them either. - When you attach an item that has attachments of its own, Graph accepts the request and drops the inner attachments.
Synchronization and notifications
Stored sync states do not carry over
A SyncState from EWS means nothing to Graph. After the switch the application does one full synchronization per folder and stores delta links from then on.
Calendar delta needs a date window
Messages have a delta query per folder. For events, Graph v1.0 documents delta only on a calendar view, a range between two dates, and it returns the occurrences of a series there. SyncFolderItems on a calendar folder has no direct counterpart.
No streaming notifications
EWS pull notifications map to delta queries and push notifications map to Graph subscriptions with a webhook. The streaming connection has no counterpart. See EWS streaming notifications in Microsoft Graph.
Delta reports net changes
Exchange logs every change, and EWS notifications replay them. A delta query compares two states. An item created and deleted between two polls produces nothing. A hard delete shows up as a deletion, where EWS reported a move to Recoverable Items. Delta does not say whether a message is new or changed; you work that out from what you have seen before.
Identifiers and time
- Stored EWS IDs can be converted with
translateExchangeIds, up to 1,000 per call. Graph IDs change when an item moves unless you ask for immutable IDs. See EWS item IDs in Microsoft Graph. - An EWS ID names its mailbox, and Exchange routes by it. Graph wants the mailbox in the URL of every request, so store the mailbox next to the ID.
- Graph returns times to the second, so
DateTimePrecision.Millisecondshas no Graph counterpart. - Graph takes time zones by name. A custom time zone built with
TimeZoneInfo.CreateCustomTimeZone, which the EWS Managed API sends as a full definition, is not accepted. - Graph returns every body as HTML unless the request says
Prefer: outlook.body-content-type="text".BodyType.Bestin EWS returned text for a plain-text message.
Mailbox settings
- Out of office: Graph does not show whether external replies are allowed (
AllowExternalOof), and it keeps no language for the reply text. - Inbox rules: the conditions WithinDateRange, FromConnectedAccounts, ItemClasses and MessageClassifications and the actions SendSMSAlertToRecipients and ServerReplyWithMessage have no Graph counterpart. A rule update replaces all conditions, exceptions and actions of the rule.
- Delegates: Graph covers only the calendar part of a delegate's access, through calendar permissions. Delegate permissions on Inbox, Tasks, Contacts, Notes and Journal have no Graph counterpart.
- User configuration objects: Graph cannot list or create them today; Microsoft's roadmap plans them for the end of 2026. Categories and working hours have their own APIs.
- Other people's calendars: an application gets free/busy information only, with no further detail.
What has no Graph API
Microsoft's retirement page on Microsoft Learn has a roadmap of the gaps. On the day we checked it, general access to public folders, to Microsoft 365 group mailboxes and to discovery mailboxes was listed as not coming. Access to online archives, and export and import of public folder items, were planned for the last quarter of 2026. The page also says not to expect a capability that is not on the roadmap before EWS is switched off.
Sources
- Microsoft Learn: EWS to Microsoft Graph API mappings
- Microsoft Learn: retirement of EWS in Exchange Online
First published at sunsetless.com/guides/ews-to-graph-differences. Based on our own test results and Microsoft's documentation.
Top comments (0)