Icewolf.EXO.SpamAnalyze.psm1

##############################################################################
# Invoke-SpamAnalyze.ps1
# Get SPAM Detail Info for Specific MessageTraceID in MessageTrace
# V2.0.0 04.05.2021 - Andres Bohren / Initial Version
# V2.0.1 07.05.2021 - Andres Bohren / Bugfixes
##############################################################################
#Requires -Modules ExchangeOnlineManagement

Function Invoke-SpamAnalyze
{

<#
.SYNOPSIS
         
.DESCRIPTION
    Get SPAM Detail Info for Specific MessageTraceID in MessageTrace
 
.PARAMETER Recipientaddress
    The Emailaddress of the Recipient
 
.PARAMETER SenderAddress
    The Emailadress of the Sender
 
    .EXAMPLE
.\SpamAnalyze.ps1 -SenderAddress SenderAddress@domain.tld -RecipientAddress RecipientAddress@domain.tld
 
.LINK
#>


Param(
    [parameter(Mandatory=$false)][String]$RecipientAddress = $null,
    [parameter(Mandatory=$false)][String]$SenderAddress = $null
    )
    
Begin {
    ##############################################################################
    # Connect to Exchange Online
    ##############################################################################
    Function Connect-EXO {
            
        If ($Null -eq (Get-PsSession | Where-Object {$_.ComputerName -eq "outlook.office365.com"})) 
        {
            Write-Host "Connect to Exchange Online..." -f Gray
            Connect-ExchangeOnline -ShowBanner:$false

            If ($Null -eq (Get-PsSession | Where-Object {$_.ComputerName -like "*compliance.protection.outlook.com"}))
            {
                Write-Host "Connect to Security and Compliance..." -f Gray
                Connect-IPPSSession  -WarningAction Silentlycontinue    
            } else {
                Write-Host "Connection to Security and Compliance already exists" -ForegroundColor Green
            }

        }
        Else {
            Write-Host "Connection to Exchange Online already exists" -ForegroundColor Green

            If ($Null -eq (Get-PsSession | Where-Object {$_.ComputerName -like "*compliance.protection.outlook.com"}))
            {
                Write-Host "Connect to Security and Compliance..." -f Gray
                Connect-IPPSSession  -WarningAction Silentlycontinue    
            } else {
                Write-Host "Connection to Security and Compliance already exists" -ForegroundColor Green
            }

        }
    }

    ##############################################################################
    # Disconnect from Exchange Online
    ##############################################################################
    Function Disconnect-EXO 
    {
                Write-Host "Disconnect from Exchange Online" -f Gray
                #fWrite-Log -fLogtext "Disconnect from Exchange Online"
                Get-PSSession | Where-Object {($_.ComputerName -eq "outlook.office365.com") -AND ($_.ConfigurationName -eq "Microsoft.Exchange")} | Remove-PSSession
                Get-PSSession | Where-Object {($_.ComputerName -like "compliance.protection.outlook.com") -AND ($_.ConfigurationName -eq "Microsoft.Exchange")} | Remove-PSSession
                
    }
    

    ##############################################################################
    # Check MessageTraceDetail
    ##############################################################################
    Function Get-SPAMinfo {
        Param(
            [parameter(Mandatory=$false)][String]$RecipientAddress,
            [parameter(Mandatory=$false)][String]$SenderAddress,
            [parameter(Mandatory=$true)][String]$MessageTraceId
            )
        
        $Start = (Get-Date).AddDays(-10) 
        $End = (Get-Date)

        Write-Host "Message events:" -ForegroundColor Magenta
        $MTDetail = Get-MessageTraceDetail -MessageTraceId $MessageTraceId -RecipientAddress $RecipientAddress -SenderAddress $SenderAddress -StartDate $Start -EndDate $End | Sort-Object Date

        $MTEventFail = $MTDetail | Where-Object {$_.event -eq "Failed"}
        If ($Null -ne $MTEventFail) {
            Write-Host "Failed-Event: " -ForegroundColor Magenta
            Write-Host (" Action: " +$MTEventFail.action )
            Write-Host
        }        
        $MTEventMal = $MTDetail | Where-Object {$_.event -eq "Malware"}
        If ($Null -ne $MTEventMal) {
            Write-Host "Malware-Event: " -ForegroundColor Magenta
            Write-Host (" Action: " +$MTEventMal.action )
            Write-Host
        }
        $MTEventSPM = $MTDetail | Where-Object {$_.event -eq "Spam"} | Select-Object -uniq
        # SPAM Detail
        If ($Null -ne $MTEventSPM) {
            Write-Host "SPAM-Event: " -ForegroundColor Magenta
            Write-Host (" Action: " +$MTEventSPM.action )
            Write-Host
            Write-Host "SPAM-Event Details:" -ForegroundColor Magenta
            Write-Host "Anti-spam message headers: https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/anti-spam-message-headers" -f Cyan
            Write-Host "Spam confidence levels: https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/spam-confidence-levels" -f Cyan
            [xml]$xmlS = $MTEventSPM.Data
            $RcptCount  = ($xmlS.root.MEP | Where-Object {$_.Name -eq "RcptCount"})
            $DI         = ($xmlS.root.MEP | Where-Object {$_.Name -eq "DI"})
            $SCL        = ($xmlS.root.MEP | Where-Object {$_.Name -eq "SCL"})
            $Score        = ($xmlS.root.MEP | Where-Object {$_.Name -eq "Score"})
            $SFV        = ($xmlS.root.MEP | Where-Object {$_.Name -eq "SFV"})
            $ClientIP   = ($xmlS.root.MEP | Where-Object {$_.Name -eq "CIP"})
            $Country    = ($xmlS.root.MEP | Where-Object {$_.Name -eq "Ctry"})
            $HeloString = ($xmlS.root.MEP | Where-Object {$_.Name -eq "H"})
            $ReturnPath = ($xmlS.root.MEP | Where-Object {$_.Name -eq "ReturnPath"})
            $Language   = ($xmlS.root.MEP | Where-Object {$_.Name -eq "Language"})
            Write-Host (" RecipientCount: " +$RcptCount.Integer)
            switch ($DI.String) {
                "SB" { $DI = "(SB) The sender of the message was blocked" }
                "SQ" { $DI = "(SQ) The message was quarantined" }
                "SD" { $DI = "(SD) The message was deleted" }
                "SJ" { $DI = "(SJ) The message was sent to the recipient's Junk Email folder" }
                "SN" { $DI = "(SN) The message was routed through the higher risk delivery pool" }
                "SO" { $DI = "(SO) The message was routed through the normal outbound delivery pool" }
            }
            Write-Host (" DI: " +$DI)
            # Color for SCL
            switch ($SCL.Integer) {
                -1 { $cSCL = "Green"; $Folder = "Inbox" }
                0 { $cSCL = "Green"; $Folder = "Inbox" }
                1 { $cSCL = "Green"; $Folder = "Inbox" }
                2 { $cSCL = "Green"; $Folder = "Inbox" }
                3 { $cSCL = "Green"; $Folder = "Inbox" }
                4 { $cSCL = "Green"; $Folder = "Inbox" }
                5 { $cSCL = "Yellow"; $Folder = "Junk-E-Mail" }
                6 { $cSCL = "Yellow"; $Folder = "Junk-E-Mail" }
                7 { $cSCL = "Red"; $Folder = "Quarantaine" }
                8 { $cSCL = "Red"; $Folder = "Quarantaine" }
                9 { $cSCL = "Red"; $Folder = "Quarantaine" }
            }
            Write-Host (" SpamConfidenceLevel (SCL): "+$SCL.Integer +" Deliver to: " +$Folder +")") -f $cSCL
            Write-Host (" SpamScoreLevel (Score): "+$Score.Integer )
            switch ($SFV.String) 
            {
                "BLK" { $SFV = "(BLK) Filtering was skipped and the message was blocked because it originated from a blocked sender" }
                "NSPM" { $SFV = "(NSPM) The message was marked as non-spam and was sent to the intended recipients" }
                "SFE" { $SFV = "(SFE) Filtering was skipped and the message was allowed because it was sent from an address in a user's Safe Senders list"}
                "SKA" { $SFV = "(SKA) The message skipped spam filtering and was delivered to the Inbox because the sender was in the allowed senders list or allowed domains list in an anti-spam policy"}
                "SKB" { $SFV = "(SKB) The message skipped spam filtering and was delivered to the Inbox because the sender was in the allowed senders list or allowed domains list in an anti-spam policy"}
                "SKI" { $SFV = "(SKI) Similar to SFV:SKN, the message skipped spam filtering for another reason (for example, an intra-organizational email within a tenant)"}
                "SKN" { $SFV = "(SKN) The message was marked as non-spam prior to being processed by spam filtering. For example, the message was marked as SCL -1 or Bypass spam filtering by a mail flow rule"}
                "SKQ" { $SFV = "(SKQ) The message was released from the quarantine and was sent to the intended recipients"}
                "SKS" { $SFV = "(SKS) The message was marked as spam prior to being processed by the content filter" }
                "SPM" { $SFV = "(SPM) The message was marked as spam by spam filtering" }
                            
            }
            Write-Host (" SpamFilterVerdikt (SFV): " +$SFV)
            Write-Host (" SenderClientIP (CIP): " +$ClientIP.String)
            Write-Host (" Country (CTRY): " +$Country.String)
            Write-Host (" HeloString (H): " +$HeloString.String)
            Write-Host (" ReturnPath: " +$ReturnPath.String)
            Write-Host (" Language: " +$Language.String)
            Write-Host    

        } Else {
            Write-Host "SPAM-Event: " -ForegroundColor Magenta
            Write-Host (" INFO: This mail contains no 'Spam' event ") -f Cyan
            Write-Host
        }
    }
}

Process {
    #Call Function to Connect to Exchange Online
    Connect-EXO

    #Set Start- and Enddate for Messagetrace
    $Start = ((Get-Date).AddDays(-10))
    $End = Get-Date
    
    #Messagetrace depending on Parameters
    If ($SenderAddress -ne $Null)
    {
        If ($RecipientAddress -ne $Null)
        {
            $MT = Get-MessageTrace -StartDate (get-date).AddDays(-10) -EndDate (get-date) -SenderAddress $SenderAddress -RecipientAddress $RecipientAddress 
        } else {
            $MT = Get-MessageTrace -StartDate (get-date).AddDays(-10) -EndDate (get-date) -SenderAddress $SenderAddress 
        }
    } else {
        #SenderAddress = $Null / RecipientAddress populated
        $MT = Get-MessageTrace -StartDate (get-date).AddDays(-10) -EndDate (get-date) -RecipientAddress $RecipientAddress  
    }
    $MT | Format-Table Received, SenderAddress, RecipientAddress, Subject, Status, MessageTraceID


    #Input MessageTraceID
    $readhost = Read-Host "MessageTraceID?"
    If ($readhost -eq "")
    {
        Write-Host "Not a MessageTraceID... Stopping Script"
    } else {
        Write-Host "DEBUG: Readhost: $readhost"
        Foreach ($Line in $MT)
        {
            If ($readhost -eq $Line.MessageTraceId)
            {
                
                #Write-Host "DEBUG: MessageTraceID: $($Line.MessageTraceId)"
                #Write-Host "DEBUG: Sender: $($Line.Senderaddress)"
                #Write-Host "DEBUG: Recipient: $($Line.RecipientAddress)"
                $MessageTraceId = $Line.MessageTraceId
                $MTSenderAddress = $Line.Senderaddress
                $MTRecipientAddress = $Line.RecipientAddress
                $MTStatus = $Line.Status
                $MTSubject = $Line.Subject
                $MTReceived = $Line.Received
                $MTMessageID = $Line.MessageID

                #Infos from Message Trace
                Write-Host
                Write-Host "E-Mail Detail:" -ForegroundColor Magenta
                Write-Host " Message ID: $MTMessageID"
                Write-Host " Received: $MTReceived"
                Write-Host " Sender: $MTSenderAddress"
                Write-Host " Recipient: $MTRecipientAddress"
                Write-Host " Subject: $MTSubject"
                Write-Host " Status: $MTStatus"
                Write-Host

                #Check Recipient
                $ExoRecipient = Get-Recipient -Identity $MTRecipientAddress
                #$ExoRecipient
                $RecipientTypeDetails = $ExoRecipient.RecipientTypeDetails

                Write-Host "Recipient Details" -ForegroundColor Magenta
                Write-Host " RecipientTypeDetails: $RecipientTypeDetails"
                Write-Host

                #JunkMailConfiguration of Mailbox
                $SenderDomain = ($SenderAddress.Split("@")[1])
                If ($RecipientTypeDetails -eq "UserMailbox")
                {
                    $JMC = Get-MailboxJunkEmailConfiguration -Identity $MTRecipientAddress
                    If ($NULL -ne $JMC)
                    {
                        Write-Host "Recipient JunkMailConfiguration" -ForegroundColor Magenta
                        Write-Host " TrustedListsOnly: $($JMC.TrustedListsOnly)"
                        Write-Host " ContactsTrusted: $($JMC.ContactsTrusted)"
                        Write-Host

                        Write-Host "Check if $MTSenderAddress exists in $MTRecipientAddress Trusted-/BlockedSenders list: " -ForegroundColor Magenta        
                        If ($JMC.TrustedSendersAndDomains -contains $MTSenderAddress)
                        {
                            Write-Host " USER Junk-E-Mail Config: Found in 'TrustedSendersAndDomains'" -f Green
                        } Else {
                            Write-Host " USER Junk-E-Mail Config: Not found in 'TrustedSendersAndDomains'" -f White
                        }
                        
                        If ($JMC.BlockedSendersAndDomains -contains $MTSenderAddress)
                        {
                            Write-Host " USER Junk-E-Mail Config: Found in 'BlockedSendersAndDomains'" -f Red
                        } Else {
                            Write-Host " USER Junk-E-Mail Config: Not found in 'BlockedSendersAndDomains'" -f White
                        }
                        Write-Host
                        
                        Write-Host "Check if $SenderDomain exists in $Recipient Trusted-/BlockedSenders list: " -ForegroundColor Magenta    
                        If ($JMC.TrustedSendersAndDomains -contains $SenderDomain)
                        {
                            Write-Host " USER Junk-E-Mail Config: Found in 'TrustedSendersAndDomains'" -f Green
                        } Else {
                            Write-Host " USER Junk-E-Mail Config: Not found in 'TrustedSendersAndDomains'" -f White
                        }
                        
                        If ($JMC.BlockedSendersAndDomains -contains $SenderDomain)
                        {
                            Write-Host " USER Junk-E-Mail Config: Found in 'BlockedSendersAndDomains'" -f Red
                        } Else {
                            Write-Host " USER Junk-E-Mail Config: Not found in 'BlockedSendersAndDomains'" -f White
                        }
                        Write-Host

                    }                    
                }

                   #GLOBALConfig
                Write-Host "Check if $MTSenderAddress found in GLOBAL Trusted-/BlockedSender list: " -ForegroundColor Magenta
                $GLOBALJunkConfig = Get-HostedContentFilterPolicy
                #Allowed Senders
                If ($GLOBALJunkConfig.AllowedSenders -match $MTSenderAddress)
                {
                    Write-Host " GLOBAL EAC SpamFilter: Found in 'AllowedSenders'" -f Green
                } Else {
                    Write-Host " GLOBAL EAC SpamFilter: Not found in 'AllowedSenders'" -f White
                }

                #Blocked Senders
                If ($GLOBALJunkConfig.BlockedSenders -match $MTSenderAddress)
                {
                    Write-Host " GLOBAL EAC SpamFilter: Found in 'BlockedSenders'" -f Red
                } Else {
                    Write-Host " GLOBAL EAC SpamFilter: Not found in 'BlockedSenders'" -f White
                }
                Write-Host

                Write-Host "Check if $SenderDomain found in GLOBAL Allowed-/BlockedSenderDomain list: " -ForegroundColor Magenta
                #Allowed Domains
                If ($GLOBALJunkConfig.AllowedSenderDomains.Domain -contains $SenderDomain)
                {
                    Write-Host " GLOBAL EAC SpamFilter: Found in 'AllowedSenderDomains'" -f Green
                } Else {
                    Write-Host " GLOBAL EAC SpamFilter: Not found in 'AllowedSenderDomains'" -f White
                }

                #Allowed Senders
                If ($GLOBALJunkConfig.BlockedSenderDomains.Domain -contains $SenderDomain)
                {
                    Write-Host " GLOBAL EAC SpamFilter: Found in 'BlockedSenderDomains'" -f Red
                } Else {
                    Write-Host " GLOBAL EAC SpamFilter: Not found in 'BlockedSenderDomains'" -f White
                }
                Write-Host


                Get-SPAMinfo -RecipientAddress $MTRecipientAddress -SenderAddress $MTSenderAddress -MessageTraceId $MessageTraceId

                #DNS Records
                Write-Host "DNS Records of $SenderDomain" -ForegroundColor Magenta
                #NS
                Write-Host "NS" -ForegroundColor Magenta
                $json = Invoke-RestMethod -URI "https://cloudflare-dns.com/dns-query?ct=application/dns-json&name=$SenderDomain&type=NS"
                [string]$NS = $json.Answer.data
                $NS

                #MX
                Write-Host "MX" -ForegroundColor Magenta
                $json = Invoke-RestMethod -URI "https://cloudflare-dns.com/dns-query?ct=application/dns-json&name=$SenderDomain&type=MX"
                [string]$MX = $json.Answer.data
                $MX

                #SPF
                Write-Host "SPF" -ForegroundColor Magenta
                $json = Invoke-RestMethod -URI "https://cloudflare-dns.com/dns-query?ct=application/dns-json&name=$SenderDomain&type=TXT"
                $TXT = $json.Answer.data
                $TXT = $TXT | where {$_ -match "v=spf1"}
                $SPF = $TXT
                $SPF


                #DKIM
                Write-Host "DKIM" -ForegroundColor Magenta
                $json = Invoke-RestMethod -URI "https://cloudflare-dns.com/dns-query?ct=application/dns-json&name=Selector1._domainkey.$SenderDomain&type=CNAME"
                $DKIM1 = $json.Answer.data
                $json = Invoke-RestMethod -URI "https://cloudflare-dns.com/dns-query?ct=application/dns-json&name=Selector2._domainkey.$SenderDomain&type=CNAME"
                $DKIM2 = $json.Answer.data
                [string]$DKIM = "$DKIM1 $DKIM2"
                $DKIM

                #DMARC
                Write-Host "DMARC" -ForegroundColor Magenta
                $json = Invoke-RestMethod -URI "https://cloudflare-dns.com/dns-query?ct=application/dns-json&name=_dmarc.$SenderDomain&type=TXT"
                $DMARC = $json.Answer.data
                $DMARC

            }
        }

    }
    break
    Get-SPAMinfo -RecipientAddress $RecipientAddress -SenderAddress $SenderAddress -MessageTraceId $MessageTraceId
}

End {
    #Disconnect from Exchange Online and
    #Disconnect-EXO
}
}