Get-MXReport.ps1

#Requires -Version 5.1
<#PSScriptInfo
 
.VERSION 1.4.1
 
.GUID e9aab4f9-ec6e-4594-a3b9-465d0af991eb
 
.AUTHOR June Castillote
 
.COMPANYNAME www.lazyexchanegadmin.com
 
.COPYRIGHT june.castillote@gmail.com
 
.TAGS MX DNS Report PowerShell Script Query
 
.LICENSEURI
 
.PROJECTURI https://github.com/junecastillote/Get-MXReport
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
.PRIVATEDATA
 
#>
 





<#
 
.DESCRIPTION
Query MX record and create reports which can also be sent by email
 
#>
 


param (
    [cmdletbinding()]

    # list of domains to query, accepts array.
    [Parameter(Mandatory=$true)]
    [string[]]
    $domains,

    #path to the output/Report directory (eg. c:\scripts\output)
    [Parameter(Mandatory=$true)]
    [string]
    $outputDirectory,

    # Parameter help description
    [Parameter()]
    [string]
    $nameServer,    

    #path to the log directory (eg. c:\scripts\logs)
    [Parameter()]
    [string]
    $logDirectory,

    #prefix string for the report (ex. COMPANY)
    [Parameter()]
    [string]
    $headerPrefix,
    
    #Switch to enable email report
    [Parameter()]
    [ValidateSet("ErrorOnly","Always")]
    [string]
    $sendEmail,

    #Sender Email Address
    [Parameter()]
    [string]
    $sender,

    #Recipient Email Addresses - separate with comma
    [Parameter()]
    [string[]]
    $recipients,

    #smtpServer
    [Parameter()]
    [string]
    $smtpServer,

    #smtpPort
    [Parameter()]
    [string]
    $smtpPort,

    #switch to indicate whether SMTP server requires authentication
    [Parameter()]
    [switch]
    $smtpServerRequiresAuthentication,

    #credential for SMTP server (if applicable)
    [Parameter()]
    [pscredential]
    $smtpCredential,

    #switch to indicate if SSL will be used for SMTP relay
    [Parameter()]
    [switch]
    $smtpSSL,
    
    # switch to attach CSV file
    [Parameter()]
    [switch]
    $attachCSVReport
)

#...................................
# Start FUNCTIONS
#...................................
Function Stop-TxnLogging
{
    $txnLog=""
    Do {
        try {
            Stop-Transcript | Out-Null
        } 
        catch [System.InvalidOperationException]{
            $txnLog="stopped"
        }
    } While ($txnLog -ne "stopped")
}

#Function to Start Transaction Logging
Function Start-TxnLogging 
{
    param 
    (
        [Parameter(Mandatory=$true,Position=0)]
        [string]$logDirectory
    )
    Stop-TxnLogging
    Start-Transcript $logDirectory -Append
}
#...................................
# End FUNCTIONS
#...................................

Stop-TxnLogging
Clear-Host
$scriptInfo = Test-ScriptFileInfo -Path $MyInvocation.MyCommand.Definition

#...................................
# Start PARAMETER CHECK
#...................................
$isAllGood = $true

if ($sendEmail)
{
    if (!$sender)
    {
        Write-Host (get-date -Format "dd-MMM-yyyy hh:mm:ss tt") ": ERROR: A valid sender email address is not specified." -ForegroundColor Yellow
        $isAllGood = $false
    }

    if (!$recipients)
    {
        Write-Host (get-date -Format "dd-MMM-yyyy hh:mm:ss tt") ": ERROR: No recipients specified." -ForegroundColor Yellow
        $isAllGood = $false
    }

    if (!$smtpServer )
    {
        Write-Host (get-date -Format "dd-MMM-yyyy hh:mm:ss tt") ": ERROR: No SMTP Server specified." -ForegroundColor Yellow
        $isAllGood = $false
    }

    if (!$smtpPort )
    {
        Write-Host (get-date -Format "dd-MMM-yyyy hh:mm:ss tt") ": ERROR: No SMTP Port specified." -ForegroundColor Yellow
        $isAllGood = $false
    }
    
    if ($smtpServerRequiresAuthentication)
    {
        if (!$smtpCredential)
        {
            Write-Host (get-date -Format "dd-MMM-yyyy hh:mm:ss tt") ": ERROR: SMTP Server requires authentication, but no credential was specified. Please specify using the -smtpCredential parameter." -ForegroundColor Yellow
            $isAllGood = $false
        }
    }
}

