Public/Get-PublicFolderAnalysis.ps1

function Get-PublicFolderAnalysis {
    <#
    .SYNOPSIS
        Analyzes public folders for migration to M365 Groups or shared mailboxes.
 
    .DESCRIPTION
        Inventories public folders with size, item count, permissions, and
        mail-enablement status. Provides recommendations for migration target
        (M365 Group, Shared Mailbox, or SharePoint).
 
    .PARAMETER MaxDepth
        Maximum folder hierarchy depth to report. Defaults to 5.
 
    .EXAMPLE
        Get-PublicFolderAnalysis
 
    .EXAMPLE
        Get-PublicFolderAnalysis | Where-Object SizeGB -gt 1 | Sort-Object SizeGB -Descending
 
    .NOTES
        Public folder migration to M365 has specific size limits.
        Folders > 25 GB require splitting before migration.
    #>

    [CmdletBinding()]
    param(
        [int]$MaxDepth = 5
    )

    Write-Verbose "Getting public folder hierarchy..."
    $folders = Get-PublicFolder -Recurse -ResultSize Unlimited -ErrorAction Stop

    $total = $folders.Count
    $current = 0

    foreach ($folder in $folders) {
        $current++
        if ($current % 25 -eq 0) {
            Write-Progress -Activity "Analyzing public folders" -Status "$($folder.Name) ($current/$total)" -PercentComplete (($current / $total) * 100)
        }

        # Calculate depth
        $depth = ($folder.Identity.ToString().Split('\')).Count - 1
        if ($depth -gt $MaxDepth) { continue }

        # Get statistics
        try {
            $stats = Get-PublicFolderStatistics -Identity $folder.Identity -ErrorAction Stop
            $sizeGB = [math]::Round($stats.TotalItemSize.Value.ToBytes() / 1GB, 3)
            $itemCount = $stats.ItemCount
        }
        catch {
            $sizeGB = 0
            $itemCount = 0
        }

        # Check if mail-enabled
        $mailEnabled = $folder.MailEnabled

        # Get permissions
        $permissions = try {
            (Get-PublicFolderClientPermission -Identity $folder.Identity -ErrorAction SilentlyContinue |
                Where-Object { $_.User.DisplayName -notin @('Default', 'Anonymous') } |
                ForEach-Object { "$($_.User.DisplayName):$($_.AccessRights -join ',')" }
            ) -join '; '
        }
        catch { '' }

        # Migration recommendation
        $recommendation = if ($sizeGB -gt 25) { 'Split before migration (>25GB limit)' }
                          elseif ($mailEnabled) { 'Consider M365 Group (mail-enabled)' }
                          elseif ($folder.FolderClass -eq 'IPF.Appointment') { 'Consider shared calendar' }
                          elseif ($folder.FolderClass -eq 'IPF.Contact') { 'Consider shared contacts' }
                          elseif ($sizeGB -gt 1) { 'SharePoint document library' }
                          elseif ($itemCount -eq 0) { 'Empty - consider removing' }
                          else { 'M365 Group or shared mailbox' }

        [PSCustomObject]@{
            Path           = $folder.Identity.ToString()
            Name           = $folder.Name
            Depth          = $depth
            FolderClass    = $folder.FolderClass
            MailEnabled    = $mailEnabled
            SizeGB         = $sizeGB
            ItemCount      = $itemCount
            Permissions    = $permissions
            HasSubFolders  = $folder.HasSubFolders
            Recommendation = $recommendation
        }
    }

    Write-Progress -Activity "Analyzing public folders" -Completed
}