HTML report as body with Send-Mailmessage

Good day all.

I have a script that queries a list of servers for their data drive sizes and now The Powers That Be would like to be notified if any of the drives have less than 25% space available. Originally the large text file wasn’t good enough and not everyone appreciated a CSV file of the data, so they asked for it in email. The problem I’m running into is that I have the results converted to HTML and sent to a file, but when I try and have it use the contents of the file as the body the email only contains the file path.

I’ve tried encapsulating the path in double quotes, tried tab completing the path and file name, tried enclosing it in parenthesis and used Get-Content and nothing seems to give me the data. I hope I’ve just missed something silly.

#Create Array and set AlertState to 0

$AlertDisks = @()
$AlertState = 0

#WMI call and custom object creation

$Disks = Get-WmiObject -ComputerName Server01, Server02, Server03, Server04 -Class win32_logicaldisk | Where-Object {$_.DeviceID -notmatch "^C|^D"} | 
    select PSComputerName, DeviceID, VolumeName, @{Name='Size (GB)' ;Expression={"{0:n2}" -f ($_.size/1gb)}}, @{Name='FreeSpace (GB)' ;Expression={"{0:n2}" -f ($_.FreeSpace/1gb)}}, @{Name='PercentFree' ;Expression={"{0:n2}" -f ($_.freespace/$_.size*100)}}


#Loop to check for any disk under 25%

$Disks | ForEach-Object{
    IF ($_.PercentFree -lt 25)
        {
        $AlertState = 1
        $AlertDisks += $_
        }
    ELSE
        {
        }
    }

# Send email if any disks triggered AlertState

IF ($AlertState -eq 1)
    {
    $AlertDisks | ConvertTo-Html -Head " TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;} TH{border-width: 1px;padding: 3px;border-style: solid;border-color: black;} TD{border-width: 1px;padding: 3px;border-style: solid;border-color: black;} " -Body " Exchange Drive Free Space Below 25% " -PostContent "", "This report was generated on : ", (Get-Date -Format G) | Out-File C:\Scripts\Reports\DiskReport.htm
    Send-MailMessage -To Admins@contoso.com -From Alerting@contoso.com -Subject "Disk Free Space Alert" -BodyAsHtml C:\Scripts\Reports\DiskReport.htm -Priority High -SmtpServer smtp.contoso.com 
    }

Any help would be appreciated and any suggestions on how to do this more effectively would be wonderful.

-BodyAsHtml is a switch. Since you’re using named and not positional parameters everywhere else, it’s probably worth pointing out that you’d still want to use -Body in addition to -BodyAsHtml (and your string is being bound to the Body parameter positionally anyway.)

Now, the Body parameter accepts a string, and it’s a common gotcha that people try to give it an array of strings instead. PowerShell will gladly join that array together into a single string, but by default, it separates them with a single space character. Since these arrays of strings tend to be “one per line”, it screws up the formatting. If you’re using PowerShell 3.0 or later, the simplest way to get your HTM file loaded into a string is to use Get-Content’s -Raw switch:

$body = Get-Content C:\Scripts\Reports\DiskReport.htm -Raw
Send-MailMessage -Body $body -BodyAsHtml # other parameters

If you need to support PowerShell 2.0, there are a few different ways to load a file into a string. I tend to use the .NET framework methods directly, since they’re fast, but you sometimes have to be careful about PSDrives with weird names other than drive letters. Those would need to be translated to basic file system paths first. Not a problem here since you’re hard-coding a value that starts with c:\

$body = [System.IO.File]::ReadAllText('C:\Scripts\Reports\DiskReport.hml')
Send-MailMessage -Body $body -BodyAsHtml # other parameters

Thank you Dave. The Get-Content - raw switch fixed my issue.