if ($isAllGood -eq $false)
{
    Write-Host (get-date -Format "dd-MMM-yyyy hh:mm:ss tt") ": ERROR: Exiting Script." -ForegroundColor Yellow
    EXIT
}
#...................................
# End PARAMETER CHECK
#...................................

#...................................
# Start PATHS
#...................................
#$today = Get-Date
#[string]$fileSuffix = '{0:dd-MMM-yyyy_hh-mm_tt}' -f $today
$logFile = $logDirectory +"\Log_$((get-date).tostring("yyyy_MM_dd")).log"
$outputCSVFile = $outputDirectory +"\MX_Report_$((get-date).tostring("yyyy_MM_dd")).csv"
$outputHTMLFile = $outputDirectory +"\MX_Report_$((get-date).tostring("yyyy_MM_dd")).html"

#Create folders if not found
if ($logDirectory)
{
    if (!(Test-Path $logDirectory)) 
    {
        New-Item -ItemType Directory -Path $logDirectory | Out-Null
        #start transcribing----------------------------------------------------------------------------------
        Start-TxnLogging $logFile
        #----------------------------------------------------------------------------------------------------
    }
    else
    {
        Start-TxnLogging $logFile
    }
}

if (!(Test-Path $outputDirectory))
{
    New-Item -ItemType Directory -Path $outputDirectory | Out-Null
}
#...................................
# End PATHS
#...................................

#...................................
# start SCRIPT
#...................................

$now = (Get-Date -Format ("MMM-dd-yyyy hh:mm tt")) + " " + (Get-TimeZone).ToString().Split(" ")[0]

#set the error flag to false as default
$errorFlag = $false

$css_string = @'
<style type="text/css">
#HeadingInfo
    {
        font-family:"Segoe UI";
        width:100%;
        border-collapse:collapse;
    }
#HeadingInfo td, #HeadingInfo th
    {
        font-size:0.8em;
        padding:3px 7px 2px 7px;
    }
#HeadingInfo th
    {
        font-size:2.0em;
        font-weight:normal;
        text-align:left;
        padding-top:5px;
        padding-bottom:4px;
        background-color:#604767;
        color:#fff;
    }
#SectionLabels
    {
        font-family:"Segoe UI";
        width:100%;
        border-collapse:collapse;
    }
#SectionLabels th.data
    {
        font-size:2.0em;
        text-align:left;
        padding-top:5px;
        padding-bottom:4px;
        background-color:#fff;
        color:#000;
    }
#data
    {
        font-family:"Segoe UI";
        width:100%;
        border-collapse:collapse;
    }
#data td, #data th
    {
        font-size:0.8em;
        border:1px solid #DDD;
        padding:3px 7px 2px 7px;
    }
#data th
    {
        font-size:0.8em;
        padding-top:5px;
        padding-bottom:4px;
        background-color:#00B388;
        color:#fff; text-align:left;
    }
#data td
    { font-size:0.8em;
        padding-top:5px;
        padding-bottom:4px;
        text-align:left;
    }
#data td.bad
    { font-size:0.8em;
        font-weight: bold;
        padding-top:5px;
        padding-bottom:4px;
        color:#f04953;
    }
#data td.good
    { font-size:0.8em;
        font-weight: bold;
        padding-top:5px;
        padding-bottom:4px;
        color:#01a982;
    }
 
.status {
    width: 10px;
    height: 10px;
    margin-right: 7px;
    margin-bottom: 0px;
    background-color: #CCC;
    background-position: center;
    opacity: 0.8;
    display: inline-block;
}
.green {
    background: #01a982;
}
.purple {
    background: #604767;
}
.orange {
    background: #ffd144;
}
.red {
    background: #f04953;
}
</style>
</head>
<body>
'@


