In the last part of this article series on sending email using PowerShell I demonstrated how to create HTML emails from PowerShell scripts.

One of the downsides to creating HTML output from PowerShell scripts is that the formatting is not very nice. The default formatting results in messages that look something like this.

How to Send SMTP Email Using PowerShell (Part 4)

The HTML for that email message was created by piping the output from one command into the ConvertTo-HTML cmdlet. Fortunately ConvertTo-HTML has the -Head parameter that can be used to add style information to the HTML that it generates.

For example, by adding this line to the script used in the last article we can change the font to something a little nicer to look at.

$style = "<style>BODY{font:arial 10pt;}</style>"

Then modify the ConvertTo-HTML cmdlet to add the -Head parameter.

$message.Body = Get-ExchangeServer | Select-Object Name,ServerRole | ConvertTo-Html -Head $style

This time when the script is run the email looks like this instead.

How to Send SMTP Email Using PowerShell (Part 4)

That is a little better, but we can do a lot more. How about we add some more styles to the table and really make it look nice.

$style = "<style>BODY{font-family: Arial; font-size: 10pt;}"
$style = $style + "TABLE{border: 1px solid black; border-collapse: collapse;}"
$style = $style + "TH{border: 1px solid black; background: #dddddd; padding: 5px; }"
$style = $style + "TD{border: 1px solid black; padding: 5px; }"
$style = $style + "</style>"

Now the script produces an email that looks like this.

How to Send SMTP Email Using PowerShell (Part 4)

Although this requires you to know a little bit about how HTML styles work, it is a pretty easy topic to learn and once you get a few working styles in your scripting tool kit you can just use them over and over again.

About the Author

Paul Cunningham

Paul is a former Microsoft MVP for Office Apps and Services. He works as a consultant, writer, and trainer specializing in Office 365 and Exchange Server. Paul no longer writes for Practical365.com.

