RSS Amplifier

Glen’s @ eMail Development Substack · Nov 27, 2025

How to Migrate from the EWS Get-Delegate Operation

0
Sign in to vote or save

Glen Scales · Glen’s @ eMail Development Substack

With the release in preview of the Exchange Online Admin API recently this has unlocked a Migration path for those EWS apps that are stuck because of the lack of Delegate operations.

Delegation in Exchange and Outlook is a complex topic and can be implemented differently across both client and administrative surfaces. This post focuses on a single EWS operation (Get-Delegate), demonstrating a like-for-like solution to assist in migrating away from the particular EWS request.

A quick note on the new Exchange Admin API

Because the post will be using this API along with the Graph API a few quick points

The main point to clarify in the Get-Delegates context is that although it is called the ‘Exchange Admin API,’ this API is available to both regular users and Administrators to control certain aspects of mailbox configurations (Delegates and Mailbox folder permissions in this case). For a normal user the only mailbox they are going to be able to configure is their own. This get enabled through the default role assignments in Exchange Online https://learn.microsoft.com/en-us/exchange/permissions-exo/role-assignment-policies . So all you need for the new Exchange Admin API to work from a user context is an Application registration that has the Exchange.ManageV2 grant and that has been consented to. If a tenant has modified the default role assignments that’s possibly an area where using this API would break in some customers in a large multi customer app.

For Delegated (RBAC)Administrators and Service Principals they can have full access to configure all mailboxes across the tenant.

Client based Mailbox Delegation (non Admin)

What the EWS Get Delegation operation allows is client based Mailbox delegation which is what you see in Outlook classic in the following UI form

If you use EWS impersonation along with the Client Credentials flow (app permissions) then your app can now do this for every user within a tenant which is the classic EWS being used for Mailbox administrator scenario.

Outlook Classic has long included this mailbox delegation feature. This feature uses the Delegate Access Configuration Protocol and the EWS GetDelegate operation is an implementation of this protocol.

Differences between Outlook Classic and Outlook New and OWA

Currently the UI for configuring delegation is different between Outlook Classic which allows full delegation and New Outlook and OWA which offers a limited ability around calendars and folder sharing. There is roadmap item https://www.microsoft.com/en-au/microsoft-365/roadmap?filters=Outlook&searchterms=417063 slated to start in January to add the full Delegation feature to New Outlook.

What’s currently Missing in the Graph and the new Exchange Admin APIThe new Exchange Admin API lacks certain functionalities compared to the old GetDelegate request. Specifically, it is currently missing the ability to retrieve the delegates in the same way they are displayed on the relevant user interface (UI) surface in Outlook eg.

You could attempt to infer this list from the Calendar folder’s permissions using Get-MailboxFolderPermission and the SharingPermissionFlags property, but this method only provides limited coverage.

Using the Delegate Information Object

As part of the Delegate Access configuration protocol the Delegate Information object https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxodlgt/8c8d24eb-cb5a-4599-811c-82827fe5cd68 which is the Local Free Busy object located in the FreeBusyData folder in a Mailbox holds the above user configuration. This object contains properties that define the information about mailbox delegates and their specific settings, such as whether each delegate can see private items. It also stores the MeetingRequestsDeliveryScope (represented by a number of Boolean MAPI properties), which is a global setting that affects all delegates.

Usually in the Graph API, you’re limited from accessing special items like FAI (Folder Associated Items) or any item that doesn’t have a particular ItemClass. However, this one is accessible because it’s not an FAI item and its ItemClass of IPM.Microsoft.ScheduleData.FreeBusy is allowed.

Accessing the Delegate Information Object using the Microsoft Graph

There are a few ways you could go about this; I think the easiest way is to use the PidTagFreeBusyEntryIds property on the Root folder of the Mailbox.

This is a multi-valued binary property. If you take the second value in the array, it contains the EntryId of the Delegate Information object. This is documented here:

https://learn.microsoft.com/en-gb/openspecs/exchange_server_protocols/ms-oxosfld/dcf3ba89-2825-4f0e-abe2-8ae6ab7855bf

Once you have the EntryId, you can convert that to a Graph Rest Id using translateExchangeIds and then open the message and expand the extended properties that contain the delegate information. The Delegate Information Object doesn’t give all the information about the delegate; it just covers the following

  1. Lists each delegate by Name and EntryId PidTagScheduleInfoDelegateEntryIds & PidTagScheduleInfoDelegateNamesW

  2. Lists if they can view the private Items PidTagDelegateFlags

  3. Contains the MeetingRequestsDeliveryScope within PidTagScheduleInfoDelegatorWantsInfo, PidTagScheduleInfoDelegatorWantsCopy

What it’s missing is all the information that is stored on the Delegate forwarding rule which you can’t access using the Graph. For this we need to rely on what you can get from the -SharingPermissionFlags in Get-MailboxFolderPermission on the calendar which is now available in the new Exchange Online Admin API. This will tell you

  1. ReceiveCopiesOfMeetingMessages value

  2. Each Folder Level permission must be enumerated using a Get-MailboxFolderPermission request and matching the Delegate Entry from the Delegate Information object.

With all that information (which takes about 9 requests) you have now a one to one map for Get-Delegates eg here is a standard Get-Delegate response

GetDelegateResponse
  ResponseCode: NoError
  ResponseMessages:
    DelegateUserResponseMessageType:
      ResponseCode: NoError
      DelegateUser:
        UserId:
          PrimarySmtpAddress: Ther@datarumble.com (Resolvable from below)
          DisplayName: Ther (Delegate Information Object)
        DelegatePermissions:
          CalendarFolderPermissionLevel: Editor (Exchange Admin API )
          TasksFolderPermissionLevel: None (Exchange Admin API )
          InboxFolderPermissionLevel: None (Exchange Admin API )
          ContactsFolderPermissionLevel: None (Exchange Admin API )
          NotesFolderPermissionLevel: None (Exchange Admin API )
        ReceiveCopiesOfMeetingMessages: true (Exchange Admin API )
        ViewPrivateItems: true (Delegate Information Object)
  DeliverMeetingRequests: DelegatesOnly (Delegate Information Object)

Shortcomings of this method

Performance is pretty poor as it requires a large number of request vs the current 1 Get-Delegate Request. The likely hood of being throttled if you scale is pretty high.

Not fully tested as its a workaround method I haven’t tested every scenario and there’s a few edge cases in the poc code I know that are missing like the

  • NoForward in DeliverMeetingRequestsScope.

  • Localization for Non English mailboxes

  • Pagination for large number of ACE’s on the DACL

Sample code

Is also supports the following EntraAuth powershell module https://github.com/FriedrichWeinmann/EntraAuth to do the Exchange Admin Authentication eg

for a Delegate connection

Connect-EntraService -ClientID “f02b2e82-eae5-46e7-b2f4-xxxxxxxxx” -RedirectUri “http://localhost” -Scopes “https://outlook.office.com/Exchange.ManageV2”

You also need to have authenticated with Connect-MgGraph first also with scope for

Mail.Read and User.Read

This module has a few different cmdlets but the Get-Delegate one to one is

Get-O365Delegate -MailboxName jcool@datarumble.com -AccessToken $AccessToken

It will return delegates like

as well as the deliveryMeetingRequests scope

Other cmdlets are

Get-DelegateInfoConfig just output the information for the Delegate Information object (just requires a Graph SDK connection)

You run it like

If you find any bugs or improvements in the script please let me know.

Read the original on glenscales.substack.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.