Send Mail with inline embedded images with powershell

Its been a while but here is a quick tip for embedding inline images in SMTP emails with powershell.  Outlook will see these the attachments and embed them inline with the message.

create your message:

$smtpServer = "SMTP.YourServer.com"
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)

Add your contact and subject to your message:

$msg.From = "<a href="mailto:From@YourServer.com">From@YourServer.com</a>"
$msg.ReplyTo = "<a href="mailto:From@YourServer.com">From@YourServer.com</a>"
$msg.To.Add("<a href="mailto:To@YourServer.com">To@YourServer.com</a>")
$msg.subject = "This is an email with inline images"

Makre sure the email is HTML enabled:

$msg.IsBodyHtml = $True

Add your Content to the body (note this can also be read in from an html file via get-content):

$body = @"
<html>
<body>
<img src="cid:image1.jpg">
</body>
</html>
"@

Attach the image to your email: (note setting the images as inline and media type will make sure that outlook attaches the images as embedded and the email will not show as having attachments)

$attachment = New-Object System.Net.Mail.Attachment –ArgumentList "C:\image1.jpg"
$attachment.ContentDisposition.Inline = $True
$attachment.ContentDisposition.DispositionType = "Inline"
$attachment.ContentType.MediaType = "image/jpg"
$attachment.ContentId = 'image1.jpg'
$msg.Attachments.Add($attachment)

Or for multiple images or attachments:


$path = C:\images
$files= Get-ChildItem $path

Foreach($file in $files)
{

$attachment = New-Object System.Net.Mail.Attachment –ArgumentList $Path\$file.ToString() #convert file-system object type to string
$attachment.ContentDisposition.Inline = $True
$attachment.ContentDisposition.DispositionType = "Inline"
$attachment.ContentType.MediaType = "image/jpg"
$attachment.ContentId = $file.ToString()
$msg.Attachments.Add($attachment)

}

Just make sure that in your html email to referece each file with <image src=”cid:filename.extension”>


<html>
<body>
<img src="cid:image1.jpg">
<img src="cid:image2.jpg">
<img src="cid:image3.jpg">
</body>
</html>

When done adding attachments send your message adn clean up:


$smtp.Send($msg)
$attachment.Dispose();
$msg.Dispose();

If you have inline image attachments of varying file formats you can also set the inline media type dynamically. In your attachment lool take the file type as a string and pipe it into the media type:

$fileType = $file.Substring(($file.IndexOf('.'))+1) #get image file extension
...
$attachment.MediaType = "image/$fileType" #set mediaType based on $file extension

About Dane

Currently working on scripting and IT automation. My skill set includes IDM, Active Directory and Exchange Administration, powershell scripting and more...
This entry was posted in Powershell and tagged , , , , . Bookmark the permalink.

