I had the need recently to find all mailboxes that a given user in Microsoft 365 has delegate access to. Whilst you can check any user or shared mailbox to easily see who has delegated permissions to that mailbox, there’s no straightforward way to show all mailboxes that any given user has been granted permission to.
This is further complicated by the three different types of permissions that a user can be given for a mailbox – Full Access, Send As, and Send on Behalf.
I’ve created a script, Get-UserDelegatedMailboxes.ps1, that will loop through all mailboxes in the tenancy and check if the given user has been granted permissions to the mailbox.
Save this script below as Get-UserDelegatedMailboxes.ps1 and then you can run it like so:
\Get-UserDelegatedMailboxes.ps1 -UserPrincipalName [email protected] -ExportCsv auto
Here’s the script:
<#
.SYNOPSIS
Reports all mailboxes a specified user has delegated access to.
.DESCRIPTION
Queries Exchange Online for Full Access, Send As, and Send on Behalf
permissions granted TO the specified user across all mailboxes.
.PARAMETER UserPrincipalName
UPN of the user to audit (e.g. [email protected])
.PARAMETER ExportCsv
Optional. If specified, exports results to CSV.
Pass 'auto' to generate a timestamped filename in the current directory,
or provide an explicit path (e.g. C:\Reports\jsmith_access.csv).
.EXAMPLE
.\Get-UserDelegatedMailboxes.ps1 -UserPrincipalName [email protected]
Console output only — no file written.
.EXAMPLE
.\Get-UserDelegatedMailboxes.ps1 -UserPrincipalName [email protected] -ExportCsv auto
Exports to .\DelegatedAccess_jsmith_contoso_com_20250413.csv
.EXAMPLE
.\Get-UserDelegatedMailboxes.ps1 -UserPrincipalName [email protected] -ExportCsv "C:\Reports\jsmith_access.csv"
Exports to the specified path.
#>
param(
[Parameter(Mandatory = $true)]
[string]$UserPrincipalName,
[switch]$ExportCsv
)
# Requires ExchangeOnlineManagement module
# Install-Module -Name ExchangeOnlineManagement -Scope CurrentUser
# Connect if not already connected
try {
$null = Get-OrganizationConfig -ErrorAction Stop
} catch {
Write-Host "Connecting to Exchange Online..." -ForegroundColor Cyan
Connect-ExchangeOnline -ShowBanner:$false
}
# Resolve the user to confirm they exist and get display name
Write-Host "`nResolving user: $UserPrincipalName" -ForegroundColor Cyan
try {
$targetUser = Get-Recipient -Identity $UserPrincipalName -ErrorAction Stop
} catch {
Write-Error "User '$UserPrincipalName' not found in Exchange Online."
exit 1
}
$displayName = $targetUser.DisplayName
Write-Host "Auditing delegated access for: $displayName ($UserPrincipalName)`n" -ForegroundColor Green
$results = @()
# --- Full Access ---
Write-Host "Checking Full Access permissions..." -ForegroundColor Cyan
$allMailboxes = Get-EXOMailbox -ResultSize Unlimited -PropertySets Minimum
foreach ($mbx in $allMailboxes) {
$perms = Get-EXOMailboxPermission -Identity $mbx.Identity -User $UserPrincipalName -ErrorAction SilentlyContinue
if ($perms | Where-Object { $_.AccessRights -contains 'FullAccess' -and $_.Deny -eq $false }) {
$results += [PSCustomObject]@{
MailboxDisplayName = $mbx.DisplayName
MailboxUPN = $mbx.UserPrincipalName
PermissionType = 'Full Access'
}
}
}
# --- Send As ---
Write-Host "Checking Send As permissions..." -ForegroundColor Cyan
foreach ($mbx in $allMailboxes) {
$perms = Get-EXORecipientPermission -Identity $mbx.Identity -Trustee $UserPrincipalName -ErrorAction SilentlyContinue
if ($perms | Where-Object { $_.AccessRights -contains 'SendAs' }) {
$results += [PSCustomObject]@{
MailboxDisplayName = $mbx.DisplayName
MailboxUPN = $mbx.UserPrincipalName
PermissionType = 'Send As'
}
}
}
# --- Send on Behalf ---
Write-Host "Checking Send on Behalf permissions..." -ForegroundColor Cyan
foreach ($mbx in $allMailboxes) {
$grantedTo = $mbx | Select-Object -ExpandProperty GrantSendOnBehalfTo -ErrorAction SilentlyContinue
if ($grantedTo) {
$resolved = $grantedTo | ForEach-Object { Get-Recipient $_ -ErrorAction SilentlyContinue }
if ($resolved | Where-Object { $_.PrimarySmtpAddress -eq $UserPrincipalName }) {
$results += [PSCustomObject]@{
MailboxDisplayName = $mbx.DisplayName
MailboxUPN = $mbx.UserPrincipalName
PermissionType = 'Send on Behalf'
}
}
}
}
# --- Output ---
Write-Host "`n--- Delegated Mailbox Access for $displayName ---`n" -ForegroundColor Yellow
if ($results.Count -eq 0) {
Write-Host "No delegated permissions found for this user." -ForegroundColor Gray
} else {
$results | Sort-Object PermissionType, MailboxDisplayName | Format-Table -AutoSize
Write-Host "Total: $($results.Count) permission entr$(if ($results.Count -eq 1) {'y'} else {'ies'}) found.`n" -ForegroundColor Green
}
# Optional CSV export
if ($ExportCsv) {
$exportPath = ".\DelegatedAccess_$($UserPrincipalName -replace '@','_' -replace '\.','_')_$(Get-Date -Format 'yyyyMMdd').csv"
$results | Export-Csv -Path $exportPath -NoTypeInformation -Encoding UTF8
Write-Host "Exported to: $exportPath" -ForegroundColor Cyan
}