<# ============================================================================================= Name: Export Mailbox Permission Report Website: o365reports.com Version: 3.0 For detailed Script execution: https://o365reports.com/2019/03/07/export-mailbox-permission-csv/ ============================================================================================ #> #If you connect via Certificate based authentication, then your application required "Directory.Read.All" application permission, assign exchange administrator role and Exchange.ManageAsApp permission to your application. param( [switch]$FullAccess, [switch]$SendAs, [switch]$SendOnBehalf, [switch]$UserMailboxOnly, [switch]$AdminsOnly, [string]$MBNamesFile, [string]$TenantId, [string]$ClientId, [string]$CertificateThumbprint ) Function ConnectModules { $MsGraphModule = Get-Module Microsoft.Graph -ListAvailable if($MsGraphModule -eq $null) { Write-host "Important: Microsoft Graph Powershell module is unavailable. It is mandatory to have this module installed in the system to run the script successfully." -ForegroundColor Yellow $confirm = Read-Host Are you sure you want to install Microsoft Graph Powershell module? [Y] Yes [N] No if($confirm -match "[yY]") { Write-host "Installing Microsoft Graph Powershell module..." Install-Module -Name Microsoft.Graph -Scope CurrentUser Write-host "Microsoft Graph Powershell module is installed in the machine successfully" -ForegroundColor Magenta } else { Write-host "Exiting. `nNote: Microsoft Graph Powershell module must be available in your system to run the script" -ForegroundColor Red Exit } } else { [Version]$InstalledVersion = (Get-InstalledModule Microsoft.Graph).Version $Result = $InstalledVersion.CompareTo([Version]"1.10.0") if($Result -eq -1) { $Confirm = Read-Host "The installed version of the Microsoft Graph Powershell module is not supported. Do you want to update the module? [Y] Yes [N] No" if($confirm -match "[yY]") { Update-Module -Name Microsoft.Graph } else { Exit } } } $ExchangeOnlineModule = Get-Module ExchangeOnlineManagement -ListAvailable if($ExchangeOnlineModule -eq $null) { Write-host "Important: Exchange Online module is unavailable. It is mandatory to have this module installed in the system to run the script successfully." $confirm = Read-Host Are you sure you want to install Exchange Online module? [Y] Yes [N] No if($confirm -match "[yY]") { Write-host "Installing Exchange Online module..." Install-Module -Name ExchangeOnlineManagement -Scope CurrentUser Write-host "Exchange Online Module is installed in the machine successfully" -ForegroundColor Magenta } else { Write-host "Exiting. `nNote: Exchange Online module must be available in your system to run the script" Exit } } Disconnect-MgGraph -ErrorAction SilentlyContinue | Out-Null Disconnect-ExchangeOnline -Confirm:$false Write-Progress -Activity "Connecting modules(Microsoft Graph and Exchange Online module)..." try{ if($TenantId -ne "" -and $ClientId -ne "" -and $CertificateThumbprint -ne "") { Connect-MgGraph -TenantId $TenantId -ClientId $ClientId -CertificateThumbprint $CertificateThumbprint -ErrorAction SilentlyContinue -ErrorVariable ConnectionError|Out-Null if($ConnectionError -ne $null) { Write-Host $ConnectionError -Foregroundcolor Red Exit } $Scopes = (Get-MgContext).Scopes if($Scopes -notcontains "Directory.Read.All" -and $Scopes -notcontains "Directory.ReadWrite.All") { Write-Host "Note: Your application required the following graph application permissions: Directory.Read.All" -ForegroundColor Yellow Exit } Connect-ExchangeOnline -AppId $ClientId -CertificateThumbprint $CertificateThumbprint -Organization (Get-MgDomain | Where-Object {$_.isInitial}).Id -ShowBanner:$false } else { Connect-MgGraph -Scopes "Directory.Read.All" -ErrorAction SilentlyContinue -Errorvariable ConnectionError |Out-Null if($ConnectionError -ne $null) { Write-Host $ConnectionError -Foregroundcolor Red Exit } Connect-ExchangeOnline -UserPrincipalName (Get-MgContext).Account -ShowBanner:$false } } catch { Write-Host $_.Exception.message -ForegroundColor Red Exit } Write-Host "Microsoft Graph Powershell module is connected successfully" -ForegroundColor Cyan Write-Host "Exchange Online module is connected successfully" -ForegroundColor Cyan } Function Print_Output { $Result = [PSCustomObject]@{'DisplayName'=$Displayname;'UserPrincipalName'=$UPN;'MailboxType'=$MBType;'AccessType'=$AccessType;'UserWithAccess'=$UserWithAccess;'Roles'=$Roles} $Result | Export-csv -Path $ExportCSV -Append -NoTypeInformation } Function Get_MBPermission { #Getting delegated Fullaccess permission for mailbox if(($FilterPresent -eq 'False') -or ($FullAccess.IsPresent)) { $FullAccessPermissions = (Get-EXOMailboxPermission -Identity $UPN -ErrorAction SilentlyContinue | Where { ($_.AccessRights -contains "FullAccess") -and ($_.IsInherited -eq $false) -and -not ($_.User -match "NT AUTHORITY" -or $_.User -match "S-1-5-21") }).User if([string]$FullAccessPermissions -ne "") { $AccessType = "FullAccess" $UserWithAccess = @($FullAccessPermissions) -join ',' Print_Output } } #Getting delegated SendAs permission for mailbox if(($FilterPresent -eq 'False') -or ($SendAs.IsPresent)) { $SendAsPermissions = (Get-EXORecipientPermission -Identity $UPN -ErrorAction SilentlyContinue | Where{ -not (($_.Trustee -match "NT AUTHORITY") -or ($_.Trustee -match "S-1-5-21"))}).Trustee if([string]$SendAsPermissions -ne "") { $AccessType = "SendAs" $UserWithAccess = @($SendAsPermissions) -join ',' Print_Output } } #Getting delegated SendOnBehalf permission for mailbox if(($FilterPresent -eq 'False') -or ($SendOnBehalf.IsPresent)) { if([string]$SendOnBehalfPermissions -ne "") { $AccessType = "SendOnBehalf" $UserWithAccess = @() Foreach($SendOnBehalfPermissionDN in $SendOnBehalfPermissions) { $SendOnBehalfPermission = (Get-EXOMailBox -Identity $SendOnBehalfPermissionDN -ErrorAction SilentlyContinue).UserPrincipalName if($SendOnBehalfPermission -eq $null) { $SendOnBehalfPermission = ($Users|?{$_.MailNickname -eq $SendOnBehalfPermissionDN}).UserPrincipalName } $UserWithAccess += $SendOnBehalfPermission } $UserWithAccess = @($UserWithAccess) -join ',' Print_Output } } } #Getting Mailbox permission Function Get_MailBoxData { Write-Progress -Activity "`n Processing mailbox: $MBUserCount `n Currently Processing: $DisplayName" $Script:MBUserCount++ if($UserMailboxOnly.IsPresent -and $MBType -ne 'UserMailBox') { return } #Get admin roles assigned to user $RoleList=Get-MgUserTransitiveMemberOf -UserId $UserId|Select-Object -ExpandProperty AdditionalProperties $RoleList = $RoleList|?{$_.'@odata.type' -eq '#microsoft.graph.directoryRole'} $Roles = @($RoleList.displayName) -join ',' if($RoleList.count -eq 0) { $Roles = "No roles" } #Admin Role based filter if($AdminsOnly.IsPresent -and $Roles -eq "No roles") { return } Get_MBPermission } Function CloseConnection { Disconnect-MgGraph | Out-Null Disconnect-ExchangeOnline -Confirm:$false } ConnectModules Write-Progress -Activity Completed -Completed Select-MgProfile -Name beta #Set output file $Location = (Get-Location) $ExportCSV = "$($Location)\MBPermission_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm-ss` tt).ToString()).csv" $Result = "" ; $Mailboxes = @(); $MBUserCount = 1; $Users = Get-MgUser -All #Check for AccessType filter if(($FullAccess.IsPresent) -or ($SendAs.IsPresent) -or ($SendOnBehalf.IsPresent)) { $FilterPresent = 'True' } else { $FilterPresent = 'False' } #Check for input file if ($MBNamesFile -ne "") { #We have an input file, read it into memory try{ $MailBoxes = Import-Csv -Header "MailBoxUPN" -Path $MBNamesFile } catch{ Write-Host $_.Exception.Message -ForegroundColor Red CloseConnection Exit } Foreach($Mail in $MailBoxes) { $Mailbox = Get-EXOMailbox -Identity $Mail.MailBoxUPN -PropertySets All -ErrorAction SilentlyContinue if($Mailbox -eq $null) { Write-Host `n $Mail.MailBoxUPN is not found -ForegroundColor Red Continue } $DisplayName = $MailBox.DisplayName $UPN = $MailBox.UserPrincipalName $UserId = $MailBox.ExternalDirectoryObjectId $MBType = $MailBox.RecipientTypeDetails $SendOnBehalfPermissions = $MailBox.GrantSendOnBehalfTo Get_MailBoxData } } else { Get-EXOMailbox -ResultSize Unlimited -PropertySets All | Where{$_.DisplayName -notlike "Discovery Search Mailbox"} |ForEach-Object{ $DisplayName = $_.DisplayName $UPN = $_.UserPrincipalName $UserId = $_.ExternalDirectoryObjectId $MBType = $_.RecipientTypeDetails $SendOnBehalfPermissions = $_.GrantSendOnBehalfTo Get_MailBoxData } } #Open output file after execution Write-Host `nScript executed successfully if((Test-Path -Path $ExportCSV) -eq "True") { Write-Host Detailed report available in: $ExportCSV -ForegroundColor Green $Prompt = New-Object -ComObject wscript.shell $UserInput = $Prompt.popup("Do you want to open output file?",` 0,"Open Output File",4) if ($UserInput -eq 6) { Invoke-Item "$ExportCSV" } } else { Write-Host No mailbox found that matches your criteria. -ForegroundColor Red } CloseConnection