16 Responses to Send Mail with inline embedded images with powershell

  1. Anthony says:

    Great break down of the script. I have been using it to tweak my own attempts at this. I’m only new to scripting and was hoping for a little help with a glitch or oversight on my part in using your script.
    When running at this point of code i get error:
    $attachment = New-Object System.Net.Mail.Attachment –ArgumentList $Path\$file.ToString()

    Error message:
    New-Object : A positional parameter cannot be found that accepts argument ”.
    At C:\Users\Owner\Desktop\SendEmail.ps1:53 char:15
    + $attachment = New-Object System.Net.Mail.Attachment –ArgumentList $Path\$file(“” …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [New-Object], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.NewObjectCommand

    Can you help me understand what the positional parameter it is expecting I presume it’s meant to take input from the image name but doesn’t seem to be grabbing it?

  2. Dane says:

    what version of powershell are you running?

  3. Brem says:

    This looks promising, but with PowerShell v3 I get so many errors. Here are the major ones:

    (I’ll try switching to PowerShell v2 if I can’t figure out how to adjust this for PS3/4.)

    Thanks for sharing!

    Exception setting “From”: “Cannot convert value “mailto:helpdesk@somecompany.com” to
    type “System.Net.Mail.MailAddress”. Error: “The specified string is not in the form required for an e-mail address.”"
    At D:\ad\PasswordReminder\email_embedded_files.ps1:12 char:1
    + $msg.From = “mailto:helpdesk@somecompany.com

    Method invocation failed because [System.IO.FileInfo] does not contain a method named ‘IndexOf’.
    At D:\ad\PasswordReminder\email_embedded_files.ps1:50 char:2
    + $fileType = $file.Substring(($file.IndexOf(‘.’))+1) # <– Get the file extensio …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

    New-Object : Exception calling ".ctor" with "1" argument(s): "Could not find file
    'D:\AD\PasswordReminder\images\footer.gif.ToString'."
    At D:\ad\PasswordReminder\email_embedded_files.ps1:51 char:16
    + $attachment = New-Object System.Net.Mail.Attachment –ArgumentList $Path\$file.T …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
    + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

    The property 'Inline' cannot be found on this object. Verify that the property exists and can be set.
    At D:\ad\PasswordReminder\email_embedded_files.ps1:52 char:2
    + $attachment.ContentDisposition.Inline = $True
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

    The property 'DispositionType' cannot be found on this object. Verify that the property exists and can be set.
    At D:\ad\PasswordReminder\email_embedded_files.ps1:53 char:2
    + $attachment.ContentDisposition.DispositionType = "Inline"
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

    The property 'MediaType' cannot be found on this object. Verify that the property exists and can be set.
    At D:\ad\PasswordReminder\email_embedded_files.ps1:54 char:2
    + $attachment.ContentType.MediaType = "image/$fileType"
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

    The property 'ContentId' cannot be found on this object. Verify that the property exists and can be set.
    At D:\ad\PasswordReminder\email_embedded_files.ps1:55 char:2
    + $attachment.ContentId = $file.ToString()
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

    Exception calling "Add" with "1" argument(s): "Value cannot be null.
    Parameter name: item"
    At D:\ad\PasswordReminder\email_embedded_files.ps1:56 char:2
    + $msg.Attachments.Add($attachment)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentNullException

    • Dane says:

      looks like you have issues with the code. should be an email address not mailto:user@domain.comm but just user@domain.com also looks like you have some other issues as well.

      can you maybe post the code you are using? I can take a look I’m running this in powershell 3 no problem.

      • Jonathan says:

        I got the same error as Brem. Additionally, on the line that says “$attachment = New-Object System.Net.Mail.Attachment –ArgumentList $Path\$file.ToString() #convert file-system object type to string” there is an error after ToString() that says “An expression was expected after ‘(‘.”

  4. Dan says:

    Hi,

    I modified your script a bit to work on PS v4. My Problem is that the Picture is not Embedded it just shows up like a document icon, i have to double click the icon to see the picture.

    Can you help me ? :-)

    $smtpServer = “172.0.0.1″
    $msg = new-object Net.Mail.MailMessage
    $smtp = new-object Net.Mail.SmtpClient($smtpServer)

    $msg.From = “2@2.com”
    $msg.To.Add(“2@2.com”)
    $msg.subject = “This is an email with inline images”

    $msg.IsBodyHtml = $True

    $body = @”

    “@

    $attachment = New-Object System.Net.Mail.Attachment –ArgumentList “C:\1.jpg”
    $attachment.ContentDisposition.Inline = $True
    $attachment.ContentDisposition.DispositionType = “Inline”
    $attachment.ContentType.MediaType = “image/jpg”
    $attachment.ContentId = ’1.jpg’
    $msg.Attachments.Add($attachment)

    $smtp.Send($msg)
    $attachment.Dispose();
    $msg.Dispose();

  5. Elio Fernandes says:

    Hi Dane,

    Great script and very well explained.
    I just tried to use it but the image does not go inline, it comes as an attachment. I would like you to help to see what am I doing wrong.

    #create your message:
    $smtpServer = "webmail.telecom.pt"
    $msg = new-object Net.Mail.MailMessage
    $smtp = new-object Net.Mail.SmtpClient($smtpServer)
    $smtp.Credentials = New-Object System.Net.NetworkCredential("user", "pwd");

    # Add your contact and subject to your message:
    $msg.From = "user1@server.com"
    $msg.To.Add("user2@server.com")
    $msg.subject = "This is an email with inline images"

    # Makre sure the email is HTML enabled:
    $msg.IsBodyHtml = $True

    # Attach the image to your email:
    $attachment = New-Object System.Net.Mail.Attachment –ArgumentList "C:\Logo.jpg"
    $attachment.ContentDisposition.Inline = $True
    $attachment.ContentDisposition.DispositionType = "Inline"
    $attachment.ContentType.MediaType = "image/jpg"
    $attachment.ContentId = 'Logo.jpg'
    $msg.Attachments.Add($attachment)

    # Add your Content to the body (note this can also be read in from an html file via get-content):
    $body = @"

    "@

    # When done adding attachments send your message adn clean up:
    $smtp.Send($msg)
    $attachment.Dispose();
    $msg.Dispose();

    Regards,
    Elio Fernandes

  6. Elio Fernandes says:

    Dane, I am using Outlook. About the snippit, I am not understanding what you are trying to say. Can you send me an e-mail with the code I sent and put inside the changes you are refering to.

    Regards,
    Elio Fernandes

    • Dane says:

      the real culprit is my lack of typing. HTML should be img src=… not image src=

      I corrected the typo in the original post above for future reference :)

  7. Mateja says:

    Thank you very much for very well explained code.

    I would like to point out that there is a typo, where you define $Body, it should be $msg.Body, cause as it is now, it will just send a blank email.

    Again, thanks!

    Regards,
    Mateja

  8. Dan says:

    Problem Solved.

    I added the picture with division Tag
    div id=’BottomRight’
    img src=’cid:Attachment’/
    /div

    Regards,
    Dan.

Leave a Reply to Brem Cancel reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>