To find who deleted, shared or forwarded something in Microsoft 365, search the unified audit log in the Microsoft Purview portal (Audit > Search) or with Search-UnifiedAuditLog in Exchange Online PowerShell, filtered by date range in UTC and by the exact operation names: FileDeleted and FileRecycled for SharePoint and OneDrive deletions, SharingSet, SharingInvitationCreated and AnonymousLinkCreated for sharing, SoftDelete and HardDelete for mailbox deletions, and New-InboxRule, Set-InboxRule, UpdateInboxRules and Set-Mailbox for forwarding. The user, IP address and full details of each event are in the record's AuditData JSON, which you can export and parse. Records are kept for 180 days with Audit (Standard), so start the search as soon as an incident is reported.
Who this is for and what you will have
This guide is for Microsoft 365 administrators and security analysts who have been asked a specific question during an incident: who deleted this folder, who sent an anonymous link to this file, who emptied this mailbox, or who set up forwarding to an outside address. At the end you will have:
- A confirmed audit configuration and the right permissions to search.
- Portal and PowerShell searches for the four most common investigation questions.
- A paging pattern that retrieves more than the default 100 records.
- A CSV with the AuditData properties split into readable columns.
- A list of the reasons a search comes back empty when it shouldn't.
How the unified audit log works
The unified audit log collects events from Exchange Online, SharePoint, OneDrive, Microsoft Entra ID, Teams, Power BI and other services into one searchable store. The portal search and Search-UnifiedAuditLog query the same data.
Retention
How long a record is searchable depends on the licence of the user who performed the activity:
| Licence of the user | Default retention |
|---|---|
| Office 365 E5, Microsoft 365 E5, Microsoft Purview Suite or Microsoft 365 E5 eDiscovery and Audit add-on | One year for Microsoft Entra ID, Exchange and SharePoint activity; other services through audit log retention policies, up to one year |
| Any other Office 365 or Microsoft 365 licence | 180 days |
Audit (Standard) records generated before 17 October 2023 were kept for 90 days; records from that date onwards follow the 180-day default.
Latency
Microsoft doesn't commit to a specific delay. For Exchange, SharePoint, OneDrive and Teams, records are typically available 60 to 90 minutes after the event; other services can take longer. If you search for something that happened ten minutes ago and find nothing, that is expected.
What the record contains
Each record has a few top-level columns (CreationDate, UserIds, Operations, RecordType) and a JSON column, AuditData, with the details. The properties you will use most:
| Property | Meaning |
|---|---|
UserId | The account that performed the action, including system accounts and app@sharepoint |
ClientIP | IP address recorded for the activity; for some services it can be the address of a Microsoft application acting for the user |
ObjectId | For SharePoint, the full URL of the file or folder; for Exchange admin activity, the object the cmdlet changed |
Parameters | For Exchange admin activity, every parameter name and value used with the cmdlet |
MailboxOwnerUPN | For mailbox activity, the owner of the mailbox that was accessed |
LogonType | For mailbox activity: 0 owner, 1 administrator, 2 delegate |
ClientInfoString | The email client used for a mailbox action |
SiteUrl, SourceRelativeUrl, SourceFileName | The pieces that make up a SharePoint ObjectId |
A UserId of app@sharepoint means an application with SharePoint app-only access performed the action, for example a retention policy or an eDiscovery hold, not a person.
Prerequisites
- Audit ingestion is on. It is on by default for enterprise organizations. Check it in Exchange Online PowerShell, not Security & Compliance PowerShell, where the property always shows
False:
Connect-ExchangeOnline -UserPrincipalName admin@contoso.com
Get-AdminAuditLogConfig | Format-List UnifiedAuditLogIngestionEnabled- Mailbox auditing is on.
Get-OrganizationConfig | Format-List AuditDisabledshould returnFalse. On the mailbox you are investigating,Get-Mailbox -Identity <mailbox> | Format-List DefaultAuditSetshould returnAdmin, Delegate, Ownerunless someone customised it. Check that the user isn't excluded withGet-MailboxAuditBypassAssociation -Identity <mailbox> | Format-List AuditByPassEnabled. - Permissions. The Audit Logs or View-Only Audit Logs role in the Microsoft Purview portal for portal searches, and the same roles in the Exchange admin center for the cmdlet. You can add either role to a custom role group.
- Administrative units. If you are a restricted admin scoped to administrative units, you only see user-generated records for users in your units. Some operations, including the Exchange
Set-Mailboxcmdlet, are only returned to unrestricted admins. - The incident window in UTC. Both the portal and the cmdlet store and filter in UTC.
Step 1: Run a scoped search in the Purview portal
- Sign in to the Microsoft Purview portal at
https://purview.microsoft.comand select the Audit solution card (under View all solutions > Core if it isn't shown). - On the Search page, set Date and time range (UTC). The default is the last seven days and the maximum range is 180 days.
- Fill in only the criteria you need:
- Activities - operations names: exact operation names separated by commas, such as
FileDeleted,FileRecycled. A typo returns nothing, so copy names from the audited activities reference. - Activities - friendly names: the same activities chosen from a list, grouped by area.
- Record types and Workloads: narrow by service.
- Users: the accounts that performed the activity. Leave blank for everyone.
- File, folder, or site: part or all of a file name, or a URL with
*at the end, such ashttps://contoso.sharepoint.com/sites/finance*. - Keyword Search: searches only indexed common-schema fields, not the full AuditData.
- Activities - operations names: exact operation names separated by commas, such as
- Give the search a Search name and select Search.
The search runs as a job. You can close the browser and come back; completed jobs are kept for 30 days. Each admin can run up to 10 search jobs at a time, only one of them unfiltered, and Microsoft notes that broad searches in large tenants can take up to 48 hours. Open a completed job to see Date (UTC), IP Address, User, Record type, Activity and Item, select a row to see the full record, and select Export to download a CSV. Export is limited to 50,000 rows for Audit (Standard) and 1,000,000 rows for Audit (Premium); split the date range if you are near the limit.
Step 2: Find who deleted a file or folder
In SharePoint and OneDrive, a normal delete sends the item to the site recycle bin. The relevant operations are:
| Operation | Activity |
|---|---|
FileRecycled / FolderRecycled | Moved a file or folder to the recycle bin |
FileDeleted / FolderDeleted | Deleted a file or folder from a site |
FileDeletedFirstStageRecycleBin | Deleted a file from the site recycle bin |
FileDeletedSecondStageRecycleBin | Deleted a file from the second-stage recycle bin |
FileRestored / FolderRestored | Restored from the recycle bin |
FileMoved / FolderMoved | Moved to another location on the site |
A file that "disappeared" is often moved rather than deleted, so include the move operations. In PowerShell, filter by the site URL with a trailing wildcard in ObjectIds:
Search-UnifiedAuditLog -StartDate "2026-10-01 00:00:00z" -EndDate "2026-10-11 00:00:00z" `
-RecordType SharePointFileOperation `
-Operations FileRecycled,FileDeleted,FolderRecycled,FolderDeleted,FileMoved,FolderMoved `
-ObjectIds "https://contoso.sharepoint.com/sites/finance/*" `
-SessionCommand ReturnLargeSet-RecordType accepts a single value. To combine record types, run separate searches and append the results.
Step 3: Find who shared a file or created a link
Sharing events use the SharePointSharingOperation record type. The operations that answer "who gave access to this":
| Operation | What happened |
|---|---|
SharingSet | Shared with a user already in your directory (member or guest) |
SharingInvitationCreated | Shared with someone not in your directory |
AnonymousLinkCreated | Created an anyone link; no sign-in needed to use it |
AnonymousLinkUsed | Someone opened an anyone link; the IP address is recorded |
CompanyLinkCreated | Created a link usable by anyone in the organization |
SecureLinkCreated, AddedToSecureLink | Created a secure sharing link, or added a user to the list of people who can use one |
SharingInvitationAccepted | An invitation was accepted |
SharingRevoked, AnonymousLinkRemoved | Access or a link was removed |
For SharingSet, the details identify who the item was shared with and whether they are a member or a guest. Sharing usually produces a second event that shows how access was granted, such as AddedToGroup, so read events around the same timestamp together.
Search-UnifiedAuditLog -StartDate "2026-09-01 00:00:00z" -EndDate "2026-10-11 00:00:00z" `
-RecordType SharePointSharingOperation `
-Operations AnonymousLinkCreated,AnonymousLinkUsed,SharingInvitationCreated,SharingSet `
-ObjectIds "https://contoso.sharepoint.com/sites/finance/Shared Documents/Budget 2027.xlsx" `
-SessionCommand ReturnLargeSetIf an anyone link was created, AnonymousLinkUsed shows every time it was opened and from which IP address.
Step 4: Find who deleted email
Mailbox actions are written to the unified audit log when mailbox auditing is on. Owner, delegate and admin deletions are audited by default:
| Operation | Meaning |
|---|---|
MoveToDeletedItems | Deleted and moved to Deleted Items |
SoftDelete | Deleted from Deleted Items or with Shift+Delete; moved to Recoverable Items |
HardDelete | Purged from Recoverable Items |
Send, SendAs, SendOnBehalf | Message sent as the owner, with Send As, or on behalf |
UserIds filters by who performed the action, which is not always the mailbox owner. To answer "who deleted mail from this mailbox", search the operations and filter on MailboxOwnerUPN after parsing AuditData (Step 6). LogonType then tells you whether it was the owner, a delegate or an admin.
$results = Search-UnifiedAuditLog -StartDate "2026-10-05 00:00:00z" -EndDate "2026-10-11 00:00:00z" `
-Operations SoftDelete,HardDelete,MoveToDeletedItems -SessionCommand ReturnLargeSet -ResultSize 5000Items that are soft-deleted or purged may still be recoverable while they are within the deleted item retention period or held by a retention policy; see the companion guide on Purview retention policies and labels.
Step 5: Find who created forwarding or an inbox rule
Forwarding is a common way for an attacker to keep receiving mail after a business email compromise. It can be set in three places, and each leaves a different audit record:
| How forwarding was set | Operation to search |
|---|---|
| Inbox rule created or changed in Outlook on the web or PowerShell | New-InboxRule, Set-InboxRule |
| Inbox rule created, changed or removed in the Outlook desktop client | UpdateInboxRules |
Mailbox forwarding (SMTP forwarding) configured with Set-Mailbox | Set-Mailbox (record type ExchangeAdmin) |
Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-30) -EndDate (Get-Date) `
-Operations "New-InboxRule","Set-InboxRule","UpdateInboxRules" -SessionCommand ReturnLargeSet
Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-30) -EndDate (Get-Date) `
-RecordType ExchangeAdmin -Operations "Set-Mailbox" -SessionCommand ReturnLargeSetFor Exchange admin activity, the Operation property holds the name of the cmdlet that was run and the Parameters property of AuditData lists every parameter and value used, so a forwarding change shows the forwarding address that was set. ObjectId shows which mailbox was changed. ExternalAccess set to True means the cmdlet was run by Microsoft datacenter personnel, a datacenter service account or a delegated administrator rather than someone in your organization. For the full clean-up procedure after you find a rule, see finding malicious inbox and forwarding rules.
Step 6: Page through results and parse AuditData
Without -SessionCommand, the cmdlet returns 100 records. Two session modes are available:
| SessionCommand | Order | Maximum |
|---|---|---|
ReturnLargeSet | Unsorted, optimised for speed | 50,000 records through paging |
ReturnNextPreviewPage | Sorted by date | 5,000 records |
Run the same command with the same SessionId until it returns nothing. Never switch between the two values for one session ID, or output is limited to 10,000 records.
$start = "2026-10-01 00:00:00z"
$end = "2026-10-11 00:00:00z"
$sessionId = [guid]::NewGuid().ToString()
$all = @()
do {
$page = Search-UnifiedAuditLog -StartDate $start -EndDate $end `
-Operations FileRecycled,FileDeleted,AnonymousLinkCreated,SharingSet `
-SessionId $sessionId -SessionCommand ReturnLargeSet -ResultSize 5000
$all += $page
} while ($page.Count -gt 0)
$rows = $all | ForEach-Object {
$d = $_.AuditData | ConvertFrom-Json
[pscustomobject]@{
TimeUtc = $d.CreationTime
User = $d.UserId
Operation = $d.Operation
ClientIP = $d.ClientIP
Object = $d.ObjectId
Workload = $d.Workload
}
}
$rows | Sort-Object TimeUtc | Export-Csv -Path C:\AuditLogs\incident.csv -NoTypeInformationBecause ReturnLargeSet is unsorted, sort after you collect everything. To check progress during a long run, look at the ResultIndex and ResultCount values returned with each page. For large or recurring exports, Microsoft recommends the Office 365 Management Activity API instead of a PowerShell loop.
If you prefer Excel, import the portal export with Data > From Text/CSV > Transform Data, right-click AuditData, select Transform > JSON, then expand the column. Power Query only proposes properties found in the first 1,000 rows, so filter Operations first if you need properties that only rare events have.
Verify your findings
- Confirm the timestamp in UTC and convert it to the reporter's local time before you write it up.
- Check
UserIdagainstClientIP,ClientInfoStringand the Microsoft Entra sign-in logs for the same window. An unfamiliar IP or client on the same account is the strongest signal of compromise. - For SharePoint events, compare
ObjectIdwith the item's current location; aFileMovedevent usually explains a missing file. - Re-run the search with
-HighCompletenessif it is available in your tenant. It is in preview, returns more complete results and takes longer. - Record the search criteria with the export, so the result can be reproduced.
Troubleshooting
No results at all. Check the date range first. If you pass the same date for StartDate and EndDate without a time, both are midnight and nothing is returned. Then confirm UnifiedAuditLogIngestionEnabled is True in Exchange Online PowerShell, and remember the 60 to 90 minute typical delay.
"The start date is earlier than the end date" or a range error in the portal. The portal accepts a maximum of 180 days, and the range can't start before auditing was turned on. When you use the full 180 days, select the current time for the start date.
Results stop at 100 or 5,000. Use -SessionCommand ReturnLargeSet with a SessionId and keep calling until an empty page comes back.
Results stop at 10,000. You switched SessionCommand values within one session ID. Start a new session ID and use one value throughout.
Operation names return nothing. Names must match exactly. Some Microsoft Entra operations end with a period, such as Add member to role.; wrap those in double quotes.
Mailbox events are missing for one user. The user may have a mailbox audit bypass association, or mailbox actions were customised so the action isn't audited. Check DefaultAuditSet, AuditOwner, AuditDelegate and AuditAdmin with Get-Mailbox. A Global Administrator can also run the audit log configuration check diagnostic from the Microsoft 365 admin center (https://aka.ms/PillarAuditConfigDiag) and enter the affected user's UPN.
You see some records but not others. You may be a restricted admin scoped to administrative units. Ask an unrestricted admin to run the search.
The CSV is missing rows. The export limit is 50,000 rows for Audit (Standard). Split the search into smaller date ranges.
Checklist
- Ingestion confirmed with
Get-AdminAuditLogConfigin Exchange Online PowerShell. - Mailbox auditing confirmed; no bypass on the accounts involved.
- Audit Logs or View-Only Audit Logs role assigned to the investigators.
- Incident window converted to UTC and kept under 180 days.
- Exact operation names chosen for each question: deletion, sharing, mailbox deletion, forwarding.
- Results paged with
ReturnLargeSetand one session ID, then sorted. - AuditData parsed for
UserId,ClientIP,ObjectId,ParametersandMailboxOwnerUPN. - Findings cross-checked with Entra sign-in logs and saved with the search criteria.
- Retention reviewed if you need records older than 180 days in future incidents.