Get-MXReport.ps1

#Requires -Version 5.1
<#PSScriptInfo
 
.VERSION 1.4
 
.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 g) + " " + (Get-TimeZone).ToString().Split(" ")[0]

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

#subject and title
$subject = "MX Record Availability Report: $now"

$css_string = @'
<style type="text/css">
#HeadingInfo
{
font-family:"Segoe UI Light";
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;
}
#section
{
font-family:"Segoe UI Light";
width:100%;
border-collapse:collapse;
}
#section th
{
font-size:1.0em;
text-align:left;
padding-top:5px;
padding-bottom:4px;
background-color:#fff;
color:#000;
}
#data
{
font-family:"Segoe UI Light";
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;
vertical-align:top;
}
#data td.bad
{ font-size:0.8em;
font-weight: bold;
padding-top:5px;
padding-bottom:4px;
color:#f04953;
vertical-align:top;
}
#data td.good
{ font-size:0.8em;
font-weight: bold;
padding-top:5px;
padding-bottom:4px;
color:#01a982;
vertical-align:top;
}
 
.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) {
    #Write-Host "Processing $($domain)... " -NoNewLine
    $queryParams = @{
        name = $domain
        type = "MX"
    }
    if ($nameServer) {$queryParams += @{Server = $nameServer}}
    
    $allRecords = resolve-dnsname @queryParams -ErrorAction SilentlyContinue
    $mxRecords = $allRecords | Where-Object {$_.QueryType -eq "MX"} | Sort-Object -Property Preference
    
    #if there are records found
    if ($mxRecords) {
        foreach ($mxRecord in $mxRecords) {
        
            $x = "" | Select-Object Name,NameExchange,Preference,IPAddresses,Status
            $x.Name = $mxRecord.Name
            $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 = 1
            $finalResult += $x
        }
        #Write-Host "OK" -ForegroundColor Green
        Write-Host (get-date -Format "dd-MMM-yyyy hh:mm:ss tt") ": $($domain): OK" -ForegroundColor Green
    }
    #if there are no records found or if an error is encountered
    elseif (!$mxRecords) {
        #trip the error flag to $true
        $errorFlag = $true

        $x = "" | Select-Object Name,NameExchange,Preference,IPAddresses,Status
        $x.Name = $domain
        $x.NameExchange = "Error"
        $x.Preference = "Error"
        $x.IPAddresses = "Error"
        $x.Status = 0
        $finalResult += $x
        Write-Host (get-date -Format "dd-MMM-yyyy hh:mm:ss tt") ": $($domain): NOT OK" -ForegroundColor RED
    }
}
$finalResult = $finalResult | Sort-Object Status
$finalResult | Export-Csv -NoTypeInformation $outputCsvFile

#create the HTML report
#html title
$mailBody = "<html><head><title>$($subject)</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)</th></tr>"
$mailBody += "</table>"
$mailBody += "<hr>"    
$mailBody += '<table id="data">'

foreach ($result in $finalResult){
    if ($currentDomain -ne $result.Name)
    {
        $mailBody += "<tr><th>$($result.Name)</th><th>MX</th><th>Preference</th><th>IP Addresses</th><th>Status</th></tr>"
        $currentDomain = $result.Name
        #$mailBody += "<tr><td>$($result.Name)</td>"
        $mailBody += "<tr><td></td>"
        
        if ($result.NameExchange -eq "Error")
        {
            $mailBody += "<td class = ""bad"">Error</td>"
            $mailBody += "<td></td><td></td>"
            $mailBody += "<td class = ""bad"">Error resolving MX, click here to <a href=https://intodns.com/$($result.Name) target=""_blank"">Analyze</a></td></tr>"
        }
        else
        {
            $mailBody += "<td>$($result.NameExchange)</td>"
            $mailBody += "<td>$($result.Preference)</td>"
            #$IPList = ($result.IPAddresses).replace(";",", ")
            $mailBody += "<td>$(($result.IPAddresses).replace(";","<br>"))</td>"
            $mailBody += "<td class = ""good"">OK</td></tr>"
        }
    }
    elseif ($currentDomain -eq $result.Name)
    {
        $mailBody += "<tr><td></td>"
        if ($result.NameExchange -eq "Error")
        {
            $mailBody += "<td class = ""bad"">Error</td>"
            $mailBody += "<td></td>"
            $mailBody += "<td class = ""bad"">Error resolving MX, click here to <a href=https://intodns.com/$($result.Name) target=""_blank"">Analyze</a></td></tr>"
        }
        else
        {
            $mailBody += "<td>$($result.NameExchange)</td>"
            $mailBody += "<td>$($result.Preference)</td>"
            #$IPList = ($result.IPAddresses).replace(";",", ")
            $mailBody += "<td>$(($result.IPAddresses).replace(";","<br>"))</td>"
            $mailBody += "<td class = ""good"">OK</td></tr>"
        }
    }
}
$mailBody += '</table>'
#$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