Querying msExchDelegateListLink in Exchange Online with PowerShell

9 Mar 2023 Update:

I updated the script to support Modern Auth (OAuth) which is now required for most things in Exchange Online. Details are in the comments of the new script itself:

https://github.com/Mike-Crowley/Public-Scripts/blob/main/Get-AlternateMailboxes.ps1

If you still want the old one, it will be here for a while

https://github.com/Mike-Crowley/Public-Scripts/blob/main/Get-AlternateMailboxes_BasicAuth.ps1

12 Aug 2020 Update:

A few readers contacted me to report this script no longer works. I got around to investigating it today and see the cause, revealed in a Fiddler trace:

X-AnchorMailbox

(larger)

It would seem Microsoft now needs an anchor mailbox, likely to determine what tenant this request is for. I was able to modify my script to accommodate. Sadly, Microsoft is decomissioning the TechNet Gallery, so I may not update that site, just to have them delete it anyway. Please consider including the following in the script yourself:

... 

#Other attributes available here: https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.autodiscover.usersettingname(v=exchg.80).aspx
 
$Headers = @{
'X-AnchorMailbox' = $Credential.UserName
} 

$WebResponse = Invoke-WebRequest https://autodiscover-s.outlook.com/autodiscover/autodiscover.svc -Credential $Credential -Method Post -Body $AutoDiscoverRequest -ContentType 'text/xml; charset=utf-8' -Headers $Headers
[System.Xml.XmlDocument]$XMLResponse = $WebResponse.Content 

... 

$Credential= Get-Credential
Get-AlternateMailboxes -SMTPAddress bob.smith2@contoso.com -Credential $Credential

...

Original Post:

 

There are a number of articles that describe the relationship between the FullAccess permission of an Exchange mailbox and the msExchDelegateListLink attribute. Here are two good ones:

In short, this attribute lists all the other mailboxes your mailbox has FullAccess to, unless AutoMapping was set to $false when assigning the permission. It can be a handy attribute to query when trying to learn what mailboxes might appear in an end-user’s Outlook profile.

This attribute is synced to Office 365 via Azure AD Connect, however, for whatever reason, it is not synced back on-premises for new or migrated mailboxes. It is also not exposed in Get-User, Get-Mailbox, Get-MailboxStatistics, Microsoft Graph or Azure AD Graph.

The information is however included in the user’s AutoDiscover XML response. This is how Outlook knows what mailboxes to mount. If you want to look at this data manually, use the ctrl+right-click tool from the Outlook icon on the system tray. This article describes how to do that, if somehow you’re reading this but don’t already know about this tool:

You can also look at the AutoDiscover XML file via the venerable TestConnectivity.Microsoft.com web site. Look at the bottom of of the file, and you’ll see “AlternativeMailbox” entries.

<AlternativeMailbox>  
<Type>Delegate</Type>
<DisplayName>crowley test 1</DisplayName>
<SmtpAddress>crowleytest1@mikecrowley.us</SmtpAddress>
<OwnerSmtpAddress>crowleytest1@mikecrowley.us</OwnerSmtpAddress>
</AlternativeMailbox>
<AlternativeMailbox>
<Type>Delegate</Type>
<DisplayName>crowley test 2</DisplayName>
<SmtpAddress>crowleytest2@mikecrowley.us</SmtpAddress>
<OwnerSmtpAddress>crowleytest2@mikecrowley.us</OwnerSmtpAddress>
</AlternativeMailbox>

While not exactly the msExchDelegateListLink attribute, its the same difference.

This is neat, but to be useful at scale, we need to query this in PowerShell. Fortunately, there are two methods to fetch the AutoDiscover XML.

You can query these endpoints directly or through the the Exchange Web Services (EWS) API. If you don’t have a preference, Microsoft’s documentation recommends SOAP, which is the approach I’ll discuss here.

Using Invoke-WebRequest and SOAP, we can request specific attributes, such as AlternateMailboxes. Other useful attributes are listed in this article:

While I’m not a developer (developers, please keep your laughter to yourself!), I did manage to cobble together the following SOAP request, which will be the string we “post” to the AutoDiscover service. You’ll notice I’ve marked the user we’re querying and any attributes I might want in bold (modify this list to suit your needs):