$finalResult = @()
foreach ($domain in $domains) {
    $queryParams = @{
        name = $domain
        type = "MX"
    }
    if ($nameServer) {$queryParams += @{Server = $nameServer}}
    
    
    try 
    {
        $mxRecords = resolve-dnsname @queryParams -ErrorAction Stop | Where-Object {$_.QueryType -eq "MX"} | Sort-Object -Property Preference
        #$mxRecords = $allRecords | Where-Object {$_.QueryType -eq "MX"} | Sort-Object -Property Preference
        if ($mxRecords) {
            foreach ($mxRecord in $mxRecords) {
            
                $x = "" | Select-Object Name,NameExchange,Preference,IPAddresses,Status,Error
                $x.Name = $domain
                $x.NameExchange = $mxRecord.NameExchange
                $x.Preference = $mxRecord.Preference
                $queryParams = @{
                    name = $mxRecord.NameExchange
                }
                if ($nameServer) {$queryParams += @{Server = $nameServer}}
    
                $x.IPAddresses = ((resolve-dnsname @queryParams -ErrorAction SilentlyContinue).IPAddress | Where-Object {$_ -notmatch ":"}) -join ";"
                $x.Status = "Passed"
                #$x.Error = ""
                $finalResult += $x
            }
            Write-Host (get-date -Format "dd-MMM-yyyy hh:mm:ss tt") ": $($domain): OK" -ForegroundColor Green
        }
    }
    Catch 
    {
        $errorFlag = $true
        $x = "" | Select-Object Name,NameExchange,Preference,IPAddresses,Status,Error
        $x.Name = $domain
        $x.NameExchange = "Error"
        $x.Preference = "Error"
        $x.IPAddresses = "Error"
        $x.Status = "Failed"
        $x.Error = $_.Exception.Message
        $finalResult += $x
        Write-Host (get-date -Format "dd-MMM-yyyy hh:mm:ss tt") ": $($domain): NOT OK" -ForegroundColor Red
    }

    
}
$finalResult | Export-Csv -NoTypeInformation $outputCsvFile

#create the HTML report
#html title
if ($headerPrefix)
{
    $subject = "[$($headerPrefix)] MX Record Validity Report"
    #$mailBody = "<html><head><title>$($subject)</title><meta http-equiv=""Content-Type"" content=""text/html; charset=ISO-8859-1"" />"
}
else {
    $subject = "MX Record Validity Report"
}

$mailBody = "<html><head><title>$($subject) - $($now)</title><meta http-equiv=""Content-Type"" content=""text/html; charset=ISO-8859-1"" />"
$mailBody += $css_string
        
#heading
$mailBody += "<hr>"    
$mailBody += '<table id="HeadingInfo">'
$mailBody += "<tr><th>$($subject)<br />$($now)</th></tr>"
$mailBody += "</table>"
$mailBody += "<hr>"    


$failedResults = $finalResult | Where-Object {$_.Status -eq "Failed"}
$passedResults = $finalResult | Where-Object {$_.Status -eq "Passed"} | Group-Object Name

if ($failedResults)
{
    $mailBody += '<table id="SectionLabels"><tr><th class="data">Failed MX Lookup</th></tr></table>'
    $mailBody += '<table id="data">'
    $mailBody += "<tr><th>Domain</th><th>Error</th></tr>"
    foreach ($result in $failedResults)
    {
        $mailBody += "<tr><td>$($result.Name)</td><td class = ""bad"">$($result.error) <a href=https://intodns.com/$($result.Name) target=""_blank""> > Analyze</a></td></tr>"
    }
    $mailBody += '</table>'
}

if ($passedResults)
{
    $mailBody += '<table id="SectionLabels"><tr><th class="data">Successful MX Lookup</th></tr></table>'
    
    $mailBody += '<table id="data">'
    $mailBody += "<tr><th>Domain</th><th>Mail Exchange | Preference</th></tr>"
    foreach ($result in $passedResults)
    {
        $mx = @()
        foreach ($item in $result.Group)
        {
            $mx += "$($item.NameExchange) | $($item.Preference)"
        }
        $mailBody += "<tr><td>$($result.Name)</td><td>" + ($mx -join "<br />")+ "</td></tr>"
    }
    $mailBody += '</table>'
}
$mailBody += "<hr>"
$mailBody += '<p><table id="SectionLabels">'
$mailBody += '<tr><th>----END of REPORT----</th></tr></table></p>'
$mailBody += '<p><font size="2" face="Tahoma"><u>Report Settings</u><br /><br />'

