Src/Private/Get-AbrExoRecovery.ps1

function Get-AbrExoRecovery {
    <#
    .SYNOPSIS
    Documents Exchange Online backup and recovery capabilities: native recovery options,
    service-level recovery, deleted item retention periods, and third-party backup posture.
    .NOTES
        Version: 0.1.0
        Author: Pai Wei Sing
    #>

    [CmdletBinding()]
    param (
        [Parameter(Position = 0, Mandatory)]
        [string]$TenantId
    )

    begin {
        Write-PScriboMessage -Message "Collecting Exchange Online Recovery/Backup configuration for $TenantId."
        Show-AbrDebugExecutionTime -Start -TitleMessage 'Recovery'
    }

    process {
        Section -Style Heading2 'Backup, Recovery & Business Continuity' {
            Paragraph "The following section documents native Exchange Online recovery capabilities, data retention for recovery purposes, and the overall recovery posture for tenant $TenantId."
            BlankLine

            #region Native Recovery Capabilities
            Section -Style Heading3 'Native Recovery Capabilities' {
                Paragraph "Exchange Online does not provide traditional backup files. Microsoft provides the following native data recovery mechanisms:"
                BlankLine

                $NatRecObj = [System.Collections.ArrayList]::new()
                $natRows = @(
                    [pscustomobject]@{
                        'Recovery Method'       = 'Deleted Items Folder'
                        'Retention Period'      = 'Until user empties folder'
                        'Who Can Recover'       = 'User (self-service via OWA/Outlook)'
                        'Data Covered'          = 'Items deleted by the user (first-stage delete)'
                        'RPO'                   = 'Immediate (no data loss)'
                    }
                    [pscustomobject]@{
                        'Recovery Method'       = 'Recoverable Items (Soft Delete)'
                        'Retention Period'      = '14 days default (configurable up to 30 days)'
                        'Who Can Recover'       = 'User via Recover Deleted Items, or Admin via eDiscovery'
                        'Data Covered'          = 'Items removed from Deleted Items, shift-deleted items'
                        'RPO'                   = 'Up to 14-30 days prior to hard delete'
                    }
                    [pscustomobject]@{
                        'Recovery Method'       = 'Single Item Recovery (SIR)'
                        'Retention Period'      = '14 days default while enabled'
                        'Who Can Recover'       = 'Admin via eDiscovery / Content Search'
                        'Data Covered'          = 'Protects against purge of recoverable items'
                        'RPO'                   = 'Up to 14 days before purge'
                    }
                    [pscustomobject]@{
                        'Recovery Method'       = 'Litigation Hold'
                        'Retention Period'      = 'Indefinite (while hold is active)'
                        'Who Can Recover'       = 'Admin via eDiscovery / Content Search'
                        'Data Covered'          = 'All mailbox content (including sent/calendar/tasks)'
                        'RPO'                   = 'Zero data loss from point of hold activation'
                    }
                    [pscustomobject]@{
                        'Recovery Method'       = 'In-Place Archive'
                        'Retention Period'      = 'Unlimited (separate 100 GB+ archive mailbox)'
                        'Who Can Recover'       = 'User (self-service) and Admin'
                        'Data Covered'          = 'Archived email content'
                        'RPO'                   = 'Data retained in archive indefinitely'
                    }
                    [pscustomobject]@{
                        'Recovery Method'       = 'Microsoft 365 Service-Level Backup'
                        'Retention Period'      = 'Microsoft internal (14+ day geo-redundant replication)'
                        'Who Can Recover'       = 'Microsoft (via support request for catastrophic loss)'
                        'Data Covered'          = 'Entire service data centre failure scenarios only'
                        'RPO'                   = 'Not a user-accessible backup; SLA-based recovery only'
                    }
                )
                foreach ($row in $natRows) { $NatRecObj.Add($row) | Out-Null }

                $NatTableParams = @{ Name = "Native Recovery Methods - $TenantId"; List = $false; ColumnWidths = 18, 18, 22, 24, 18 }
                if ($Report.ShowTableCaptions) { $NatTableParams['Caption'] = "- $($NatTableParams.Name)" }
                if ($NatRecObj.Count -gt 0) { $NatRecObj | Table @NatTableParams }
            }
            #endregion

            #region Tenant Recovery Configuration Summary
            try {
                Write-Host " - Retrieving tenant recovery configuration..."
                $AllMailboxes = Get-Mailbox -ResultSize Unlimited -ErrorAction Stop |
                    Where-Object { $_.RecipientTypeDetails -in @('UserMailbox', 'SharedMailbox') }

                $SirEnabled      = @($AllMailboxes | Where-Object { $_.SingleItemRecoveryEnabled -eq $true }).Count
                $LitHoldCount    = @($AllMailboxes | Where-Object { $_.LitigationHoldEnabled -eq $true }).Count
                $ArchiveEnabled  = @($AllMailboxes | Where-Object { $_.ArchiveStatus -ne 'None' }).Count
                $TotalMbx        = @($AllMailboxes).Count

                # Most common deleted items retention
                $CommonRetention = $AllMailboxes |
                    Group-Object -Property RetainDeletedItemsFor |
                    Sort-Object Count -Descending |
                    Select-Object -First 1

                Section -Style Heading3 'Tenant Recovery Configuration' {
                    Paragraph "The following summarises the recovery configuration across $TotalMbx mailbox(es) in tenant $TenantId."
                    BlankLine

                    $TrcObj = [System.Collections.ArrayList]::new()
                    $trcInObj = [ordered] @{
                        'Total Mailboxes'                           = $TotalMbx
                        'Single Item Recovery Enabled'              = "$SirEnabled of $TotalMbx ($([math]::Round(($SirEnabled / [math]::Max($TotalMbx,1)) * 100, 0))%)"
                        'Litigation Hold Active'                    = "$LitHoldCount of $TotalMbx"
                        'Archive Mailbox Enabled'                   = "$ArchiveEnabled of $TotalMbx ($([math]::Round(($ArchiveEnabled / [math]::Max($TotalMbx,1)) * 100, 0))%)"
                        'Most Common Deleted Item Retention'        = if ($CommonRetention) { "$($CommonRetention.Name) ($($CommonRetention.Count) mailboxes)" } else { 'Unknown' }
                    }
                    $TrcObj.Add([pscustomobject]$trcInObj) | Out-Null

                    $TrcTableParams = @{ Name = "Recovery Configuration Summary - $TenantId"; List = $true; ColumnWidths = 45, 55 }
                    if ($Report.ShowTableCaptions) { $TrcTableParams['Caption'] = "- $($TrcTableParams.Name)" }
                    $TrcObj | Table @TrcTableParams
                }
            } catch {
                Write-ExoError 'Recovery' "Unable to retrieve recovery configuration: $($_.Exception.Message)"
            }
            #endregion

            #region RPO/RTO Summary
            Section -Style Heading3 'Recovery Objectives' {
                Paragraph "The following documents the native recovery objectives for Exchange Online in tenant $TenantId. NOTE: Third-party backup solutions may provide additional RPO/RTO capabilities."
                BlankLine

                $RpoObj = [System.Collections.ArrayList]::new()
                $rpoRows = @(
                    [pscustomobject]@{ 'Scenario'='Accidental email deletion (user recovers)';  'RPO'='0 (immediate)'; 'RTO'='Minutes (self-service)'; 'Method'='Recover Deleted Items in Outlook/OWA' }
                    [pscustomobject]@{ 'Scenario'='Accidental purge from Recoverable Items'; 'RPO'='Up to 14 days'; 'RTO'='Hours (admin via eDisc)'; 'Method'='Content Search / eDiscovery export' }
                    [pscustomobject]@{ 'Scenario'='Mailbox corruption / accidental bulk delete'; 'RPO'='Up to 14-30 days'; 'RTO'='Hours to days'; 'Method'='eDiscovery, Litigation Hold restore' }
                    [pscustomobject]@{ 'Scenario'='Ransomware / malicious deletion'; 'RPO'='Point of Litigation Hold / archive'; 'RTO'='Days'; 'Method'='eDiscovery, Microsoft support, third-party backup' }
                    [pscustomobject]@{ 'Scenario'='Microsoft datacentre failure'; 'RPO'='Near-zero (geo-redundant)'; 'RTO'='Per Microsoft SLA (99.9% uptime)'; 'Method'='Automatic failover (Microsoft managed)' }
                )
                foreach ($row in $rpoRows) { $RpoObj.Add($row) | Out-Null }

                $RpoTableParams = @{ Name = "Recovery Objectives - $TenantId"; List = $false; ColumnWidths = 28, 14, 18, 40 }
                if ($Report.ShowTableCaptions) { $RpoTableParams['Caption'] = "- $($RpoTableParams.Name)" }
                if ($RpoObj.Count -gt 0) { $RpoObj | Table @RpoTableParams }
            }
            #endregion

            #region Third-Party Backup Note
            Section -Style Heading3 'Third-Party Backup Assessment' {
                Paragraph "Microsoft Exchange Online does not provide a traditional tape or snapshot backup. For organisations requiring point-in-time recovery beyond native capabilities (particularly for ransomware recovery, accidental bulk deletes, or regulatory requirements), a third-party backup solution is recommended."
                BlankLine
                Paragraph "Third-party backup solutions commonly used with Microsoft 365 include: Veeam Backup for Microsoft 365, Druva inSync, Acronis Cyber Cloud, Barracuda Cloud-to-Cloud Backup, and AvePoint Cloud Backup."
                BlankLine
                Paragraph "RECOMMENDATION: Review whether the organisation's backup and recovery strategy requirements are met by native Microsoft 365 capabilities alone, or whether a third-party backup solution should be implemented. Document the decision and review annually."
            }
            #endregion
        }
    }

    end {
        Show-AbrDebugExecutionTime -End -TitleMessage 'Recovery'
    }
}