Public/Get-MailboxInventory.ps1

function Get-MailboxInventory {
    <#
    .SYNOPSIS
        Inventories all mailboxes with size, type, and migration-relevant details.
 
    .DESCRIPTION
        Gathers mailbox data needed for migration planning:
        - Mailbox size and item count
        - Mailbox type (User, Shared, Room, Equipment)
        - Archive mailbox status and size
        - Litigation/retention hold status (migration blocker awareness)
        - Forwarding rules
        - Protocol access (ActiveSync, OWA, etc.)
 
    .PARAMETER RecipientType
        Filter by recipient type. Defaults to all mailbox types.
 
    .PARAMETER MinimumSizeGB
        Only return mailboxes larger than this size. Useful for identifying large migrations.
 
    .EXAMPLE
        Get-MailboxInventory
 
    .EXAMPLE
        Get-MailboxInventory -MinimumSizeGB 10 | Sort-Object SizeGB -Descending
 
    .NOTES
        Requires: Exchange Management Shell or ExchangeOnlineManagement module.
    #>

    [CmdletBinding()]
    param(
        [ValidateSet('UserMailbox', 'SharedMailbox', 'RoomMailbox', 'EquipmentMailbox', 'All')]
        [string]$RecipientType = 'All',

        [double]$MinimumSizeGB = 0
    )

    $mailboxParams = @{ ResultSize = 'Unlimited' }
    if ($RecipientType -ne 'All') {
        $mailboxParams['RecipientTypeDetails'] = $RecipientType
    }

    $mailboxes = Get-Mailbox @mailboxParams
    $total = $mailboxes.Count
    $current = 0

    foreach ($mbx in $mailboxes) {
        $current++
        if ($current % 25 -eq 0) {
            Write-Progress -Activity "Inventorying mailboxes" -Status "$($mbx.Alias) ($current/$total)" -PercentComplete (($current / $total) * 100)
        }

        try {
            $stats = Get-MailboxStatistics -Identity $mbx.Identity -ErrorAction Stop
            $sizeGB = [math]::Round($stats.TotalItemSize.Value.ToBytes() / 1GB, 2)
        }
        catch {
            $stats = $null
            $sizeGB = 0
        }

        if ($sizeGB -lt $MinimumSizeGB) { continue }

        # Archive info
        $archiveSizeGB = 0
        if ($mbx.ArchiveDatabase -or $mbx.ArchiveGuid -ne [guid]::Empty) {
            try {
                $archiveStats = Get-MailboxStatistics -Identity $mbx.Identity -Archive -ErrorAction Stop
                $archiveSizeGB = [math]::Round($archiveStats.TotalItemSize.Value.ToBytes() / 1GB, 2)
            }
            catch { }
        }

        [PSCustomObject]@{
            DisplayName          = $mbx.DisplayName
            Alias                = $mbx.Alias
            PrimarySmtpAddress   = $mbx.PrimarySmtpAddress
            RecipientType        = $mbx.RecipientTypeDetails
            SizeGB               = $sizeGB
            ItemCount            = if ($stats) { $stats.ItemCount } else { 0 }
            HasArchive           = [bool]($mbx.ArchiveDatabase -or $mbx.ArchiveGuid -ne [guid]::Empty)
            ArchiveSizeGB        = $archiveSizeGB
            LitigationHold       = $mbx.LitigationHoldEnabled
            RetentionHold        = $mbx.RetentionHoldEnabled
            ForwardingAddress    = $mbx.ForwardingAddress
            ForwardingSMTP       = $mbx.ForwardingSmtpAddress
            ActiveSyncEnabled    = $mbx.ActiveSyncEnabled
            OWAEnabled           = $mbx.OWAEnabled
            Database             = $mbx.Database
            ServerName           = $mbx.ServerName
        }
    }

    Write-Progress -Activity "Inventorying mailboxes" -Completed
}