Src/Private/Get-AbrExoMailboxPermissions.ps1

function Get-AbrExoMailboxPermissions {
    <#
    .SYNOPSIS
    Documents Exchange Online mailbox permissions in detail: Full Access, Send As,
    Send on Behalf, and calendar sharing for shared and user mailboxes.
    .NOTES
        Version: 0.1.0
        Author: Pai Wei Sing
    #>

    [CmdletBinding()]
    param (
        [Parameter(Position = 0, Mandatory)]
        [string]$TenantId
    )

    begin {
        Write-PScriboMessage -Message "Collecting Exchange Online Mailbox Permissions for $TenantId."
        Show-AbrDebugExecutionTime -Start -TitleMessage 'MailboxPermissions'
    }

    process {
        Section -Style Heading2 'Permissions' {
            Paragraph "The following section documents delegated mailbox permissions (Full Access, Send As, Send on Behalf) for tenant $TenantId."
            BlankLine

            try {
                Write-Host " - Retrieving mailbox permissions (this may take a moment)..."
                $AllMailboxes = Get-Mailbox -ResultSize Unlimited -ErrorAction Stop |
                    Where-Object { $_.RecipientTypeDetails -in @('UserMailbox', 'SharedMailbox') } |
                    Sort-Object RecipientTypeDetails, DisplayName

                $FullAccessPerms = [System.Collections.ArrayList]::new()
                $SendAsPerms     = [System.Collections.ArrayList]::new()
                $SoboPerms       = [System.Collections.ArrayList]::new()

                $processed = 0
                foreach ($Mbx in $AllMailboxes) {
                    $processed++
                    if ($processed % 20 -eq 0) {
                        Write-Host " - Processed $processed of $(@($AllMailboxes).Count) mailboxes..." -ForegroundColor DarkGray
                    }

                    # Full Access
                    try {
                        $FaPerms = Get-MailboxPermission -Identity $Mbx.Identity -ErrorAction SilentlyContinue |
                            Where-Object {
                                $_.AccessRights -contains 'FullAccess' -and
                                -not $_.IsInherited -and
                                $_.User -notlike 'NT AUTHORITY\*' -and
                                $_.User -notlike 'S-1-5-*'
                            }
                        foreach ($Perm in $FaPerms) {
                            $null = $FullAccessPerms.Add([pscustomobject]@{
                                'Mailbox'       = $Mbx.DisplayName
                                'Mailbox SMTP'  = $Mbx.PrimarySmtpAddress
                                'Mailbox Type'  = $Mbx.RecipientTypeDetails
                                'Granted To'    = "$($Perm.User)"
                                'Inherited'     = $Perm.IsInherited
                                'Deny'          = $Perm.Deny
                            })
                        }
                    } catch {}

                    # Send As
                    try {
                        $SaPerms = Get-RecipientPermission -Identity $Mbx.Identity -ErrorAction SilentlyContinue |
                            Where-Object {
                                $_.AccessRights -contains 'SendAs' -and
                                $_.Trustee -notlike 'NT AUTHORITY\*' -and
                                $_.Trustee -notlike 'S-1-5-*'
                            }
                        foreach ($Perm in $SaPerms) {
                            $null = $SendAsPerms.Add([pscustomobject]@{
                                'Mailbox'       = $Mbx.DisplayName
                                'Mailbox SMTP'  = $Mbx.PrimarySmtpAddress
                                'Mailbox Type'  = $Mbx.RecipientTypeDetails
                                'Granted To'    = "$($Perm.Trustee)"
                                'Inherited'     = $Perm.IsInherited
                            })
                        }
                    } catch {}

                    # Send on Behalf
                    if ($Mbx.GrantSendOnBehalfTo -and $Mbx.GrantSendOnBehalfTo.Count -gt 0) {
                        foreach ($Delegate in $Mbx.GrantSendOnBehalfTo) {
                            $null = $SoboPerms.Add([pscustomobject]@{
                                'Mailbox'       = $Mbx.DisplayName
                                'Mailbox SMTP'  = $Mbx.PrimarySmtpAddress
                                'Mailbox Type'  = $Mbx.RecipientTypeDetails
                                'Granted To'    = "$Delegate"
                            })
                        }
                    }
                }

                #region Full Access summary
                Section -Style Heading3 'Full Access Permissions' {
                    if ($FullAccessPerms.Count -gt 0) {
                        Paragraph "The following $($FullAccessPerms.Count) Full Access permission assignment(s) are configured across mailboxes in tenant $TenantId."
                        BlankLine

                        $null = (& {
                            if ($HealthCheck.ExchangeOnline.Mailboxes) {
                                # Flag Deny entries as they can indicate misconfiguration
                                $null = ($FullAccessPerms | Where-Object { $_.Deny -eq $true } | Set-Style -Style Warning | Out-Null)
                            }
                        })

                        $FaTableParams = @{ Name = "Full Access Permissions - $TenantId"; List = $false; ColumnWidths = 20, 26, 16, 26, 6, 6 }
                        if ($Report.ShowTableCaptions) { $FaTableParams['Caption'] = "- $($FaTableParams.Name)" }
                        if ($FullAccessPerms.Count -gt 0) { $FullAccessPerms | Table @FaTableParams }
                        $script:ExcelSheets['Full Access Perms'] = $FullAccessPerms
                    } else {
                        Paragraph "No delegated Full Access permissions found."
                    }
                }
                #endregion

                #region Send As summary
                Section -Style Heading3 'Send As Permissions' {
                    if ($SendAsPerms.Count -gt 0) {
                        Paragraph "The following $($SendAsPerms.Count) Send As permission assignment(s) are configured in tenant $TenantId."
                        BlankLine

                        $SaTableParams = @{ Name = "Send As Permissions - $TenantId"; List = $false; ColumnWidths = 22, 28, 16, 28, 6 }
                        if ($Report.ShowTableCaptions) { $SaTableParams['Caption'] = "- $($SaTableParams.Name)" }
                        if ($SendAsPerms.Count -gt 0) { $SendAsPerms | Table @SaTableParams }
                        $script:ExcelSheets['Send As Perms'] = $SendAsPerms
                    } else {
                        Paragraph "No Send As permissions found."
                    }
                }
                #endregion

                #region Send on Behalf summary
                Section -Style Heading3 'Send on Behalf Permissions' {
                    if ($SoboPerms.Count -gt 0) {
                        Paragraph "The following $($SoboPerms.Count) Send on Behalf permission assignment(s) are configured in tenant $TenantId."
                        BlankLine

                        $SoboTableParams = @{ Name = "Send on Behalf Permissions - $TenantId"; List = $false; ColumnWidths = 22, 30, 18, 30 }
                        if ($Report.ShowTableCaptions) { $SoboTableParams['Caption'] = "- $($SoboTableParams.Name)" }
                        if ($SoboPerms.Count -gt 0) { $SoboPerms | Table @SoboTableParams }
                        $script:ExcelSheets['Send On Behalf Perms'] = $SoboPerms
                    } else {
                        Paragraph "No Send on Behalf permissions found."
                    }
                }
                #endregion

            } catch {
                Write-ExoError 'MailboxPermissions' "Unable to retrieve mailbox permissions: $($_.Exception.Message)"
                Paragraph "Unable to retrieve mailbox permission data: $($_.Exception.Message)"
            }
        }
    }

    end {
        Show-AbrDebugExecutionTime -End -TitleMessage 'MailboxPermissions'
    }
}