Sending styled HTML email from Powershell (Using a .NET DLL in Powershell)

Shaun VermaakCOG Lead Engineer
CERTIFIED EXPERT
My name is Shaun Vermaak and I have always been fascinated with technology and how we use it to enhance our lives and business.
Published:
Via various tools, systems and automated alerts I generate thousands of emails per day. Using a common method to send these emails makes it easier to standardize these messages. One key feature of these email methods is stylized emails. This article shows how to use this library with Powershell.

Introduction


I have written a small mail sending function in .NET that I leverage in all my systems I develop. I had to develop a bunch of Powershell scripts to monitor and report on various process and instead of going throught the effort of reworking my .NET DLL and a Powershell function I opted to call the .NET DLL directly from Powershell.


My email DLL gives the ability to mail styled email messages. You can get the DLL from http://blog.ittelligence.com/wp-content/uploads/2019/05/ITtelligence.Email_.dll_.zip


This method also produces the same result in Microsoft Outlook and other mail clients. See GMail preview of mail below.



Below you can see how to use this DLL to do the same from Powershell


Powershell


The first step is to make the DLL methods available in Powershell

[Reflection.Assembly]::LoadFile("C:\SOMEPATH\ITtelligence.Email\bin\Debug\ITtelligence.Email.dll")


One of the parameters that my DLL accepts is a list collection of string. To be able to pass this to the .NET DLL, first we create a string array

[string[]]$toEmailAddressesArray = "shaun.vermaak@ittelligence.com","someoneelse@ittelligence.com";


Once we have the string array we can cast it as a list collection type string

[Collections.Generic.List[String]]$toEmailAddressesList = $toEmailAddressesArray;


To make it easier to manage errors, the Send method returns a main result of type boolean based on the overall result and 

detailed error as a reference variable.

$ReturnMessage = "";


This is the .NET Send method definition

