SHELL/2.1.10.ps1

$CheckId = "2.1.10"
$Title = "Ensure DMARC Records for all Exchange Online domains are published"

try {
    $AcceptedDomains = Get-AcceptedDomain | ForEach-Object { $_.DomainName.ToString() }
    $MoeraDomain = Get-MgDomain -All | Where-Object { $_.IsInitial -eq $true } | Select-Object -First 1 -ExpandProperty Id
    $DomainsToCheck = @($AcceptedDomains + $MoeraDomain | Where-Object { $_ } | Sort-Object -Unique)

    $DomainResults = foreach ($Domain in $DomainsToCheck) {
        $QueryName = "_dmarc.$Domain"

        try {
            $TxtRecords = Resolve-DnsName -Name $QueryName -Type TXT -ErrorAction Stop |
                Where-Object { $_.Strings } |
                ForEach-Object { ($_.Strings -join "") }

            $DmarcRecords = $TxtRecords | Where-Object { $_ -match "^v=DMARC1;" }

            if (-not $DmarcRecords) {
                [pscustomobject]@{
                    Domain      = $Domain
                    QueryName   = $QueryName
                    Record      = $null
                    PolicyOk    = $false
                    Pct100      = $false
                    RuaPresent  = $false
                    RufPresent  = $false
                    IsCompliant = $false
                    Status      = "DmarcRecordMissing"
                }
                continue
            }

            foreach ($Record in $DmarcRecords) {
                $PolicyOk = $Record -match "(^|;)\s*p=(reject|quarantine)(;|$)"
                $Pct100 = $Record -match "(^|;)\s*pct=100(;|$)"
                $RuaPresent = $Record -match "(^|;)\s*rua=mailto:[^;\s]+"
                $RufPresent = $Record -match "(^|;)\s*ruf=mailto:[^;\s]+"

                [pscustomobject]@{
                    Domain      = $Domain
                    QueryName   = $QueryName
                    Record      = $Record
                    PolicyOk    = $PolicyOk
                    Pct100      = $Pct100
                    RuaPresent  = $RuaPresent
                    RufPresent  = $RufPresent
                    IsCompliant = ($PolicyOk -and $Pct100 -and $RuaPresent -and $RufPresent)
                    Status      = "RecordParsed"
                }
            }
        }
        catch {
            [pscustomobject]@{
                Domain      = $Domain
                QueryName   = $QueryName
                Record      = $null
                PolicyOk    = $false
                Pct100      = $false
                RuaPresent  = $false
                RufPresent  = $false
                IsCompliant = $false
                Status      = "LookupFailed"
                Error       = $_.Exception.Message
            }
        }
    }

    $NonCompliant = $DomainResults | Where-Object { $_.IsCompliant -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
    }
}