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.



1 2 3 $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.



1 $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.



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $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.



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





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

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



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





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



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





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



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





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



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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.

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.

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:

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



1 [ 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.



1 2 3 4 5 6 7 8 9 10 11 $mailParams = @ { 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:



1 Send-MailMessage @ mailparams



And the mail is sent.

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.