<soap:Envelope xmlns:a="http://schemas.microsoft.com/exchange/2010/Autodiscover"
xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<a:RequestedServerVersion>Exchange2013</a:RequestedServerVersion>
<wsa:Action>http://schemas.microsoft.com/exchange/2010/Autodiscover/Autodiscover/GetUserSettings</wsa:Action>
<wsa:To>https://autodiscover.exchange.microsoft.com/autodiscover/autodiscover.svc</wsa:To>
</soap:Header>
<soap:Body>
<a:GetUserSettingsRequestMessage xmlns:a="http://schemas.microsoft.com/exchange/2010/Autodiscover">
<a:Request>
<a:Users>
<a:User>
<a:Mailbox>bob@contoso.com</a:Mailbox>
</a:User>
</a:Users>
<a:RequestedSettings>
<a:Setting>UserDisplayName</a:Setting>
<a:Setting>UserDN</a:Setting>
<a:Setting>UserDeploymentId</a:Setting>
<a:Setting>MailboxDN</a:Setting>
<a:Setting>AlternateMailboxes</a:Setting>
</a:RequestedSettings>
</a:Request>
</a:GetUserSettingsRequestMessage>
</soap:Body>
</soap:Envelope>

(For this post, I only care about AlternateMailboxes.)

AutoDiscover requires authentication, so we’ll also need to use the Get-Credential cmdlet. Interestingly, any mailbox can query the AutoDiscover response for any other user in the Office 365 tenant. This means, through PowerShell, I can look up the msExchDelegateListLink / AlternativeMailbox values for other users (even without administrative privileges).

I’ve written a function to return the results in a PowerShell array like this:

Get-AlternateMailboxes-Example

I should also point out:

  • It has the Exchange Online URL hard-coded within, though you could adapt this for other URLs if you’d like.
  • Both SMTPAddress and Credential parameters require valid Exchange Online mailboxes (though, as previously mentioned they do not need to be the same mailbox).

Usage Example:

Get-AlternateMailboxes -SMTPAddress bob@contoso.com -Credential (Get-Credential)

Finally, here is the script itself:

9 thoughts on “Querying msExchDelegateListLink in Exchange Online with PowerShell

  1. Hey Mike, great post and so useful for confirming that a user has delegated permissions to a mailbox.

    However, while your script pulls out the information and clearly shows us that one of our users has delegated permissions to a “migrated from on-prem to online shared mailbox”, we’re struggling to remove this orphaned permission. It was showing earlier today in the on-prem MSExchDelegateListLink attribute, but that was removed and following an AD Sync it’s not showing up in the online MSExchDelegateListLink attribute.

    We’ve confirmed that it’s not showing in the Exchange Portal under Mailbox Delegation – Full Access and we’ve also converted the shared mailbox to a normal mailbox and logged in to check for user given delegation permissions, but there were none.

    As such, I was wondering if you’ve come across this kind of orphaned delegation setting and if so explored how to remove such a permission where it’s not set in the expected places?

    Thank you JC

  2. Not to worry – we spoke with MS and the end solution to this was to do a reset of the shared mailbox permissions by logging into the Exchange Portal and under Mailbox Delegation set the user with Full Access, save it and then after a short period of time, remove it again. This appears to have cleared the orphaned permission that wasn’t showing.

    Hope that helps for someone.

  3. Hi Mike,
    I’ve been wondering about something like this for ages, and your script looks amazing, however when I try to use it to query my own mailbox (in O365 with delegate perms on about a dozen other mailboxes) I get a 401 Unauthorized error from the Autodiscover service. Any advice on working around this?

    Cheers,

    Andy

    • Possible your account requires MFA? This script doesn’t support Modern Authentication, but you should be able to target any mailbox as long as you auth as any other mailbox. If you have everyone using MFA however, this script would need to be redeveloped.

      • We’ve just started getting 401 errors with this (noted yesterday but that was also a Monday and code using it wouldn’t have run over the weekend). Suspect a change at the MS end? The accounts we use aren’t using MFA.

      • Hi both,

        I can only assume it must be something going on MS-side or with my mailbox as when I do the same thing but use a different set of credentials, it works fine. I don’t have MFA or anything special on my account, so I’m not sure what it could be.

        Cheers,

        Andy

  4. Hello,
    This may be an easier solution for EXOL. This will list out the delegatelist.
    $CheckAutoMapping = Read-Host ‘Which Mailbox do you Want to Check automapping?’

    Get-MailboxPermission $checkautomapping -ReadFromDomainController | ft DelegateList*

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s