PowerShell

Sending HTML emails with PowerShell and zero HTML knowledge required

I saw this article by Altaro tweeted Building PowerShell Tools for MSPs: HTML Tables for Reporting, and it describes how you can create HTML emails with just a few lines of code. Luke created that article in 2018 (tweets from the archive I guess), but I just saw it now so thought I would make a slight comparison. In 2018 I would probably go the same way as shown by Luke Orellana, who takes a simple example of querying WMI to get disk drive sizes and send them over, formatted via Email.

What Altaro article is all about?

The article describes how you can send yourself this little table of disk data with some WMI query, some basic HTML and Send-MailMessage.

$disks = GET-WMIOBJECT win32_logicaldisk -filter "DriveType='3'"

foreach($disk in $disks)
{
$DriveLetter = $disk.DeviceID;
$SizeGB = $disk.Size / 1GB -as [int]
$FreeSpaceGB = $disk.FreeSpace / 1GB -as [int]
$PercentFree = [math]::Round((1- ($freeSpaceGB/ $sizeGB)) * 100)

$dataRow = "
</tr>
<td>$DriveLetter</td>
<td>$SizeGB GB</td>
<td>$FreeSpaceGB GB</td>
<td>$PercentFree %</td>
</tr>
"
$diskreport += $datarow

}