Comments

  1. Justin

    Well that was a head scratcher. I’m guessing the comment section is stripping HTML tags. So things like this line are blank:

    $style = $style + “”

    The end style tag should be in the quotes. This is why people are complaining about their “style” being in text at the top of their email.

  2. Harish

    How to conditionally change table row color in html table by power shell command

    1. Paul Wain

      The CSS is something like this for Odd/Even rows:

      tr:nth-child(even) { background-color: #eee; } tr:nth-child(odd) { background-color: #fff; }

  3. Kathy

    Brilliant. Thanks for posting.

  4. Vinay

    Hi , Can u please help me to get table in HTML format in powershell.

    Thursday, March 01, 2018 6:53:02 AM

    Queue status Count
    BadQueue 0
    HoldingQueue 0
    InboundQueue 0
    LanQueue 0
    LocalQueue 0
    RemoteQueue 0
    RetryQueue 76

    Diskspace Used Free
    E:Drive space 1357.241749 318.1576614

  5. fahid

    for some reason, when I do my script, the style tag comes out above the table. and the table is formatted plain. this is my script, i am really stuck on this and have tried various ways to get this to work, i am using gmail.

    # make the “creds” file first and drop it into a directory.

    Write-Host “`n Starting script, connecting to server” -ForegroundColor Green

    $creds = Get-VICredentialStoreItem -file “D:…”
    connect-viserver -server $creds.Host -User $creds.User -Password $creds.Password
    Start-Sleep -s 30

    Write-Host “`n Connection to server complete” -ForegroundColor Green
    Write-Host “`n Pulling data from Win03vc02” -ForegroundColor Green

    $date = Get-Date
    $dateforname = Get-Date -UFormat ‘%m-%d-%Y-%H%M%S’
    $filename = “VMsnapshots_” + $dateforname + “.html”

    $tablestyle = “BODY{font:calibri 14pt;}”

    $Report += Get-VM | Get-Snapshot | Select-Object VM,VMId,Description,PowerState,SizeGB | Sort-Object SizeGB | ConvertTo-Html -Head $tablestyle | Out-String

    Write-Host “`n Data pulled, sending mail in 60 seconds…” -ForegroundColor green

    Start-Sleep -s 60

    $from = “a”
    $to = “a”
    $subject = “VMWare snapshots report for week of $date”
    $smtp = “a”

    Send-MailMessage -from $from -to $to -subject $subject -BodyAsHtml -Body $Report -smtpServer $smtp

    Write-Host “`n e-mail will arrive shortly, process complete!”

    1. Victor

      I had the same problem.
      This style works for me:
      $style = “”
      $style = $style + “BODY{font-family: Arial; font-size: 10pt;}”
      $style = $style + “TABLE{border: 1px solid black; border-collapse: collapse;}”
      $style = $style + “TH{border: 1px solid black; background: #dddddd; padding: 5px; }”
      $style = $style + “TD{border: 1px solid black; padding: 5px; }”
      $style = $style + “”

  6. Abhishek Gupta

    How to add two tables in one e-mail body

  7. vijender Reddy

    Hi All,

    I need a pwershell script to get the email alert when site went to disable state in IIS 7.0

    can some one help on this, Thanks

  8. Larry

    Hi Paul,

    I am new to Powershell and I am trying to make use of your code above. Basically I want to change font size half way through an email but so far I have failed. The email is set as HTML, and I can get the text to change to italic, but I am stumped on the font size change.

    Where the font changes to italic below, I want that font to change to Arial, font size 8. – Many Thanks – Larry

    #Message Body
    $msg.IsBodyHTML = $True
    $msg.Body = ”Please See Attached Files
    Many Thanks,
    Larry (Test) xxxx

    1. Larry

      Sorry Paul, it did not accept the breaks or italic commands in the $msg.body above

      Where the “(Test) xxxx” is shown above, this is the text that I want changed

      Cheers

      Larry

  9. Matt Pollock

    Ah right I see, thanks Paul.
    I’ve amended the script, which now works perfectly.
    Thanks again.
    Matt

    $smtpsettings = @{
    To = “me@domain.com”,”me1@domain.com”
    From = “ExchangeReports@domain.com”
    Subject = “MailBox Report for $((Get-Date).ToShortDateString())”
    SmtpServer = “mail.domain.localnet”
    }

    $style = “BODY{font-family: Arial; font-size: 10pt;}”
    $style = $style + “TABLE{border: 1px solid black; border-collapse: collapse;}”
    $style = $style + “TH{border: 1px solid black; background: #7FFF00; padding: 5px;}”
    $style = $style + “TD{border: 1px solid black; padding: 5px;}”
    $style = $style + “”

    $MailBoxReport = Get-MailboxDatabase `
    | Get-MailboxStatistics | ?{$_.IsArchiveMailbox -eq $false} `
    | Sort-Object TotalItemSize -Desc `
    | Select-Object DisplayName, Database, TotalItemSize, LastLogonTime, LastLoggedOnUserAccount -First 20 `
    | ConvertTo-Html -Head $style

    Send-MailMessage @smtpsettings -Body $MailBoxReport -BodyAsHTML

    1. Fabian Vega

      Hey, Matt.

      I’ve tried to add this line “Send-MailMessage @smtpsettings -Body $MailBoxReport -BodyAsHTML” into sharepoint powershell function, but it returns an error. LOL

      what can i do?

  10. Logan

    Hey thanks for this. If you wanted to add more than one table in the body of an email, how would you do so using this script?

    Thanks

    1. Matt Pollock

      Hello Paul,

      Great script, it works very well.
      Just one question though – how do you specify multiple email recipients?

      Thanks

      1. Avatar photo
        Paul Cunningham

        As a comma-separated list.

        Eg, “address1@domain.com”,”address2@domain.com”

        1. Matt Pollock

          Thanks for the reply Paul.
          I tried a comma separated list before posting the comment – the error returned is below:

          New-Object : Exception calling “.ctor” with “2” argument(s): “The specified string is not in the form required for an e-mail address.”

          The script runs but the only the first email address in the list receives the email.

          Script is below:

          $smtpServer = “mail.domain.localnet”
          $smtpFrom = “ExchangeReports@domain.com”
          $smtpTo = “me@domain.com”,”me1@domain.com”
          $messageSubject = “MailBox Report for $((Get-Date).ToShortDateString())”

          $message = New-Object System.Net.Mail.MailMessage $smtpfrom, $smtpto
          $message.Subject = $messageSubject
          $message.IsBodyHTML = $true

          $style = “BODY{font-family: Arial; font-size: 10pt;}”
          $style = $style + “TABLE{border: 1px solid black; border-collapse: collapse;}”
          $style = $style + “TH{border: 1px solid black; background: #7FFF00; padding: 5px;}”
          $style = $style + “TD{border: 1px solid black; padding: 5px;}”
          $style = $style + “”

          $message.Body = Get-MailboxDatabase `
          | Get-MailboxStatistics | ?{$_.IsArchiveMailbox -eq $false} `
          | Sort-Object TotalItemSize -Desc `
          | Select-Object DisplayName, Database, TotalItemSize, LastLogonTime, LastLoggedOnUserAccount -First 20 `
          | ConvertTo-Html -Head $style

          $smtp = New-Object Net.Mail.SmtpClient($smtpServer)
          $smtp.Send($message)

        2. Avatar photo
          Paul Cunningham

          Ah, I really should update this article series to get rid of the PowerShell 1.0 references.

          So if you look back at this part you’ll see the PowerShell 2.0 method for sending email, which uses a proper cmdlet Send-MailMessage.

          https://www.practical365.com/powershell-how-to-send-email/

          An example:

          ==================================
          $smtpsettings = @{
          To = “administrator@exchangeserverpro.net”
          From = “exchangeserver@exchangeserverpro.net”
          Subject = “Exchange CAS Health Report – $now”
          SmtpServer = “smtp.exchangeserverpro.net”
          }

          Send-MailMessage @smtpsettings -Body $whatever
          ==================================

          So in this case that To should accept multiple comma-separated addresses.

          If you’re looking for some more comprehensive examples most if not all of the scripts available in http://inside.exchangeserverpro.com have code for sending email.

    2. Matthew

      Hi Logan

      Did Paul ever reply to you? I have a scenario where I have two tables in my message body, but the second one doesn’t seem to adhere to the formatting. Yet if I output the entire message body to and HTML file and open in a browser, it looks right. Seems like Outlook or the send-mailmessage cmdlet is doing something with the formatting.

  11. Tim Preston

    Oops, sorry – my copy/paste didn’t work so well there. The ‘$style’ code should be:

    $style = “BODY{font-family: Arial; font-size: 10pt;}”
    $style = $style + “TABLE{border: 1px solid black; border-collapse: collapse;}”
    $style = $style + “TH{border: 1px solid black; background: #dddddd; padding: 5px; }”
    $style = $style + “TD{border: 1px solid black; padding: 5px; }”
    $style = $style + “”

  12. Tim Preston

    Hi Paul, great write up.

    I have followed all 4 parts of your series and have had good success. The only thing I can’t get working is the table formatting from this latest part. The tags don’t seem to be getting processed, the HTML code is simply printed at the top of email body verbatim (before the cmdlet’s output).

    Here’s my script:

    $smtpServer = “localhost”
    $smtpFrom = “name1@test.com”
    $smtpTo = “name2@test.com”
    $messageSubject = “Test”

    $message = New-Object System.Net.Mail.MailMessage $smtpfrom, $smtpto
    $message.Subject = $messageSubject
    $message.IsBodyHTML = $true

    $style = “BODY{font-family: Arial; font-size: 10pt;}”
    $style = $style + “TABLE{border: 1px solid black; border-collapse: collapse;}”
    $style = $style + “TH{border: 1px solid black; background: #dddddd; padding: 5px; }”
    $style = $style + “TD{border: 1px solid black; padding: 5px; }”
    $style = $style + “”

    $message.Body = Get-MailboxExportRequest | Get-MailboxExportRequestStatistics | Select-Object SourceAlias,Status | ConvertTo-Html -Head $style

    $smtp = New-Object Net.Mail.SmtpClient($smtpServer)
    $credentials=new-object system.net.networkcredential(”user”,”password”)
    $smtp.credentials=$credentials.getcredential($smtpServer,25,”basic”)
    $smtp.Send($message)

    Thanks!

  13. Vasili Syrakis

    Hey Paul,

    This guide is awesome and I’ll definitely be using it to create some custom alerts for my servers.

    There is one thing that I wanted to nitpick though.

    Where you assigned values to the style sheet variable, there is a short way to do it:

    $style = “BODY{font-family: Arial; font-size: 10pt;}
    TABLE{border: 1px solid black; border-collapse: collapse;}
    TH{border: 1px solid black; background: #dddddd; padding: 5px; }
    TD{border: 1px solid black; padding: 5px; }

    Unless there is a reason why you did it your way?… I am still new to PS.

  14. JKY

    Very useful tip!
    Thanks a lot.

Leave a Reply