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
For the official Getting Started, what it its and Authentication docs for this API read https://learn.microsoft.com/en-us/exchange/reference/admin-api-overview
For some other commentary and information on the API see https://office365itpros.com/2025/11/18/exchange-admin-api-preview/ and https://michev.info/blog/post/7142/quick-look-at-the-new-exchange-admin-api-additions
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:
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
Lists each delegate by Name and EntryId PidTagScheduleInfoDelegateEntryIds & PidTagScheduleInfoDelegateNamesW
Lists if they can view the private Items PidTagDelegateFlags
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
ReceiveCopiesOfMeetingMessages value
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.

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.