Entra / Microsoft 365 · Compliance & audit
Find deleted email audit records
Search the unified audit log to find who deleted messages via HardDelete and SoftDelete operations; output can be filtered to specific mailboxes.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Connect-ExchangeOnline
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
param([int] $LookbackDays = 90,[string] $StartDate = (Get-Date).AddDays(-$LookbackDays); $EndDate = (Get-Date),[string] $EndDate = (Get-Date))If ($Null -eq (Get-ConnectionInformation)) {Connect-ExchangeOnline}$Records = (Search-UnifiedAuditLog -StartDate $StartDate -EndDate $EndDate -Operations "HardDelete", "SoftDelete" -ResultSize 5000)If (!($Records)) { Write-Host "No deletion records found."; break }Else {Write-Host "Processing" $Records.Count "audit records..."$Report = [System.Collections.Generic.List[Object]]::new() # Create output fileForEach ($Rec in $Records) {$AuditData = ConvertFrom-Json $Rec.AuditdataIf ($AuditData.ResultStatus -eq "PartiallySucceeded") {$EMailSubjects = "*** Not deleted by" + $AuditData.ClientInfoString + " ***" }Else {$EmailSubjects = $AuditData.AffectedItems.Subject -join ", " }$ReportLine = [PSCustomObject] @{TimeStamp = Get-Date($AuditData.CreationTime) -format gUser = $AuditData.UserIdAction = $AuditData.OperationStatus = $AuditData.ResultStatusMailbox = $AuditData.MailboxOwnerUPN"Message Subjects" = $EmailSubjectsFolder = $AuditData.Folder.Path.Split("\")[1]Client = $AuditData.ClientInfoString }$Report.Add($ReportLine) }}$Report | Sort-Object Mailbox | Select Timestamp, Action, User, Mailbox, "Message Subjects", Folder | Out-GridView
Parameters
ParameterDefaultNotes
-LookbackDays90Number of days back to search deletion audit records.-StartDate(Get-Date).AddDays(-90)Start of the audit log search window.-EndDate(Get-Date)End of the audit log search window.Attribution
Author
Office365itpros