SHELL/2.1.15.ps1

$CheckId = "2.1.15"
$Title = "Ensure outbound anti-spam message limits are in place"
$Level = "L1"
$BenchmarkType = "Automated"

try {
    # CIS audit commands:
    # $params = (
    # 'RecipientLimitExternalPerHour',
    # 'RecipientLimitInternalPerHour',
    # 'RecipientLimitPerDay',
    # 'ActionWhenThresholdReached'
    # )
    # Get-HostedOutboundSpamFilterPolicy -Identity Default | fl $params
    $Policy = Get-HostedOutboundSpamFilterPolicy -Identity Default

    $ExternalLimit = [int]$Policy.RecipientLimitExternalPerHour
    $InternalLimit = [int]$Policy.RecipientLimitInternalPerHour
    $DailyLimit = [int]$Policy.RecipientLimitPerDay
    $ActionWhenThresholdReached = [string]$Policy.ActionWhenThresholdReached
    $NotifyRecipients = @($Policy.NotifyOutboundSpamRecipients | Where-Object {
        -not [string]::IsNullOrWhiteSpace([string]$_)
    } | ForEach-Object { ([string]$_).Trim() })

    # Recommended values or more restrictive:
    # External <= 500, Internal <= 1000, Daily <= 1000, Action = BlockUser
    # plus at least one monitored mailbox in NotifyOutboundSpamRecipients.
    $ExternalOk = ($ExternalLimit -gt 0 -and $ExternalLimit -le 500)
    $InternalOk = ($InternalLimit -gt 0 -and $InternalLimit -le 1000)
    $DailyOk = ($DailyLimit -gt 0 -and $DailyLimit -le 1000)
    $ActionOk = ($ActionWhenThresholdReached -eq "BlockUser")
    $NotifyOk = (@($NotifyRecipients).Count -gt 0)

    $Pass = $ExternalOk -and $InternalOk -and $DailyOk -and $ActionOk -and $NotifyOk

    $FailureReasons = @()
    if (-not $ExternalOk) { $FailureReasons += "RecipientLimitExternalPerHour must be between 1 and 500." }
    if (-not $InternalOk) { $FailureReasons += "RecipientLimitInternalPerHour must be between 1 and 1000." }
    if (-not $DailyOk) { $FailureReasons += "RecipientLimitPerDay must be between 1 and 1000." }
    if (-not $ActionOk) { $FailureReasons += "ActionWhenThresholdReached must be BlockUser." }
    if (-not $NotifyOk) { $FailureReasons += "NotifyOutboundSpamRecipients must include at least one monitored mailbox." }

    [pscustomobject]@{
        CheckId       = $CheckId
        Title         = $Title
        Level         = $Level
        BenchmarkType = $BenchmarkType
        Status        = if ($Pass) { "PASS" } else { "FAIL" }
        Pass          = $Pass
        Evidence      = [pscustomobject]@{
            PolicyIdentity                   = $Policy.Identity
            RecipientLimitExternalPerHour    = $ExternalLimit
            RecipientLimitInternalPerHour    = $InternalLimit
            RecipientLimitPerDay             = $DailyLimit
            ActionWhenThresholdReached       = $ActionWhenThresholdReached
            NotifyOutboundSpamRecipients     = @($NotifyRecipients)
            Checks                           = [pscustomobject]@{
                ExternalLimitCompliant       = $ExternalOk
                InternalLimitCompliant       = $InternalOk
                DailyLimitCompliant          = $DailyOk
                ActionCompliant              = $ActionOk
                NotifyRecipientsConfigured   = $NotifyOk
            }
            RecommendedState                 = [pscustomobject]@{
                RecipientLimitExternalPerHour = "<=500 (and >0)"
                RecipientLimitInternalPerHour = "<=1000 (and >0)"
                RecipientLimitPerDay          = "<=1000 (and >0)"
                ActionWhenThresholdReached    = "BlockUser"
                NotifyOutboundSpamRecipients  = "At least one monitored mailbox"
            }
            SourceDocument                  = "CIS_Microsoft_365_Foundations_Benchmark_v6.0.1"
            AuditCommand                    = "Get-HostedOutboundSpamFilterPolicy -Identity Default | fl RecipientLimitExternalPerHour,RecipientLimitInternalPerHour,RecipientLimitPerDay,ActionWhenThresholdReached,NotifyOutboundSpamRecipients"
        }
        Error         = if ($Pass) { $null } else { ($FailureReasons -join " ") }
        Timestamp     = Get-Date
    }
}
catch {
    [pscustomobject]@{
        CheckId       = $CheckId
        Title         = $Title
        Level         = $Level
        BenchmarkType = $BenchmarkType
        Status        = "ERROR"
        Pass          = $null
        Evidence      = [pscustomobject]@{
            SourceDocument = "CIS_Microsoft_365_Foundations_Benchmark_v6.0.1"
            AuditCommand   = "Get-HostedOutboundSpamFilterPolicy -Identity Default | fl RecipientLimitExternalPerHour,RecipientLimitInternalPerHour,RecipientLimitPerDay,ActionWhenThresholdReached,NotifyOutboundSpamRecipients"
        }
        Error         = $_.Exception.Message
        Timestamp     = Get-Date
    }
}