public static bool Send(List<string> MailAddresses, string Host, int Port, bool SSL, int Timeout, string Domain, string UserName, string Password, string From, string Subject, string Title, string Body, string LogoImage, string BackgroundImage, out string Ret


Based on the definition above, here's an example of calling the Send method. The LogoImage and BackgroundImage can be physical locations to images or a base64 string using a service like https://www.base64-image.de/

[ITtelligence.EMail]::Send($mailAddresses, "in-v3.mailjet.com", 587, $true, 60000, "", "REMOVED", "REMOVED", "shaun.vermaak@ittelligence.com", "Sample Subject", "Sample Title", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", "c:\temp\ACME.png", "c:\Temp\Tile002.jpg",[ref] $ReturnMessage)


For reference, here's the full script

[Reflection.Assembly]::LoadFile("C:\SOMEPATH\ITtelligence.Email\bin\Debug\ITtelligence.Email.dll")

[string[]]$toEmailAddressesArray = "shaun.vermaak@ittelligence.com","someoneelse@ittelligence.com";

[Collections.Generic.List[String]]$toEmailAddressesList = $toEmailAddressesArray;

$ReturnMessage = "";

[ITtelligence.EMail]::Send($mailAddresses, "in-v3.mailjet.com", 587, $true, 60000, "", "REMOVED", "REMOVED", "someone@ittelligence.com", "Sample Subject", "Sample Title", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", "c:\temp\ACME.png", "c:\Temp\Tile002.jpg",[ref] $ReturnMessage)


.NET DLL Source Code


If you are interested in the DLL source code, you can find it below or via this repo

https://github.com/svermaak/ITtelligence.Emailhttps://github.com/svermaak/ITtelligence.Email


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Mail;
using System.Net.Mime;
using System.Text;
using System.Threading.Tasks;
using static System.Net.Mime.MediaTypeNames;

namespace ITtelligence
{
    public class EMail
    {
        public static bool Send(List<string> MailAddresses, string Host, int Port, bool SSL, int Timeout, string Domain, string UserName, string Password, string From, string Subject, string Title, string Body, string LogoImage, string BackgroundImage, out string ReturnMessage)
        {
            try
            {
                SmtpClient client = new SmtpClient();
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                client.Host = Host;
                client.Port = Port;
                client.EnableSsl = SSL;
                client.Timeout = Timeout;


                if ((!string.IsNullOrEmpty(Domain)) && (!string.IsNullOrEmpty(UserName)) && (!string.IsNullOrEmpty(Password)))
                {
                    client.UseDefaultCredentials = false;
                    client.Credentials = new System.Net.NetworkCredential(UserName, Password, Domain);
                }
                else if ((!string.IsNullOrEmpty(UserName)) && (!string.IsNullOrEmpty(Password)))
                {
                    client.UseDefaultCredentials = false;
                    client.Credentials = new System.Net.NetworkCredential(UserName, Password);
                }
                else
                {
                    client.UseDefaultCredentials = false;
                }

                MailMessage mail = new MailMessage();

                mail.From = new MailAddress(From);
                foreach (string mailAddress in MailAddresses.Distinct().ToArray())
                {
                    if (!string.IsNullOrEmpty(mailAddress))
                    {
                        mail.To.Add(new MailAddress(mailAddress)); ;
                    }
                }

                // If file doesn't exist, perhaps it is base64 image?
                if (!File.Exists(LogoImage))
                {
                    LogoImage = LoadBase64ImageIntoTEMP(LogoImage);
                }
                if (!File.Exists(BackgroundImage))
                {
                    BackgroundImage = LoadBase64ImageIntoTEMP(BackgroundImage);
                }

                // Alternate View HTML version
                LinkedResource logoLinkedResource = new LinkedResource(LogoImage);
                LinkedResource backgroundLinkedResource = new LinkedResource(BackgroundImage);
                logoLinkedResource.ContentId = Guid.NewGuid().ToString();
                backgroundLinkedResource.ContentId = Guid.NewGuid().ToString();
                string avHtmlBody = $"<html><head></head><body style='background-image: url(\"cid:{backgroundLinkedResource.ContentId}\");background-repeat: repeat;'><center><img src=\"cid:{logoLinkedResource.ContentId}\"></center><h1>{Title}</h1>{Body}</body></html>";
                AlternateView avHtml = AlternateView.CreateAlternateViewFromString(avHtmlBody, null, MediaTypeNames.Text.Html);
                avHtml.LinkedResources.Add(logoLinkedResource);
                avHtml.LinkedResources.Add(backgroundLinkedResource);
                mail.AlternateViews.Add(avHtml);

                // HTML version
                Attachment backgroundAttachment = new Attachment(BackgroundImage);
                Attachment logoAttachment = new Attachment(LogoImage);
                string htmlBody = $"<html><head></head><body style='background-image: url(\"{backgroundAttachment.Name}\");background-repeat: repeat;'><center><img src=\"cid:{logoAttachment.Name}\"></center><h1>{Title}</h1>{Body}</body></html>";
                mail.Body = htmlBody;
                mail.IsBodyHtml = true;
                mail.Attachments.Add(logoAttachment);
                mail.Attachments.Add(backgroundAttachment);

                mail.Subject = Subject;
                client.Send(mail);
                ReturnMessage = "Send";

                return true;
            }
            catch (Exception ex)
            {
                ReturnMessage = ex.Message;
                Console.WriteLine(ex.Message);
                return false;
            }
        }
        private static string LoadBase64ImageIntoTEMP(string Base64String)
        {
            try
            {
                byte[] bytes = Convert.FromBase64String(Base64String);

                System.Drawing.Image image;
                using (MemoryStream ms = new MemoryStream(bytes))
                {
                    string temporaryFileName = "";

                    temporaryFileName = Path.Combine(Path.GetTempPath(), System.Guid.NewGuid().ToString() + ".jpg");
                    image = System.Drawing.Image.FromStream(ms);
                    image.Save(temporaryFileName, System.Drawing.Imaging.ImageFormat.Jpeg);

                    return temporaryFileName;
                }
            }
            catch
            {
               
            }
            return null;
        }
    }
}


Conclusion

 

I hope you found this tutorial useful. You are encouraged to ask questions, report any bugs or make any other comments about it below. 

 

Note: If you need further "Support" about this topic, please consider using the Ask a Question feature of Experts Exchange. I monitor questions asked and would be pleased to provide any additional support required in questions asked in this manner, along with other EE experts...  

 

Please do not forget to press the "Thumbs Up" button if you think this article was helpful and valuable for EE members.

 

It also provides me with positive feedback. Thank you!

 

1
1,789 Views
Shaun VermaakCOG Lead Engineer
CERTIFIED EXPERT
My name is Shaun Vermaak and I have always been fascinated with technology and how we use it to enhance our lives and business.

Comments (0)

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.