Private/Helper/Debug-SPFRecord.ps1

<#
Copyright © 2024 Integris. For internal company use only. All rights reserved.
#>


FUNCTION Get-DNSEmailHealthCheck {

    [CmdletBinding()]
    PARAM (
        [Parameter(Mandatory)]
        [string[]]$Domain,
        [switch]$IssuesOnly = $False,
        [switch]$CheckBlacklist = $False
    )

    FUNCTION Debug-SPFRecord {

    <#
    .SYNOPSIS
    Checks SPF Records for correct syntax.
 
    .DESCRIPTION
    Checks SPF Records for correct syntax and returns the results
 
    .EXAMPLE
    Debug-DNSRecordSPF IntegrisIT.com
 
    Checks SPF Records for correct syntax and returns the results
    #>


    param (
        [Parameter(Mandatory)]
        [string]$Domain
    )      

    FUNCTION Format-SPFRecord {

        param (
            [Parameter(Mandatory)]
            [string]$Domain2
        )
    
        $SPFRecord = Get-DNSRecordSPF $Domain2 -ErrorAction SilentlyContinue
        $SPFRecord = $SPFRecord.Value -Join ""
        $SPFRecord = ($SPFRecord -Replace ("v=spf1 ",""))
  
        RETURN $SPFRecord.Split(" ")
    }

    $Results = @()
    $LookupFQDNs = @()
    $LookupCount = 0
    $Length = 0
    $TXTRecord = Get-DNSRecordSPF $Domain -ErrorAction SilentlyContinue

    $SPFRecord = $TXTRecord.Value -Join ""
    $Length = $SPFRecord.Length
           
    $Split = Format-SPFRecord $Domain
        
    FOREACH ($Item in $Split) {
        IF ($Item -eq "a" -or $Item -eq "+a" -or $Item -like "a:*") { $LookupCount++; $LookupFQDNs += $Item }
        ELSEIF ($Item -eq "mx" -or $Item -eq "+mx" -or $Item -like "mx:*") { $LookupCount++; $LookupFQDNs += $Item }
        ELSEIF ($Item -like "*include:*" -or $Item -like "*%{*") {
                $LookupCount++
                $LookupFQDNs += $Item
                $Split2 = Format-SPFRecord ($Item -replace ("include:",""))
                FOREACH ($Item2 in $Split2) {
                    IF ($Item2 -like "*include:*" -or $Item2 -like "*%{*") {
                        $LookupCount++
                        $LookupFQDNs += $Item2
                        $Split3 = Format-SPFRecord ($Item2 -replace ("include:",""))
                        FOREACH ($Item3 in $Split3) {
                            IF ($Item3 -like "*include:*" -or $Item3 -like "*%{*") {
                                $LookupCount++
                                $LookupFQDNs += $Item3
                                $Split4 = Format-SPFRecord ($Item3 -replace ("include:",""))
                                FOREACH ($Item4 in $Split4) {
                                    IF ($Item4 -like "*include:*" -or $Item4 -like "*%{*") {
                                        $LookupCount++
                                        $LookupFQDNs += $Item4
                                        $Split5 = Format-SPFRecord ($Item4 -replace ("include:",""))
                                        FOREACH ($Item5 in $Split5) {
                                            IF ($Item5 -like "*include:*" -or $Item5 -like "*%{*") {
                                                $LookupCount++
                                                $LookupFQDNs += $Item5
                                                $Split6 = Format-SPFRecord ($Item5 -replace ("include:",""))
                                                FOREACH ($Item6 in $Split6) {
                                                    IF ($Item6 -like "*include:*" -or $Item6 -like "*%{*") {
                                                        $LookupCount++
                                                        $LookupFQDNs += $Item6
                                                    }
                                                }   
                                            }
                                        }   
                                    }
                                }   
                            }
                        }   
                    }
                }   
            }
    }

    ### Syntax Checker
    ### Test Line
    #$SPFRecord = "v=spf1 ip6:1234:2234:2223::0000 a include:horses.net include:f02934hrjio2qjr39023jr203rk.net ?all"

    $SPFSyntaxErrors = @()
    IF ($SPFRecord -match " ") { $SPFSyntaxErrors += "Error: SPF has Unnecessary Spaces" }
    $SyntaxSplit = $SPFRecord.Split(" ")
    $SPFSyntaxVersionCount = 0
    $SPFSyntaxInvalidIP4 = $False
    $SPFSyntaxInvalidIP6 = $False
    $SPFRecordInvalidFQDNCount = 0
    $SPFFQDNDoesntResolveCount = 0
    $SPFValidPolicyCount = 0
    $SPFUnknownInvalidEntryFound = 0
    $RedirectCount = 0
        

    FOREACH ($Item in $SyntaxSplit) {
            IF ($null -eq $Item) { continue } 
            IF ("" -eq $Item) { continue }
            IF ($Item -eq "mx") { continue } 
            IF ($Item -eq "a") { continue } 
            IF ($Item.Substring($Item.Length-3,1) -eq "/") { $Item = $Item.Substring(0,$Item.Length-3) }
            IF ($Item.Substring($Item.Length-2,1) -eq "/") { $Item = $Item.Substring(0,$Item.Length-2) }
            IF ($Item -eq "v=spf1") { $SPFSyntaxVersionCount++; continue }
            IF ($Item -like "*ip4:*") { TRY { $Test = [System.Net.IPAddress]($Item -replace ("ip4:","")); continue } CATCH { $SPFSyntaxInvalidIP4 = $True; $SPFSyntaxErrors+= "Invalid IPv4 Entry: $Item"; continue } }
            IF ($Item -match "ip6:") { TRY { $Test = [System.Net.IPAddress]($Item -replace ("ip6:","")); continue } CATCH { $SPFSyntaxInvalidIP6 = $True; $SPFSyntaxErrors+= "Invalid IPv6 Entry: $Item"; continue } } 
            IF ($Item -match "include:" -or $Item -match "exists:" -or $Item -match "mx:" -or $Item -match "a:") { 
                IF ($Item -match "{" -and $Item -match "}") { continue }                 
                TRY { 
                    $Test = $null
                    $Test = Resolve-DnsName $Item.Split(":")[1] -ErrorAction SilentlyContinue
                    IF ($null -eq $Test) { $SPFFQDNDoesntResolveCount++; $SPFSyntaxErrors+= "FQDN Entry Does Not Resolve: $Item"; }
                } 
                CATCH { $SPFFQDNDoesntResolveCount++; $SPFSyntaxErrors+= "FQDN Entry Does Not Resolve: $Item"; }
                continue 
            }
            IF ($Item -match "all") { IF ( $Item -match "~" -or $Item -match "-" -or $Item -match "\+" -or $Item -match "\?") { $SPFValidPolicyCount++; continue } }
            IF ($Item -match "redirect=") { $RedirectCount++; continue }
            $SPFUnknownInvalidEntryFound++
            $SPFSyntaxErrors+= "Unknown Entry: $Item"
        }

    IF ($SPFSyntaxVersionCount -eq 0) { $SPFSyntaxErrors+= "Error: Missing Valid SPF Version" }
    IF ($SPFSyntaxVersionCount -gt 1) { $SPFSyntaxErrors+= "Error: Multiple Version Entries" }
    IF ($SPFValidPolicyCount -eq 0 -and $RedirectCount -eq 0) { $SPFSyntaxErrors+= "Error: Missing Valid SPF Policy" }
    IF ($SPFValidPolicyCount -gt 1) { $SPFSyntaxErrors+= "Error: Multiple Policy Entries" }



    $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Type = $TXTRecord.Type
            Name = $TXTRecord.Name
            LookupCount = $LookupCount
            LookupFQDNs = $LookupFQDNs
            Length = $Length
            Value = $TXTRecord.Value -Join ""
            SyntaxErrors = $SPFSyntaxErrors
        }


    RETURN $Results | Select Type, Name, LookupCount, LookupFQDNs, Length, Value, SyntaxErrors
}
    FUNCTION Get-DNSEMailInfo {

    param (
        [Parameter(Mandatory)]
        [string[]]$Domain,
        [switch]$MainProgressBarOff = $False,
        [switch]$SkipBlacklistCheck = $False
    )

    $Results = @()

    $DomainCount = 0  
    $DomainCountTotal = $Domain.Count

    FOREACH ($Item in $Domain) {

        IF ($MainProgressBarOff -eq $False) { 
            $DomainActivityMessage = "Getting E-Mail DNS Info"
            $DomainStatusMessage = "Checking $($DomainCount+1) of $DomainCountTotal - $Item"
            $DomainProgressPercent = [math]::round(($DomainCount / $DomainCountTotal * 100),0)
            Write-Progress -ID 64251342 -Activity $DomainActivityMessage -Status $DomainStatusMessage -PercentComplete $DomainProgressPercent
        }
        $DomainCount++

        Write-Progress -ID 61201542 -Activity "Collecting Data" -Status "Step 1 of 7 - Getting DNS Records" -PercentComplete 0
        $AllRecords = Get-DNSRecordAll $Item

        Write-Progress -ID 61201542 -Activity "Collecting Data" -Status "Step 2 of 7 - Counting MX Records" -PercentComplete 15
        $HasMX = $False
        $HasSPF = $False
        $HasDMARC = $False
        $HasDKIM = $False

        ### Confirm if Each Record Type Exists
        FOREACH ($Record in $AllRecords) {
            IF ($Record.Purpose -eq "MX") { $HasMX = $True }
            IF ($Record.Purpose -eq "SPF") { $HasSPF = $True }
            IF ($Record.Purpose -eq "DMARC") { $HasDMARC = $True }
            IF ($Record.Purpose -eq "DKIM") { $HasDKIM = $True }
        }

        ### Confirm Count of Records
        IF ( (($AllRecords) | Where-Object { $_.Purpose -eq "MX" }).Count -eq $Null ) { $MXRecordCount = 1 } 
        ELSE { $MXRecordCount = (($AllRecords) | Where-Object { $_.Purpose -eq "MX" }).Count } 

        IF ( (($AllRecords) | Where-Object { $_.Purpose -eq "SPF" }).Count -eq $Null ) { $SPFRecordCount = 1 } 
        ELSE { $SPFRecordCount = (($AllRecords) | Where-Object { $_.Purpose -eq "SPF" }).Count } 

        IF ( (($AllRecords) | Where-Object { $_.Purpose -eq "DMARC" }).Count -eq $Null ) { $DMARCRecordCount = 1 } 
        ELSE { $DMARCRecordCount = (($AllRecords) | Where-Object { $_.Purpose -eq "DMARC" }).Count }

        IF ( (($AllRecords) | Where-Object { $_.Purpose -eq "DKIM" }).Count -eq $Null ) { $DKIMRecordCount = 1 } 
        ELSE { $DKIMRecordCount = (($AllRecords) | Where-Object { $_.Purpose -eq "DKIM" }).Count }

        Write-Progress -ID 61201542 -Activity "Collecting Data" -Status "Step 3 of 7 - Checking for Duplicate Records" -PercentComplete 30
        ### Check for Duplicates Records
        $MXRecordDuplicateCount = ((($AllRecords) | Where-Object { $_.Purpose -eq "MX" }) | Group-Object Value | Where-Object { $_.Count -gt 1 }).Count    
        $DKIMRecordDuplicateCount = ((($AllRecords) | Where-Object { $_.Purpose -eq "DKIM" }) | Group-Object Value | Where-Object { $_.Count -gt 1 }).Count

        Write-Progress -ID 61201542 -Activity "Collecting Data" -Status "Step 4 of 7 - Reviewing SPF Record" -PercentComplete 45
        ### SPF Parsing
        $SPFCheck = Debug-DNSRecordSPF $Item
        $SPFSplit = ($SPFCheck.Value -replace ("v=spf1 ","")).Split(" ")
        $FailType = $SPFSplit[$SPFSplit.Length-1]
        $SPFSplit = $SPFSplit | Where-Object { $_ -like "*include:*" }

        ### SPF Fail Type
        $SPFFailString = ""
        IF ($FailType -match "~") { $SPFFailString = "Soft Fail"; $AlertString = "" }
        ELSEIF ($FailType -match "-") { $SPFFailString = "Fail"; $AlertString = "" }
        ELSEIF ($FailType -match "\+") { $SPFFailString = "Pass"; $AlertString = "Error: SPF Policy set to Pass" }
        ELSEIF ($FailType -match "\?") { $SPFFailString = "None"; $AlertString = "Error: SPF Policy set to None" }
        ELSEIF ($FailType -like "*redirect*") { $SPFFailString = "Redirected"; $AlertString = "" }
        ELSE { $FailType = ""; $SPFFailString = "Missing"; $AlertString = "Error: SPF Policy is Missing" }    

        Write-Progress -ID 61201542 -Activity "Collecting Data" -Status "Step 5 of 7 - Reviewing DMCAR Record" -PercentComplete 60
        ### DMARC Parsing
        $DMARCRecords = (($AllRecords) | Where-Object { $_.Purpose -eq "DMARC" })
        FOREACH ($DMARCRecord in $DMARCRecords) {
            $DMARCVersion = ((($DMARCRecord.Value -replace (";"," ")) -replace (" "," "))).Split(" ") | Where-Object { $_ -like "*v=*" }
            $DMARCPolicy = ((($DMARCRecord.Value -replace (";"," ")) -replace (" "," "))).Split(" ") | Where-Object { $_ -like "*p=*" }
            $DMARCRUA = ((($DMARCRecord.Value -replace(";"," ")) -replace (" "," "))).Split(" ") | Where-Object { $_ -like "*rua=*" }
        }

        ### DMARC Fail Type
        $DMARCFailString = ""
        IF ($DMARCPolicy -eq "p=none") { $DMARCFailString = "Monitoring"; $AlertString = "Warning: DMARC Enforcement Not Enabled" }
        ELSEIF ($DMARCPolicy -eq "p=quarantine") { $DMARCFailString = "Quarantine"; $AlertString = "" }
        ELSEIF ($DMARCPolicy -eq "p=reject") { $DMARCFailString = "Reject"; $AlertString = "" }
        ELSE { $DMARCPolicy = ""; $DMARCFailString = "Missing"; $AlertString = "Error: DMARC Policy is Missing" }

        Write-Progress -ID 61201542 -Activity "Collecting Data" -Status "Step 6 of 7 - Getting WhoIS Info" -PercentComplete 75
        $WhoISInfo = Get-WhoIS $Item

        Write-Progress -ID 61201542 -Activity "Collecting Data" -Status "Step 7 of 7 - Checking for Blacklist Entries" -PercentComplete 90
        ### Check for Blacklistings
        $Blacklist = $Null
        $BlacklistCount = 0
        IF ($SkipBlacklistCheck -eq $False) {
            $Blacklist = Get-EmailDomainBlacklist $Item
            $BlacklistCount = ($Blacklist.BlacklistedOn | select -Unique).Count
        }
        
        ### Join SPF Records
        FOREACH ($SPF in ($AllRecords | Where-Object { $_.Purpose -eq "SPF" })) {
            $SPF.Value = $SPF.Value -join ""
        }

        $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
            Domain = $Item
            Registrar = $WhoISInfo.Registrar 
            FirstRegistrationDate = $WhoISInfo.CreationDate
            HasMXRecord = $HasMX
            MXRecord = ($AllRecords | Where-Object { $_.Purpose -eq "MX" }).Value            
            MXRecordCount = $MXRecordCount
            DuplicateMXRecord = ($MXRecordDuplicateCount -ne 0)
            HasSPFRecord = $HasSPF
            SPFRecord = ($AllRecords | Where-Object { $_.Purpose -eq "SPF" }).Value   
            SPFRecordCount = $SPFRecordCount
            SPFLookupCount = $SPFCheck.LookupCount
            SPFLookupFQDNs = $SPFCheck.LookupFQDNs
            SPFPolicy = $SPFFailString
            SPFSyntaxErrors = $SPFCheck.SyntaxErrors
            HasDMARCRecord = $HasDMARC
            DMARCRecord = ($AllRecords | Where-Object { $_.Purpose -eq "DMARC" }).Value 
            DMARCRecordCount = $DMARCRecordCount
            DMARCPolicy = $DMARCFailString
            HasDKIMRecord = $HasDKIM
            DKIMRecord = ($AllRecords | Where-Object { $_.Purpose -eq "DKIM" }).Value 
            DKIMRecordCount = $DKIMRecordCount
            HasBlacklist = ($BlacklistCount -ne 0)
            BlacklistEntries = $Blacklist.BlacklistedOn
        }

    }

    RETURN $Results | Select Domain, Registrar, FirstRegistrationDate, HasMXRecord, MXRecord, MXRecordCount, DuplicateMXRecord, HasSPFRecord, SPFRecord, SPFRecordCount, SPFLookupCount, SPFLookupFQDNs, SPFPolicy, SPFSyntaxErrors, HasDMARCRecord, DMARCRecord, DMARCRecordCount, DMARCPolicy, HasDKIMRecord, DKIMRecord, DKIMRecordCount, HasBlacklist, BlacklistEntries
} 
    FUNCTION Get-EmailDomainBlacklist {

    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        #List of MX records to monitor if the parameter is not changed
        [string[]]$Domain
    )       
    
    #Blacklist Servers
    $BlacklistServers = @(
        'b.barracudacentral.org'
        'spam.rbl.msrbl.net'
        'zen.spamhaus.org'
        'bl.deadbeef.com'
        'bl.spamcannibal.org'
        'bl.spamcop.net'
        'blackholes.five-ten-sg.com'
        'blacklist.woody.ch'
        'bogons.cymru.com'
        'cbl.abuseat.org'
        'combined.abuse.ch'
        'combined.rbl.msrbl.net'
        'db.wpbl.info'
        'dnsbl-1.uceprotect.net'
        'dnsbl-2.uceprotect.net'
        'dnsbl-3.uceprotect.net'
        'dnsbl.cyberlogic.net'
        'dnsbl.inps.de'
        'dnsbl.sorbs.net'
        'drone.abuse.ch'
        'drone.abuse.ch'
        'duinv.aupads.org'
        'dul.dnsbl.sorbs.net'
        'dul.ru'
        'dyna.spamrats.com'
        'dynip.rothen.com'
        'http.dnsbl.sorbs.net'
        'images.rbl.msrbl.net'
        'ips.backscatterer.org'
        'ix.dnsbl.manitu.net'
        'korea.services.net'
        'misc.dnsbl.sorbs.net'
        'noptr.spamrats.com'
        'ohps.dnsbl.net.au'
        'omrs.dnsbl.net.au'
        'orvedb.aupads.org'
        'osps.dnsbl.net.au'
        'osrs.dnsbl.net.au'
        'owfs.dnsbl.net.au'
        'owps.dnsbl.net.au'
        'pbl.spamhaus.org'
        'phishing.rbl.msrbl.net'
        'probes.dnsbl.net.au'
        'proxy.bl.gweep.ca'
        'proxy.block.transip.nl'
        'psbl.surriel.com'
        'rbl.interserver.net'
        'rdts.dnsbl.net.au'
        'relays.bl.gweep.ca'
        'relays.bl.kundenserver.de'
        'relays.nether.net'
        'residential.block.transip.nl'
        'ricn.dnsbl.net.au'
        'rmst.dnsbl.net.au'
        'sbl.spamhaus.org'
        'short.rbl.jp'
        'smtp.dnsbl.sorbs.net'
        'socks.dnsbl.sorbs.net'
        'spam.abuse.ch'
        'spam.dnsbl.sorbs.net'
        'spam.spamrats.com'
        'spamrbl.imp.ch'
        'spamsources.fabel.dk'
        't3direct.dnsbl.net.au'
        'ubl.lashback.com'
        'ubl.unsubscore.com'
        'virbl.bit.nl'
        'virus.rbl.jp'
        'virus.rbl.msrbl.net'
        'web.dnsbl.sorbs.net'
        'wormrbl.imp.ch'
        'xbl.spamhaus.org'
        'zombie.dnsbl.sorbs.net'
    )

    #Initialize Variables
    $Results = @()
    $MXInfo = @() 
    $MXRecords = @()
    
    ### Collect MX Records
    FOREACH ($Name in $Domain) { $MXRecords += (Get-DNSRecordMX $Name).Value; $MXRecords += $Domain }
    $MXRecords = $MXRecords | select -Unique

    ### Collect IPs
    FOREACH ($MX in $MXRecords){
        $IPs = ((Resolve-DnsName $MX) | Where-Object { $_.Type -eq "A" }).IPAddress
        $IPs = $IPs | Select -Unique
        FOREACH ($IP in $IPs) {
            IF ($MXInfo.IP -contains $IP) { continue }
            $MXInfo += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                MXRecord = $MX
                IP = $IP
            }
        }
    }

    $MXCount = 0  
    $MXCountTotal = $MXInfo.Count
    
    FOREACH ($Info in $MXInfo) {

        $MXActivityMessage = "Checking for Blacklist Entries..."
        $MXStatusMessage = "Checking $($MXCount+1) of $MXCountTotal - $($Info.MXRecord) ($($Info.IP)) "
        $MXProgressPercent = [math]::round(($MXCount / $MXCountTotal * 100),0)
        Write-Progress -ID 34572342 -Activity $MXActivityMessage -Status $MXStatusMessage -PercentComplete $MXProgressPercent
        $MXCount++

        ### Check for Blacklisting
        $JobResults = $BlacklistServers | Start-RSJob {
    
            $Info = $Using:Info
            $ReversedIP = ($Info.IP -split '\.')[3..0] -join '.'
            $FQDN = "$reversedIP.$_"
    
            $BlacklistResults = New-Object PSObject
 
            TRY {
                Write-Verbose "Checking $IP against $server"
                $null = [System.Net.Dns]::GetHostEntry($FQDN)        
                Add-Member -InputObject $BlacklistResults -MemberType NoteProperty -Name IP -Value $Info.IP
                Add-Member -InputObject $BlacklistResults -MemberType NoteProperty -Name "BlacklistedOn" -Value $_
                Add-Member -InputObject $BlacklistResults -MemberType NoteProperty -Name "MXRecord" -Value $Info.MXRecord
            }
            CATCH { }
    
            RETURN $BlacklistResults

        } | Wait-RSJob | Receive-RSJob

        $Results = $JobResults | Where-Object { $_.IP -ne $null }
    }

    Write-Progress -ID 34572342 -Activity $MXActivityMessage -PercentComplete 100 -Completed

    RETURN $Results
}

    $Results = @()
    
    ### Progress Bar Stuff
    $DomainCount = 0  
    $DomainCountTotal = $Domain.Count


    FOREACH ($Item in $Domain) {

        $ErrorCount = 0

        ### Progress Bar Stuff
        $DomainActivityMessage = "Checking E-mail Health"
        $DomainStatusMessage = "Checking $($DomainCount+1) of $DomainCountTotal - $Item"
        $DomainProgressPercent = [math]::round(($DomainCount / $DomainCountTotal * 100),0)
        Write-Progress -ID 12551342 -Activity $DomainActivityMessage -Status $DomainStatusMessage -PercentComplete $DomainProgressPercent
        $DomainCount++


        IF ($CheckBlacklist) { $DNSInfo = Get-DNSEMailInfo $Item -MainProgressBarOff -CheckBlacklist }
        ELSE { $DNSInfo = Get-DNSEMailInfo $Item -MainProgressBarOff }

        $RegistrationTimeSpan = (Get-Date) - $DNSInfo.FirstRegistrationDate
        
        
        ### First Registration Date
        IF ($DNSInfo.FirstRegistrationDate -ne 0) {
            IF ($RegistrationTimeSpan.TotalDays -lt 180) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "Registration"
                    ItemCheck = "Recently Registered" 
                    ItemResults = $True
                    ItemDetails = $DNSInfo.FirstRegistrationDate
                    Alert = "Error: Domain Registered Less Than 6 Months Ago"
                }
                $ErrorCount++
            }
            ELSEIF ($RegistrationTimeSpan.TotalDays -lt 365) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "Registration"
                    ItemCheck = "Recently Registered" 
                    ItemResults = $True
                    ItemDetails = $DNSInfo.FirstRegistrationDate
                    Alert = "Warning: Domain Registered Less Than a Year Ago"
                }
                $ErrorCount++
            }
            ELSEIF ($RegistrationTimeSpan.TotalDays -ge 365) { 
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "Registration"
                    ItemCheck = "Recently Registered"
                    ItemResults = $False
                    ItemDetails = $DNSInfo.FirstRegistrationDate
                    Alert = ""
                }
            }
            ELSE { 
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "Registration"
                    ItemCheck = "Recently Registered"
                    ItemResults = ""
                    ItemDetails = ""
                    Alert = "Error: Unknown Registration Date"
                }
                $ErrorCount++
            }
        }

        ### MX Record
        IF ($DNSInfo.MXRecordCount -ne 0) {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Domain = $Item
                Item = "MX"
                ItemCheck = "MX Record Exists" 
                ItemResults = $True
                ItemDetails = $DNSInfo.MXRecord
                Alert = ""
            }

            IF ($DNSInfo.DuplicateMXRecord -eq $False) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "MX"
                    ItemCheck = "Duplicate MX Records" 
                    ItemResults = $DNSInfo.DuplicateMXRecord
                    ItemDetails = $DNSInfo.MXRecord
                    Alert = ""
                }
            }
            ELSE {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "MX"
                    ItemCheck = "Duplicate MX Records" 
                    ItemResults = $DNSInfo.DuplicateMXRecord
                    ItemDetails = $DNSInfo.MXRecord
                    Alert = "Warning: Duplicate MX Record Found"
                }
                $ErrorCount++    
            }
        } 
        ELSE {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Domain = $Item
                Item = "MX"
                ItemCheck = "MX Record Exists" 
                ItemResults = $False
                ItemDetails = $DNSInfo.MXRecord
                Alert = "Error: Missing MX Record"
            }
            $ErrorCount++
        }
        
        ### SPF Record
        IF ($DNSInfo.SPFRecordCount -eq 0) {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Domain = $Item
                Item = "SPF"
                ItemCheck = "SPF Record Exists" 
                ItemResults = $False
                ItemDetails = $DNSInfo.SPFRecord
                Alert = "Error: Missing SPF Record"
            }
            $ErrorCount++
        }
        ELSEIF ($DNSInfo.SPFRecordCount -eq 1) {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Domain = $Item
                Item = "SPF"
                ItemCheck = "SPF Record Exists" 
                ItemResults = $True
                ItemDetails = $DNSInfo.SPFRecord
                Alert = ""
            }
        }
        ELSE {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Domain = $Item
                Item = "SPF"
                ItemCheck = "SPF Record Exists" 
                ItemResults = $True
                ItemDetails = $DNSInfo.SPFRecord
                Alert = "Error: Multiple SPF Records Found"
            }
            $ErrorCount++
        }

        IF ($DNSInfo.SPFRecordCount -ne 0) {
            
            ### SPF Policy Info
            IF ($DNSInfo.SPFPolicy -eq "Fail") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "SPF"
                    ItemCheck = "SPF Policy" 
                    ItemResults = "Fail"
                    ItemDetails = "-All"
                    Alert = ""
                }
            }
            ELSEIF ($DNSInfo.SPFPolicy -eq "Soft Fail") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "SPF"
                    ItemCheck = "SPF Policy" 
                    ItemResults = "Soft Fail"
                    ItemDetails = "~All"
                    Alert = ""
                }
            }
            ELSEIF ($DNSInfo.SPFPolicy -eq "Pass") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "SPF"
                    ItemCheck = "SPF Policy" 
                    ItemResults = "Soft Fail"
                    ItemDetails = "+All"
                    Alert = "Error: SPF Policy Set to Pass"
                }
                $ErrorCount++
            }
            ELSEIF ($DNSInfo.SPFPolicy -eq "None") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "SPF"
                    ItemCheck = "SPF Policy" 
                    ItemResults = "Soft Fail"
                    ItemDetails = "?All"
                    Alert = "Error: No SPF Policy Set"
                }
                $ErrorCount++
            }
            ELSEIF ($DNSInfo.SPFPolicy -eq "Redirected") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "SPF"
                    ItemCheck = "SPF Policy" 
                    ItemResults = "Redirect"
                    ItemDetails = ((($DNSInfo.SPFRecord) -replace (" "," ")).Split(" ") | Where-Object { $_ -like "*redirect*"})
                    Alert = ""
                }
            }
            ELSE {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "SPF"
                    ItemCheck = "SPF Policy" 
                    ItemResults = "Not Set"
                    ItemDetails = ""
                    Alert = "Error: SPF Policy Not Set"
                }
                $ErrorCount++
            }

            ### SPF Lookup Info
            IF ($DNSInfo.SPFLookupCount -le 8 -and $DNSInfo.SPFPolicy -ne "Redirected") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "SPF"
                    ItemCheck = "SPF Lookup Count" 
                    ItemResults = $DNSInfo.SPFLookupCount
                    ItemDetails = $DNSInfo.SPFLookupFQDNs
                    Alert = ""
                }
            }
            ELSEIF ($DNSInfo.SPFLookupCount -le 10 -and $DNSInfo.SPFPolicy -ne "Redirected") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "SPF"
                    ItemCheck = "SPF Lookup Count" 
                    ItemResults = $DNSInfo.SPFLookupCount
                    ItemDetails = $DNSInfo.SPFLookupFQDNs
                    Alert = "Warning: High SPF Lookup Count"
                }
                $ErrorCount++
            }
            ELSEIF ($DNSInfo.SPFPolicy -ne "Redirected") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "SPF"
                    ItemCheck = "SPF Lookup Count"
                    ItemResults = $DNSInfo.SPFLookupCount
                    ItemDetails = $DNSInfo.SPFLookupFQDNs
                    Alert = "Error: Too Many SPF Lookups"
                }
                $ErrorCount++
            }

            ### SPF Syntax Errors
            IF ($DNSInfo.SPFSyntaxErrors.Count -gt 0) {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "SPF"
                    ItemCheck = "SPF Syntax" 
                    ItemResults = "$($DNSInfo.SPFSyntaxErrors.Count.ToString()) Errors"
                    ItemDetails = $DNSInfo.SPFSyntaxErrors
                    Alert = "Error: SPF Has Syntax Errors"
                }
                $ErrorCount++
            }
            ELSE {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "SPF"
                    ItemCheck = "SPF Syntax" 
                    ItemResults = "No Issues Found"
                    ItemDetails = $DNSInfo.SPFSyntaxErrors
                    Alert = ""
                }
            }
        }

        ### DMARC Record Exists
        IF ($DNSInfo.DMARCRecordCount -eq 0) {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Domain = $Item
                Item = "DMARC"
                ItemCheck = "DMARC Record Exists" 
                ItemResults = $False
                ItemDetails = $DNSInfo.DMARCRecord
                Alert = "Error: Missing DMARC Record"
            }
            $ErrorCount++
        }
        ELSEIF ($DNSInfo.DMARCRecordCount -eq 1) {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Domain = $Item
                Item = "DMARC"
                ItemCheck = "DMARC Record Exists" 
                ItemResults = $True
                ItemDetails = $DNSInfo.DMARCRecord
                Alert = ""
            }
        }
        ELSE {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Domain = $Item
                Item = "DMARC"
                ItemCheck = "DMARC Record Exists" 
                ItemResults = $True
                ItemDetails = $DNSInfo.DMARCRecord
                Alert = "Error: Multiple DMARC Records Found"
            }
            $ErrorCount++
        }


        ### DMARC Policy
        IF ($DNSInfo.DMARCRecordCount -ne 0) {
            IF ($DNSInfo.DMARCPolicy -eq "Monitoring") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "DMARC"
                    ItemCheck = "DMARC Policy" 
                    ItemResults = "Monitoring"
                    ItemDetails = "p=none"
                    Alert = "Warning: DMARC Policy Set to Monitoring"
                }
                $ErrorCount++
            }
            ELSEIF ($DNSInfo.DMARCPolicy -eq "Quarantine") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "DMARC"
                    ItemCheck = "DMARC Policy" 
                    ItemResults = "Quarantine"
                    ItemDetails = "p=quarantine"
                    Alert = ""
                }
            }
            ELSEIF ($DNSInfo.DMARCPolicy -eq "Reject") {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "DMARC"
                    ItemCheck = "DMARC Policy" 
                    ItemResults = "Reject"
                    ItemDetails = "p=reject"
                    Alert = ""
                }
            }
            ELSE {
                $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                    Domain = $Item
                    Item = "DMARC"
                    ItemCheck = "DMARC Policy" 
                    ItemResults = "Unknown"
                    ItemDetails = ""
                    Alert = "Error: Unknown DMARC Policy"
                }
                $ErrorCount++
            }
        }


        ### DKIM Record Exists
        IF ($DNSInfo.DKIMRecordCount -eq 0) {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Domain = $Item
                Item = "DKIM"
                ItemCheck = "DKIM Records Exists" 
                ItemResults = $False
                ItemDetails = ""
                Alert = "Warning: Missing DKIM Record"
            }
            $ErrorCount++
        }
        ELSE {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Domain = $Item
                Item = "DKIM"
                ItemCheck = "DKIM Records Exists" 
                ItemResults = $True
                ItemDetails = $DNSInfo.DKIMRecord
                Alert = ""
            }
        }

        ### Blacklist
        IF ($DNSInfo.HasBlacklist -eq $False) {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Domain = $Item
                Item = "Blacklist"
                ItemCheck = "Blacklist Entry Exists" 
                ItemResults = $False
                ItemDetails = ""
                Alert = ""
            }
        }
        ELSEIF ($DNSInfo.BlacklistEntries.Count -gt 4) {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Domain = $Item
                Item = "Blacklist"
                ItemCheck = "Blacklist Entry Exists" 
                ItemResults = $True
                ItemDetails = $DNSInfo.BlacklistEntries
                Alert = "Error: Several Blacklist Entries Found"
            }
            $ErrorCount++
        }
        ELSE {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Domain = $Item
                Item = "Blacklist"
                ItemCheck = "Blacklist Entry Exists" 
                ItemResults = $True
                ItemDetails = $DNSInfo.BlacklistEntries
                Alert = "Warning: Blacklist Entries Found"
            }
            $ErrorCount++
        }

        IF ($ErrorCount -eq 0 -and $IssuesOnly -eq $True) {
            $Results += New-Object PSObject -WarningAction SilentlyContinue -Property @{
                Domain = $Item
                Item = "Health Check"
                ItemCheck = "Issues" 
                ItemResults = $False
                ItemDetails = "No Issues Found"
                Alert = ""
            }
        }
    }

    IF ($IssuesOnly -eq $True) {
        $Results = $Results | Where-Object { ($_.Alert -ne "" -and $_.Alert -ne $null) -or $_.ItemDetails -eq "No Issues Found" } 
    }

    RETURN $Results | Select Domain, Item, ItemCheck, ItemResults, Alert, ItemDetails | FT -GroupBy Domain | Out-String -Stream | ForEach-Object {
    $OutA = IF ($_ -match 'Warning') { @{ 'ForegroundColor' = 'Yellow' } } 
            ELSEIF ($_ -match 'Category:') { @{ 'ForegroundColor' = 'White' } } 
            ELSEIF ($_ -like '*----*') { @{ 'ForegroundColor' = 'White' } } 
            ELSEIF ($_ -match 'AlertLevel') { @{ 'ForegroundColor' = 'White' } } 
            ELSEIF ($_ -match 'Error') { @{ 'ForegroundColor' = 'Red' } } 
            ELSEIF ($_ -match 'Critical') { @{ 'ForegroundColor' = 'Red' } } 
            ELSE { @{ 'ForegroundColor' = 'White' } }
    Write-Host @OutA $_
    }   
}