As a Build and Release Engineer, one of my job responsibilities is to set up software build automation on Windows systems. I have developed a number of automation tools internally, and one that is frequently used is for sending email notifications. The easiest and most lightweight way to perform this task is to use a PowerShell script. This is because I can easily modify or update the script to fit various system environments or workflows. Some people don’t like to install notification apps on their PCs, so they prefer to receive notifications via email.
PowerShell script
Here’s how I wrote the script to be used as a tool for sending email notifications. It’s not a full, complete script from my actual work, but the snippet should give you an idea of how it works.
# 1. SETTING UP NECESSARY PARAMETERS
$emailTo = "[email protected],[email protected]" # Separate by comma for multiple email addresses
$emailCC = "[email protected],[email protected]" # Separate by comma for multiple email addresses
$emailFrom = "[email protected]"
$emailFromDisplayName = "Auto Email Notification"
$smtpServer = "smtp.yourserver.com"
$smtpPort = 0 # 0 = not in use
$enableSSL = $false
$useDefaultCredentials = $true # Set to $false for Network Credentials
$username = "" # Provide this when $useDefaultCredentials = $false
$password = "" # Provide this when $useDefaultCredentials = $false
$useHTML = $true
$priority = [System.Net.Mail.MailPriority]::Normal # Low|Normal|High
# 2. ACQUIRING DATA OR INFO, INTERPRET IT AND PROCESS THE RESULT HERE
# Many things you can do here...
# 3. CREATING MESSAGE BODY
# Generally I use HTML for email message body.
$html_var1 = "..."
$html_var2 = "..."
$html_var3 = "..."
$emailBody = $html_var1 + $html_var2 + $html_var3
# 4. CREATING EMAIL SUBJECT
# Sometimes I decide the email subject at last, or auto-generate it.
$emailSubject = "..."
# 5. SENDING EMAIL...
# You might want to do checking/validation beforehand for necessary variables
$mailMessage = New-Object System.Net.Mail.MailMessage
if ($emailFromDisplayName -eq "" -or $emailFromDisplayName -eq $null) {
$mailMessage.From = New-Object System.Net.Mail.MailAddress($emailFrom)
} else {
$mailMessage.From = New-Object System.Net.Mail.MailAddress($emailFrom, $emailFromDisplayName)
}
$mailMessage.To.Add($emailTo)
if ($emailCC -ne "") {
$mailMessage.CC.Add($emailCC)
}
$mailMessage.Subject = $emailSubject
$mailMessage.Body = $emailBody
$mailMessage.IsBodyHtml = $useHTML
$mailMessage.Priority = $priority
$smtp = $null
if ($smtpPort -ne 0) {
$smtp = New-Object System.Net.Mail.SmtpClient($smtpServer, $smtpPort)
} else {
$smtp = New-Object System.Net.Mail.SmtpClient($smtpServer)
}
$smtp.EnableSsl = $enableSSL
$smtp.DeliveryMethod = [System.Net.Mail.SmtpDeliveryMethod]::Network
if ($useDefaultCredentials -eq $true) {
$smtp.UseDefaultCredentials = $true
} else {
$smtp.UseDefaultCredentials = $false
$smtp.Credentials = New-Object System.Net.NetworkCredential($username, $password)
}
try {
Write-Output "Sending email notification..."
$smtp.Send($mailMessage)
Write-Output "Sending email notification --> Complete"
} catch {
Write-Output "Sending email notification --> Error"
Write-Warning ('Failed to send email: "{0}"', $_.Exception.Message)
}
Here’s how you can make the script executable with parameters
To execute the script from other program with some arguments/parameters to pass, you need to include [CmdletBinding()]
and Param()
on top of your main script code.
Example:
[CmdletBinding()]
Param
(
[string]$EmailTo = "",
[string]$EmailCC = "",
[string]$EmailFrom = "[email protected]"
# ...more parameters that suit your needs
# continue here...
)
# YOUR SCRIPT GOES HERE...
You can execute your PowerShell script in different ways, depending on the program you use to run the command. Some programs may require you to provide the full path to the script file and its parameters explicitly.
Example:
./EmailNotification.ps1 -EmailTo "[email protected]" -EmailCC "[email protected]" ...
Handling the PowerShell script in more proper way
Sometimes, your PowerShell script may become complex and contain hundreds of lines of code. In this case, you may want to organize and separate it into multiple parameterized functions. The example snippet below shows how this can be done:
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Medium')]
[Alias()]
[OutputType([int])]
Param
(
[Parameter(Mandatory=$true, Position=0)]
[ValidateNotNullOrEmpty()]
[string]$EmailTo = "",
[Parameter(Position=1)]
[ValidateNotNullOrEmpty()]
[string]$EmailFrom = "[email protected]",
[switch]$EnableLog
# ...more parameters that suit your needs
# continue here...
)
function EmailNotification
{
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Medium')]
[Alias()]
[OutputType([int])]
Param
(
[Parameter(Mandatory=$true, Position=0)]
[ValidateNotNullOrEmpty()]
[string]$EmailTo = "",
[Parameter(Position=1)]
[ValidateNotNullOrEmpty()]
[string]$EmailFrom = "[email protected]",
[Parameter(Position=2)]
[AllowEmptyString()]
[string]$EmailFromDisplayName = "Auto-build Notification System",
[Parameter(Position=3)]
[ValidateNotNullOrEmpty()]
[string]$SmtpServer = "smtp.example.com"
# ...more parameters that suit your needs
# continue here...
)
# YOUR MAIN SCRIPT GOES HERE WITH OTHER FUNCTIONS...
# Example:
$otherVar1 = "..."
$otherVar2 = "..."
$template = GenerateEmailTemplate -Var1 "..." -Var2 1 -Var3
# Process variable $template...
# Do other things...
# YOUR MAIN SCRIPT ENDS HERE...
}
function GenerateEmailTemplate
{
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Medium')]
[Alias()]
[OutputType([string])]
Param
(
[string]$Var1 = "",
[int]$Var2 = 0,
[switch]$Var3
)
# CODE TO GENERATE EMAIL TEMPLATE HTML HERE... THEN RETURN AS STRING.
}
function CreateLogFile
{
# CODE TO GENERATE LOG FILE...
}
# This is how invocation of your script started...
if (-not ($myinvocation.line.Contains("`$here\`$sut"))) {
if ($EnableLog -eq $true) {
CreateLogFile
}
# Final call usually start at the main function
EmailNotification -EmailTo $EmailTo -EmailFrom $EmailFrom # ...and more parameters here...
}