Public/Send-AlertEmails.ps1

#Requires -Version 5.0

Function Send-AlertEmails() {
    <#
        .SYNOPSIS
        This PowerShell function will attempt to email alerts generated by a script
 
        The function will return true (success) or false (failed). If arrAlerts is passed it will also return any errors into the array
 
        .PARAMETER arrAlerts
        Mandatory. This is a PSCustomObject ARRAY containing the alerts to send. These should be generated like this:
 
        # Initialise the array and the session timestamp
        $arrAlerts = @()
        $sTimestamp = Get-Date -Format "yyyyMMddHHmmss"
         
        #Something happens that needs alerting on...
        $sErrMsg = "This is my error message"
        $arrAlerts += New-Object -TypeName PSCustomObject -Property @{ Session= $sTimestamp; Type="Startup-Error" ; Result=$sErrMsg }
 
        .PARAMETER objConfig
        Mandatory. This is a PowerShell object containing the following properies:
 
        $objConfig = [PSCustomObject] @{
            mailfrom = "sending-address@domain.com"
            mailto = "recipient-address@domain.com"
            mailSubject = "Mail Subject"
            smtpserver = "my-smtp-server.domain.com"
        }
 
        This information can come from an imported json config file converted to a PSCustomObject
 
        .PARAMETER EmailBodyHead
        Mandatory. This is a STRING value containing the HTML message to appear at the top of the email above the alerts data
 
        .PARAMETER arrAlertHeaders
        Optional. This is the STRING ARRAY contains the headers within the alert object that will be exported. By default this is "Type" and "Result"
 
        .PARAMETER sTimestamp
        Optional. This is a string containing the script session timestamp (Get-Date -Format "yyyyMMddHHmmss"). This is required if a log file is specified.
 
        .PARAMETER sLogFile
        Optional. This is a string containing the full path of the log file to write messages into.
 
        .EXAMPLE
        $arrAlerts = @()
        $sTimestamp = Get-Date -Format "yyyyMMddHHmmss"
        $objConfig = [PSCustomObject] @{mailfrom="joe.blogs@domain.com";mailto="ann.other@domain.com";mailsubject="My subject";smtpServer="my-smtpserver.domain.com"}
        $sEmailBodyHead = "Myscript alerts<br>This is some information that will appear above the alerts<br><br>"
 
        #Something happens that needs alerting on...
        $arrAlerts += New-Object -TypeName PSCustomObject -Property @{ Session= $sTimestamp ; Type="Startup-Error" ; Result=$sErrMsg }
         
        $bProceed = Send-AlertEmails -arrAlerts $arrAlerts -objConfig $objConfig -sEmailBodyHead $sEmailBodyHead
        This will email the alerts containined in arrAlerts. If anything fails it will return false and display the reason on screen but won't return an alert
 
        .EXAMPLE
        $sLogFile = "C:\temp\MyLogFile.log"
        $arrAlerts = @()
        $sTimestamp = Get-Date -Format "yyyyMMddHHmmss"
        $objConfig = [PSCustomObject] @{mailfrom="joe.blogs@domain.com";mailto="ann.other@domain.com";mailsubject="My subject";smtpServer="my-smtpserver.domain.com"}
        $sEmailBodyHead = "Myscript alerts<br>This is some information that will appear above the alerts<br><br>"
 
        #Something happens that needs alerting on...
        $arrAlerts += New-Object -TypeName PSCustomObject -Property @{ Session= $sTimestamp ; Type="Startup-Error" ; Result=$sErrMsg }
 
        # Send the alerts
        $params_SendAlerts = @{
            arrAlerts=$arrAlerts
            objConfig=$objConfig
            sEmailBodyHead=$sEmailBodyHead
            sTimestamp=$sTimestamp
            sLogFile=$sLogFile
        }
 
        $bProceed = Send-AlertEmails @params_SendAlerts
 
        This will email the alerts containined in arrAlerts. If anything fails it will return false and display the reason on screen and will log the reason to the log file specified in sLogFile
 
        .NOTES
        MVogwell
 
        Version history:
            0.1 - Development - pre testing - 20211204-2134
            1.0 - Production - Made the fields exportable to alerts customisable during runtime
            1.1 - Set the warning action to SilentlyContinue for the send-mailmessage command. PS v7 displays a useless warning message
            1.2 - Added param bShowInfo to supress messages on screen
    #>


    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param (
        [Parameter(Mandatory=$true)][PSCustomObject[]]$arrAlerts,
        [Parameter(Mandatory=$true)][PSCustomObject]$objConfig,
        [Parameter(Mandatory=$true)][string]$sEmailBodyHead,
        [Parameter(Mandatory=$false)][string[]]$arrAlertHeaders = @("Type","Result"),
        [Parameter(Mandatory=$false)][string]$sTimestamp,
        [Parameter(Mandatory=$false)][string]$sLogFile,
        [Parameter(Mandatory=$false)][string]$sEmailHeader = "<meta name='robots' content='noindex'><style>table { font-family: 'Trebuchet MS', Arial, Helvetica, sans-serif; border-collapse: collapse; width: 100%; font-size: 10px}td, tr { border: 1px solid #ddd; padding: 8px;}tr:nth-child(even){background-color: #f2f2f2;}tr:hover {background-color: #ddd;}th { padding-top: 12px; padding-bottom: 12px; text-align: center; background-color: #4CAF50; color: white;}</style>",
        [Parameter(Mandatory=$false)][bool]$bShowInfo = $true
    )

    BEGIN {
        $ErrorActionPreference = "Stop"

        # Write-Information requires the preference needs to be
        # set to Continue to display the messages
        if ($bShowInfo -eq $true) {
            $objInfoPref = $InformationPreference
            $InformationPreference = "Continue"
        }

        # Set the default return flag value
        $bRtn = $true

        # Handle if the timestamp is null or empty
        if (!(($PSBoundParameters).Keys -contains "sTimestamp")) {
            $sTimestamp = "NotSet"
        }
    }
    PROCESS {
        try {
            Write-Information "`n*** Alerts discovered - sending via email to $($objConfig.mailto) "

            $sEmailBody = ($arrAlerts | Select-Object $arrAlertHeaders | ConvertTo-Html -Body $sEmailBodyHead -Head $sEmailHeader) -Join ""

            $params_MailSend = @{
                From = $objConfig.mailfrom
                To = $objConfig.mailto
                SmtpServer = $objConfig.smtpserver
                Body = $sEmailBody
                BodyAsHtml = $true
                Subject = $objConfig.mailSubject
                ErrorAction = "Stop"
                WarningAction = "SilentlyContinue"
            }

            Send-MailMessage @params_MailSend

            if (($PSBoundParameters).Keys -contains "sLogFile") {
                $sLogMsg = ($sTimestamp + ",INFO,Successfully emailed alerts")
                Add-Content $sLogFile -Value $sLogMsg
            }

            Write-Information "`t+++ Success `n"
        }
        catch {
            $bRtn = $false

            # Capture and add to the error message
            [string]$sErrMsg = ("Failed to send alert emails! ")
            [string]$sErrMsg += ("Error: " + (($Global:Error[0].Exception.Message).toString()).replace("`r"," ").replace("`n"," "))

            # If the log file path has been specified in the parameters write the error log message
            if (($PSBoundParameters).Keys -contains "sLogFile") {
                [string]$sLogMsg = ($sTimestamp + ",ERROR," + $sErrMsg)
                $sLogMsg | Out-File $sLogFile -Encoding utf8 -Append -ErrorAction "Continue"
            }

            Write-Information "`t--- $sErrMsg `n"
        }
    }
    END {
        # Reset the InformationPreference value
        if ($bShowInfo -eq $true) {
            $InformationPreference = $objInfoPref
        }

        return $bRtn
    }
}