SHELL/2.1.8.ps1

$CheckId = "2.1.8"
$Title = "Ensure that SPF records are published for all Exchange Domains"

try {
    $AcceptedDomains = Get-AcceptedDomain | ForEach-Object { $_.DomainName.ToString() }

    $DomainResults = foreach ($Domain in $AcceptedDomains) {
        try {
            $TxtRecords = Resolve-DnsName -Name $Domain -Type TXT -ErrorAction Stop
            $SpfRecords = $TxtRecords |
                Where-Object { $_.Strings } |
                ForEach-Object { ($_.Strings -join "") } |
                Where-Object { $_ -like "v=spf1*" }

            [pscustomobject]@{
                Domain                       = $Domain
                SpfRecord                    = ($SpfRecords -join " | ")
                IncludesOutlookProtectionSpf = [bool]($SpfRecords -match "include:spf.protection.outlook.com")
                Status                       = if ($SpfRecords) { "RecordFound" } else { "RecordMissing" }
            }
        }
        catch {
            [pscustomobject]@{
                Domain                       = $Domain
                SpfRecord                    = $null
                IncludesOutlookProtectionSpf = $false
                Status                       = "LookupFailed"
                Error                        = $_.Exception.Message
            }
        }
    }

    $NonCompliant = $DomainResults | Where-Object {
        $_.Status -ne "RecordFound" -or $_.IncludesOutlookProtectionSpf -ne $true
    }
    $Pass = @($DomainResults).Count -gt 0 -and @($NonCompliant).Count -eq 0

    [pscustomobject]@{
        CheckId   = $CheckId
        Title     = $Title
        Status    = if ($Pass) { "PASS" } else { "FAIL" }
        Pass      = $Pass
        Evidence  = [pscustomobject]@{
            DomainResults = @($DomainResults)
            NonCompliant  = @($NonCompliant)
        }
        Error     = $null
        Timestamp = Get-Date
    }
}
catch {
    [pscustomobject]@{
        CheckId   = $CheckId
        Title     = $Title
        Status    = "ERROR"
        Pass      = $null
        Evidence  = $null
        Error     = $_.Exception.Message
        Timestamp = Get-Date
    }
}