Exchange Online reporting

How to list deleted mailboxes in Exchange Online

List soft-deleted and inactive mailboxes with Exchange Online PowerShell, check deleted users and inactive mailboxes in the admin centres, or run Altivane's Deleted Mailboxes report.

By the Published

To list deleted mailboxes in Exchange Online, run Get-EXOMailbox -SoftDeletedMailbox for the soft-deleted ones and Get-EXOMailbox -InactiveMailboxOnly for those a hold keeps. A soft-deleted mailbox can be restored for 30 days and is then gone for good, while an inactive mailbox stays until its hold is removed.

Choose the method that fits the job
MethodBest fit
PowerShellA CSV of soft-deleted and inactive mailboxes with the days left to restore each.
Admin centreA look at the deleted users list, or at inactive mailboxes in the Purview portal.
AltivaneRecommended for leaver clean-ups, with mailboxes near permanent deletion marked and a workbook to keep.

Before you start

Use an account in a role group that can read recipients: Microsoft lists Organization Management and Recipient Management, and says members of View-Only Management can view the configuration. Viewing inactive mailboxes in the Microsoft Purview portal uses a Compliance Administrator account.

Know the 2 states. A mailbox is soft-deleted when its user account is deleted, and Microsoft keeps it for 30 days. A mailbox placed on Litigation Hold or another hold before it was deleted becomes inactive, and its contents are kept until the last hold is removed and for 30 days after. The examples read and export; they restore, recover or purge nothing.

Option 1

List deleted mailboxes with PowerShell

Install the module once, then connect and export both lists, each mailbox once.

PowerShell
# Install once, if the module is not already installed.
Install-Module ExchangeOnlineManagement -Scope CurrentUser
PowerShell
$ErrorActionPreference = 'Stop'
Connect-ExchangeOnline -ShowBanner:$false
try {
    $query = @{
        ResultSize = 'Unlimited'
        PropertySets = 'Minimum', 'SoftDelete', 'Hold'
        Properties = 'ExchangeGuid'
    }
    $soft = @(Get-EXOMailbox -SoftDeletedMailbox @query)
    $inactive = @(Get-EXOMailbox -InactiveMailboxOnly @query)
    $now = (Get-Date).ToUniversalTime()
    $seen = @{}
    $report = @(foreach ($mailbox in $soft + $inactive) {
        $key = "$($mailbox.ExchangeGuid)"
        if ($seen.ContainsKey($key)) { continue }
        $seen[$key] = $true
        $held = [bool]$mailbox.IsInactiveMailbox
        $start = $mailbox.WhenSoftDeleted
        if ($mailbox.InactiveMailboxRetireTime) { $start = $mailbox.InactiveMailboxRetireTime }
        $daysLeft = $null
        if (-not $held -and $start) {
            $until = ([datetime]$start).ToUniversalTime().AddDays(30)
            $daysLeft = [math]::Floor(($until - $now).TotalDays)
        }
        [pscustomobject]@{
            Name = $mailbox.DisplayName
            Address = $mailbox.PrimarySmtpAddress.ToString()
            Type = $mailbox.RecipientTypeDetails
            State = if ($held) { 'Inactive' } else { 'Soft-deleted' }
            Deleted = $mailbox.WhenSoftDeleted
            DaysLeft = $daysLeft
            LitigationHold = $mailbox.LitigationHoldEnabled
            ExchangeGuid = $key
        }
    })
    if ($report.Count -eq 0) {
        Write-Output 'There are no soft-deleted or inactive mailboxes.'
    } else {
        $report | Sort-Object Deleted -Descending |
            Export-Csv -Path './deleted-mailboxes.csv' -NoTypeInformation -Encoding utf8
        Write-Output "$($report.Count) deleted mailboxes exported."
    }
} finally {
    Disconnect-ExchangeOnline -Confirm:$false
}

The CSV has 1 row for each mailbox, newest deletion first. DaysLeft counts 30 days in UTC from WhenSoftDeleted, or from InactiveMailboxRetireTime for a mailbox whose last hold was removed, since Microsoft keeps it 30 days from then. It is blank for an inactive mailbox, which has no end date of its own. A mailbox in both lists is kept once, matched by its Exchange GUID.

Check the holds on 1 inactive mailbox

Reconnect with Connect-ExchangeOnline, then read the holds that keep it. The export above disconnects when it finishes.

PowerShell
# Run while connected to Exchange Online. Replace the example mailbox.
Get-EXOMailbox -Identity 'leaver@example.com' -InactiveMailboxOnly -PropertySets Hold |
    Select-Object LitigationHoldEnabled, LitigationHoldDuration, InPlaceHolds

Option 2

Find deleted mailboxes in the admin centres

  1. Sign in to the Microsoft 365 admin centre for the correct tenant and go to Users > Deleted users. It lists the accounts deleted in the last 30 days, whose mailboxes can still be restored with them.
  2. For inactive mailboxes, sign in to the Microsoft Purview portal and go to Solutions > Data Lifecycle Management > Policies > Retention policies.
  3. Select Inactive mailbox to open the list, then select a mailbox for its Exchange identifier and whether it is on Litigation Hold.
  4. Leave each page without restoring a user or changing a policy, so nothing changes.

This suits a quick look. The Exchange admin centre can't delete or restore mailboxes, the deleted users list shows accounts rather than mailboxes, and the Purview list shows at most 5,000 inactive mailboxes and only Litigation Hold among the holds.

Common questions

How do I get a soft-deleted mailbox back?

Restore the user account in the Microsoft 365 admin centre within 30 days, and the mailbox comes back with it. Microsoft recommends restoring from the place the user or mailbox was deleted from, or the restore fails. The Exchange admin centre has no restore.

Why is a leaver from last year still listed?

Their mailbox was on hold when the account was deleted, so it became inactive and is kept until the hold is removed. To see which mailboxes are on hold now, see how to find mailboxes on litigation hold in Exchange Online.

Why does the same address appear twice?

An inactive mailbox can have the same SMTP address as an active one. Microsoft says to tell them apart by the distinguished name or the Exchange GUID, which is why the script keeps the GUID.

Microsoft references

Technical references checked on 7 November 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.

Talk to us about Altivane

Questions, or pricing? Get in touch.

Contact us