Scenario

Create professional looking email notifications and newsletters

Sending rich content emails in the HTML format, including their attachments and CID embedded images. The approach uses the .Net MailMessage class and conversion to a byte array for raw data submission to an email service like AWS SES or SendGrid.

PowerShell

Example Use

$logo = '<imageFile.png>'
$att1 = New-Object System.Net.Mail.Attachment($logo) 
$att1.ContentDisposition.Inline = $True 
$att1.ContentDisposition.DispositionType = "Inline" 
$att1.ContentType.MediaType = "image/png" 
$att1.ContentID = "att1"

$mailMessage = New-Object Net.Mail.MailMessage
$mailMessage.From = 'Someone<someone@domain.com>'
$mailMessage.IsBodyHtml = $true
$mailMessage.Attachments.Add($att1)

$mailMessage.Body = '<Your HTML Body>'
# href links in your body should reference your
# content ids ie. 'cid:att1' for the image attached.
$mailMessage.To.Add('recipient@targetdomain.com')
$mailMessage.Subject = 'Your subject'
                
$raw_data = ConvertTo-RawDataMailMessage($mailMessage)

# For Amazon SES
Send-SES2Email -Raw_Data $raw_data

Code

$ErrorActionPreference = 'stop'
function ConvertTo-RawDataMailMessage {
    [CmdletBinding()]
    [OutputType([Byte[]])]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipelineByPropertyName = $true,
            Position = 0)]
        [Net.Mail.MailMessage] $mailMessage
    )
    process {
        
        $assembly = [System.Net.Mail.SmtpClient].Assembly
        $mailWriterType = $assembly.GetType("System.Net.Mail.MailWriter")

        # Based upon the C# implementation
        # https://stackoverflow.com/questions/1264672/how-to-save-mailmessage-object-to-disk-as-eml-or-msg-file/70582581#70582581

        $bindingFlags = [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic
        $typeArray = ([System.Type]::GetType("System.IO.Stream"), [System.Type]::GetType("System.Boolean"))

        $mailWriterConstructor = $mailWriterType.GetConstructor($bindingFlags, $typeArray)

        $MemoryStream = New-Object -TypeName "System.IO.MemoryStream"
        [System.Array]$paramArray = ($MemoryStream)
        $paramArray += $true
        $mailWriter = $mailWriterConstructor.Invoke($paramArray)

        $messageType = $mailMessage.GetType()
        $sendMethod = $messageType.GetMethod("Send", $bindingFlags)

        [System.Array]$sendParams = ($mailWriter, $true, $true)
        $sendMethod.Invoke($mailMessage, $bindingFlags, $null, $sendParams, $null)

        $closeMethod = $mailWriter.GetType().GetMethod("Close", $bindingFlags)
        $closeMethod.Invoke($mailWriter, $bindingFlags, $null, @(), $null)

        # [System.Text.Encoding]::UTF8.GetString($MemoryStream.ToArray())
        $raw_data = $MemoryStream.ToArray()
        $MemoryStream.Dispose()
        Remove-Variable MemoryStream
        $raw_data
    }
}

Categories:

Updated: