Back to script library
Entra / Microsoft 365 · Compliance & audit

Analyze Send As audit data

Compares Send As audit records against mailbox Send As permissions to find events that lack a matching permission assignment.

Connect & set up

Run these once per session. All scopes are read-only unless the script makes changes.

# Review required modules and connection steps before running.
# Connect to Microsoft Graph or Exchange Online as needed for this script.

Run it

The main script. Copy it, or download the .ps1 and run it from your console.

If (!(Test-Path -Path c:\temp\MailboxAccessPermissions.csv)) {
Write-Host "Error: c:\temp\MailboxAccessPermissions.csv not found. Please run script to generate report of mailbox SendAs permissions" ; break}
If (!(Test-Path -Path c:\temp\SendAsAuditRecords.CSV)) {
Write-Host "Error: c:\temp\SendAsAuditRecords.CSV not found. Please run script to extract audit records for SendAs events" ; break}
# Import information gathered about audit records and permissions
$UserSendAsRecords = Import-CSV c:\temp\SendAsAuditRecords.CSV | Where-Object {$_.MailboxType -eq "UserMailbox"}
$SendAsData = Import-CSV c:\temp\MailboxAccessPermissions.csv | Where-Object {$_.Permission -eq "SendAs"}
If ($SendAsData.Count -eq 0) {
Write-Host "No SendAs permissions found"; break
}
$PermissionsUsed = 0; $PermissionsNotUsed = 0
$PermissionsUsedReport = [System.Collections.Generic.List[Object]]::new()
# Check each assigned permission to establish if we can find an audit record to prove its use (or not)
ForEach ($S in $SendAsData) {
$AuditCheck = $UserSendAsRecords | Where-Object {$_.SentBy -eq $S.AssignedTo -and $_.SentAs -eq $S.UPN} | Select-Object -ExpandProperty TimeStamp
If ($null -eq $AuditCheck) {
$PermissionsNotUsed++
$ReportLine = [PSCustomObject] @{
Mailbox = $S.Mailbox
UPN = $S.UPN
Assignedto = $S.AssignedTo
Status = "SendAs permission not used"
}
$PermissionsUsedReport.Add($ReportLine)
} Else {
$LastUsedDate = $AuditCheck | Sort-Object {$_.TimeStamp -as [datetime]} -Descending | Select-Object -Last 1 # Grab latest SendAs
$PermissionsUsed++
$ReportLine = [PSCustomObject] @{
Mailbox = $S.Mailbox
UPN = $S.UPN
Assignedto = $S.AssignedTo
Status = [String]$AuditCheck.Count + " SendAs permissions used. Last use on " + $LastUsedDate
}
$PermissionsUsedReport.Add($ReportLine)
}
}
$PermissionsUsedReport | Sort-Object AssignedTo | Out-GridView
$PermissionsUsedReport | Export-CSV -NoTypeInformation -Encoding UTF8 c:\Temp\SendAsPermissionsUsageReport.CSV
Clear-Host
Write-Host "SendAs Analysis for the last 90 days"
Write-Host "------------------------------------"
Write-Host "Total SendAs Permissions :" $SendAsData.Count
Write-Host "SendAs permissions used :" $PermissionsUsed
Write-Host "SendAs permissions not used:" $PermissionsNotUsed
Write-Host ""
Write-Host "Output report available in c:\Temp\SendAsPermissionsUsageReport.CSV"
Attribution