if ($sendEmail)
{
    $mailBody += '<b>[EMAIL SETTINGS]</b><br />'
    $mailBody += 'Email Report: ' +  $sendEmail + '<br />'
    $mailBody += 'Sender: ' +  $sender + '<br />'
    $mailBody += 'Recipients: ' +  ($recipients -join ";") + '<br />'
    $mailBody += 'SMTP Server: ' +  $smtpServer + '<br />'
    $mailBody += 'SMTP Port: ' +  $smtpPort + '<br />'
    $mailBody += 'SMTP SSL: ' +  $smtpSSL + '<br />'
    $mailBody += 'SMTP Authentication: ' +  $smtpServerRequiresAuthentication + '<br />'
    $mailBody += 'Attach CSV: ' +  $attachCSVReport + '<br /><br />'
}

if ($nameServer)
{
    $mailBody += '<b>[DNS SETTINGS]</b><br />'
    $mailBody += 'DNS Server: ' +  $nameServer + '<br /><br />'
}

$mailBody += '<b>[CONFIGURATION]</b><br />'
$mailBody += 'Generated from Server: ' + (Get-Content env:computername) + '<br />'
$mailBody += 'Script File: ' + $MyInvocation.MyCommand.Definition + '<br />'
if ($logDirectory)
{
    $mailBody += 'Log File: ' + $logFile + '<br />'
}
$mailBody += 'CSV Report File: ' + $outputCsvFile + '<br />'
$mailBody += 'HTML Report File: ' + $outputHTMLFile + '<br /><br />'


$mailBody += '</p><p>'
$mailBody += "<a href=""$($scriptInfo.ProjectURI)"">$($MyInvocation.MyCommand.Definition.ToString().Split("\")[-1].Split(".")[0]) $($scriptInfo.version)</a></p>"
$mailBody += '</body></html>'
$mailBody | Out-File $outputHTMLFile

Write-Host (get-date -Format "dd-MMM-yyyy hh:mm:ss tt") ": HTML Report save to $($outputHTMLFile)" -ForegroundColor Yellow 
Write-Host (get-date -Format "dd-MMM-yyyy hh:mm:ss tt") ": Csv Report save to $($outputCsvFile)" -ForegroundColor Yellow 

#...................................
# Start MAIL
#...................................
if ($sendEmail)
{    
    [string]$mailBody = Get-Content $outputHTMLFile
    $mailParams = @{
        From = $sender
        To = $recipients
        smtpServer = $smtpServer
        Port = $smtpPort
        useSSL = $smtpSSL
        body = $mailBody
        bodyashtml = $true
    }

    if ($errorFlag -eq $true)
    {
        $subject = "ALERT!!! $($subject)"
        $mailParams += @{priority = "HIGH"}        
    }
    else {
        $subject = $subject
        $mailParams += @{priority = "LOW"}
    }

    $mailParams += @{subject = $subject}

    if ($smtpServerRequiresAuthentication)
    {
        $mailParams += @{credential = $smtpCredential}
    }

    if ($attachCSVReport)
    {
        $mailParams += @{Attachments = $outputCSVFile}
    }

    #Always
    if ($sendEmail -eq 'Always')
    {
        Write-Host (get-date -Format "dd-MMM-yyyy hh:mm:ss tt") ": Sending email to" ($recipients -join ", ") -ForegroundColor Yellow
        Send-MailMessage @mailParams
    }

    #ErrorOnly AND errorFlag=$true
    if ($sendEmail -eq 'ErrorOnly' -and $errorFlag -eq $true)
    {
        Write-Host (get-date -Format "dd-MMM-yyyy hh:mm:ss tt") ": Sending email to" ($recipients -join ", ") -ForegroundColor Yellow
        Send-MailMessage @mailParams
    }
}
#...................................
# Start MAIL
#...................................

Stop-TxnLogging