$report = "<html>
<style>
{font-family: Arial; font-size: 13pt;}
TABLE{border: 1px solid black; border-collapse: collapse; font-size:13pt;}
TH{border: 1px solid black; background: #dddddd; padding: 5px; color: #000000;}
TD{border: 1px solid black; padding: 5px; }
</style>
<h2>Server Space Report</h2>
<table>
<tr>
<th>Volume</th>
<th>Total Space</th>
<th>Free Space</th>
<th>Percent Full</th>
</tr>
$diskreport
</table>
<tr>
"

Send-MailMessage -To luke@test.com -From ServerReport@test.com -Body $report -subject "Server Disk Space Report" -SmtpServer mysmtpserver.com

In 2018 I would probably do something similar with maybe a change to table building using ConvertTo-HTML as it's much easier than playing with all that TR/TD stuff that is shown above.  Still, the main issue here is that to some degree you need to know what you're doing in HTML, and how those things work together to get what you see on screen.

How I do it using Emailimo (PSWriteHTML)

But in 2019, I do stuff a bit differently. I wrote PSWriteHTML module, and with its the help I've created Emailimo PowerShell Module. Now anytime I want to send an email I start with Emailimo. How to get it started and achieve the same thing as shown above? First, we need to install Emailimo.

Install-Module Emailimo -AllowClobber -Force

When that's done and working, there's only a matter of code. The setup and getting of disk data stay mostly the same. I left it intact although I should have used Get-CimInstance instead of Get-WmiObject as it's 2019 way to work with WMI classes). I've only changed the way I'm building FormattedDisk object so that I can pass this Array of PSCustomObjects into EmailTable later on. I don't need the data to be in separate variables, as shown in the example above. I treat one drive as one object, and I can display it without any effort.

$Disks = Get-WmiObject win32_logicaldisk -filter "DriveType='3'"
$FormattedDisk = foreach ($disk in $disks) {
    [PSCustomObject] @{
        'Volume' = $disk.DeviceID
        'Total Space'      = "$($disk.Size / 1GB -as [int]) GB"
        'Free Space' = "$($disk.FreeSpace / 1GB -as [int]) GB"
        'Percent Full' = "$([math]::Round((1 - ($freeSpaceGB / $sizeGB)) * 100))%"
    }
}

Email {
    EmailFrom -Address 'reminder@domain.pl'
    EmailTo -Addresses "przemyslaw.klys@domain.pl"
    EmailCC -Addresses "przemyslaw.klys@domain.pl"
    EmailBCC -Addresses "kontakt@domain.pl"
    EmailServer -Server 'mail.domain.pl' -UserName 'UserName' -Password 'C:\Support\Important\Password-Evotec-Reminder.txt' -PasswordAsSecure -PasswordFromFile
    EmailOptions -Priority Low
    EmailSubject -Subject 'This is a test email'
    
    EmailBody -FontFamily 'Calibri' -Size 15 {
        EmailText -Text 'Server Space Report' -FontWeight bold -Color Grey -LineBreak

        EmailTable -DataTable $FormattedDisk -HideFooter
    }
}

See? Similar output, zero HTML and mostly easy to read, and understand the code that you can adjust to your needs. The thing to know here is that you don't need to do pre-formatting anything to pass it to EmailTable. You can provide it as is, but since emails are emails, you may want to export only data you need. Here's an example with full output from Disks variable.

Way too many columns for the email to be readable, and useful, but the code to generate it, mostly the same with just two added lines.

$Disks = Get-WmiObject win32_logicaldisk -filter "DriveType='3'"
$FormattedDisk = foreach ($disk in $disks) {
    [PSCustomObject] @{
        'Volume' = $disk.DeviceID
        'Total Space'      = "$($disk.Size / 1GB -as [int]) GB"
        'Free Space' = "$($disk.FreeSpace / 1GB -as [int]) GB"
        'Percent Full' = "$([math]::Round((1 - ($freeSpaceGB / $sizeGB)) * 100))%"
    }
}

Email {
    EmailFrom -Address 'reminder@domain.pl'
    EmailTo -Addresses "przemyslaw.klys@domain.pl"
    EmailCC -Addresses "przemyslaw.klys@domain.pl"
    EmailBCC -Addresses "kontakt@domain.pl"
    EmailServer -Server 'mail.domain.pl' -UserName 'UserName' -Password 'C:\Support\Important\Password-Evotec-Reminder.txt' -PasswordAsSecure -PasswordFromFile
    EmailOptions -Priority Low
    EmailSubject -Subject 'This is a test email'
    
    EmailBody -FontFamily 'Calibri' -Size 15 {
        EmailText -Text 'Server Space Report' -FontWeight bold -Color Grey -LineBreak

        EmailTable -DataTable $FormattedDisk -HideFooter

        EmailText -LineBreak

        EmailTable -DataTable $Disks -HideFooter
    }
}

If you want to find out about Emailimo other features have a look on my earlier blog about it or if you prefer to see sources that are available on GitHub. I do plan on working on Emailimo, by adding more features and making it prettier. Right now it has some custom stuff built-in, but if you've seen what PSWriteHTML can do, you can expect all of that ported to Emailimo.

Przemyslaw Klys

System Architect with over 14 years of experience in the IT field. Skilled, among others, in Active Directory, Microsoft Exchange and Office 365. Profoundly interested in PowerShell. Software geek.

Share
Published by
Przemyslaw Klys

Recent Posts

Upgrade Azure Active Directory Connect fails with unexpected error

Today, I made the decision to upgrade my test environment and update the version of…

1 month ago

Mastering Active Directory Hygiene: Automating Stale Computer Cleanup with CleanupMonster

Have you ever looked at your Active Directory and wondered, "Why do I still have…

2 months ago

Active Directory Replication Summary to your Email or Microsoft Teams

Active Directory replication is a critical process that ensures the consistent and up-to-date state of…

7 months ago

Syncing Global Address List (GAL) to personal contacts and between Office 365 tenants with PowerShell

Hey there! Today, I wanted to introduce you to one of the small but excellent…

11 months ago

Active Directory Health Check using Microsoft Entra Connect Health Service

Active Directory (AD) is crucial in managing identities and resources within an organization. Ensuring its…

1 year ago

Seamless HTML Report Creation: Harness the Power of Markdown with PSWriteHTML PowerShell Module

In today's digital age, the ability to create compelling and informative HTML reports and documents…

1 year ago