Learn What IT Pros Need to Know About Windows 11 - August 24th at 1 PM ET! Learn What IT Pros Need to Know About Windows 11 - August 24th at 1 PM ET!
PowerShell

Creating Colorful Emails with PowerShell

color-aspect-hero

In the comments on a recent article about creating a color coded report of domain controller service statuses, there was a question in the comments about sending the same type of information, presumably colorized, in an email message. PowerShell makes it very easy to send email with the Send-MailMessage cmdlet. You can even send HTML messages, which is the key to answering this question.

As in the previous articles, I need to get the service information from my domain controllers. Of course, this could be other data that you want to report.

$dcs = "chi-dc01","chi-dc02","chi-dc04"
$svcs = "adws","dns","kdc","netlogon"
$data = Get-Service -name $svcs -ComputerName $dcs

I’ll also define a title for the report.
$ReportTitle = "Domain Controller Services"

Now for the first tricky part. When we create HTML documents in PowerShell, typically with ConvertTo-HTML, style is applied separately, usually through a CSS file. But you can also embed style information in the head of an HTML document. I’ll create a here-string with an embedded style sheet.
$head = @"
<Title>$ReportTitle</Title>
<style>
body { background-color:#FFFFFF;
font-family:Tahoma;
font-size:12pt; }
td, th { border:1px solid black;
border-collapse:collapse; }
th { color:white;
background-color:black; }
table, tr, td, th { padding: 2px; margin: 0px }
table { width:95%;margin-left:5px; margin-bottom:20px;}
.stopped {color: Red }
.running {color: Green }
.pending {color: #DF01D7 }
.paused {color: #FF8000 }
.other {color: Black }
</style>
<br>
<H1>$ReportTitle</H1>
"@


The relevant parts for dynamically colorizing our output is in lines 13 to 17. These settings will be used to define a new style class. The settings inside the curly brackets will be applied for each match. All I’m doing is setting the font color. I’m using a mix of color names like red and HTML color codes. The better practice would probably be to use color codes for everything. Now we’re ready to start generating some HTML.

I only need a few properties, so I’ll select them and pipe to Convertto-Html. I don’t want a complete document yet, because I’m going to have to adjust it first to account for the different service statues. I have found the easiest solution is to create an HTML fragment, but treat it as an XML document.

[xml]$html = $data |
Select @{Name="DomainController";Expression={$_.MachineName.ToUpper()}},Name,Displayname,Status |
ConvertTo-Html -Fragment

Sponsored Content

Read the Best Personal and Business Tech without Ads

Staying updated on what is happening in the technology sector is important to your career and your personal life but ads can make reading news, distracting. With Thurrott Premium, you can enjoy the best coverage in tech without the annoying ads.

Why? Because I can now “walk” the document.

HTML as an XML document
HTML as an XML document (Image Credit: Jeff HIcks)

It will be much easier to reference specific rows and columns. I’ll skip the first row since it is the table header.

1..($html.table.tr.count-1) | foreach {
#enumerate each TD
$html.table.tr[$_]
}

Enumerating the table
Enumerating the table (Image Credit: Jeff Hicks)

What I’m really seeing, remember this is an XML document, is a collection of child nodes.

1..($html.table.tr.count-1) | foreach {
#enumerate each TD
$td = $html.table.tr[$_]
$td.childnodes
}

Expanding the table rows
Expanding the table rows (Image Credit: Jeff Hicks)

Because I know the Status column is the last row, I can select just that node.

1..($html.table.tr.count-1) | foreach {
#enumerate each TD
$td = $html.table.tr[$_]
$td.childnodes.item(3)
}

Listing text values
Listing text values (Image Credit: Jeff HIcks)

My intention is to add a style class to this column based on the text value.

1..($html.table.tr.count-1) | foreach {
#enumerate each TD
$td = $html.table.tr[$_]
#create a new class attribute
$class = $html.CreateAttribute("class")

#set the class value based on the item value
Switch ($td.childnodes.item(3).'#text') {
"Running" { $class.value = "running"}
"Stopped" { $class.value = "stopped"}
"Pending" { $class.value = "pending"}
"paused" { $class.value = "paused"}
Default { $class.value = "other"}
}
#append the class
$td.childnodes.item(3).attributes.append($class) | Out-Null
}

If I look again, I’ll now see the class attribute.

The new class attribute
The new class attribute (Image Credit: Jeff Hicks)

At this point my HTML is complete, and I can see it as the InnerXML property of my XML document. I’ve highlighted a few of the changes.

The updated HTML code
The updated HTML code (Image Credit: Jeff Hicks)

All that remains now is to create the final HTML report. If I wanted to create a stand-alone report I can use ConvertTo-Html and send the results to a file.

ConvertTo-HTML -Head $head -Body $html.InnerXml -PostContent “<h6>Created $(Get-Date)</h6>” |
Out-File -filepath c:\work\DCSvcs.htm -Encoding asci

The end result is an HTML report that looks like this:

Sample HTML report
Sample HTML report (Image Credit: Jeff HIcks)

Or if I want to send this as an email message, I’ll convert to HTML and save the results to a variable.

[string]$body = ConvertTo-HTML -Head $head -Body $html.InnerXml -PostContent "<h6>Created $(Get-Date)</h6>"

The body needs to be a string, which is why I am explicitly telling PowerShell to treat it as a string. I can define a hashtable of parameter values for Send-MailMessage.
[email protected]{
To = "[email protected]"
From = "[email protected]"
Subject = "Domain Controller Status Report"
SMTPServer = "smtp.mycompany.com"
Body = $Body
BodyAsHTML = $True
Port = 587
UseSSL = $True
Credential = $mailCred
}

You will have different needs depending on your mail server. I splat the parameters:
Send-MailMessage @mailparams

And the mail is sent.

Sample HTML email
Sample HTML email (Image Credit: Jeff Hicks)

So the long answer to the original question is that you can send a colorized email, but you’ll need an HTML document that has been dynamically modified with some styling. I use many of these techniques for a lot of my HTML reporting needs. If I lost you anywhere in the process, please feel free to post a question in the comments.

Related Topics:

BECOME A PETRI MEMBER:

Don't have a login but want to join the conversation? Sign up for a Petri Account

Register
Comments (1)

One response to “Creating Colorful Emails with PowerShell”

  1. asa75asa

    Can't see the images in the article :(

Leave a Reply

Register for Advanced Microsoft 365 Day!

GET-IT: Advanced Microsoft 365 1-Day Virtual Conference - Live August 24th!

Join us on Tuesday, August 24th and hear from Microsoft MVPs and industry experts about how to take advantage of Microsoft 365 at a technical level and dive deep into the features and functionality that will make your environment more secure and compliant.

RSVP Now

Sponsored By