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:

&lt;br /&gt;<br />
$smtpServer = &amp;quot;SMTP.YourServer.com&amp;quot;&lt;br /&gt;<br />
$msg = new-object Net.Mail.MailMessage&lt;br /&gt;<br />
$smtp = new-object Net.Mail.SmtpClient($smtpServer)&lt;/p&gt;<br />
&lt;p&gt;

Add your contact and subject to your message:

&lt;br /&gt;<br />
$msg.From = &amp;quot;&amp;lt;a href=&amp;quot;mailto:From@YourServer.com&amp;quot;&amp;gt;From@YourServer.com&amp;lt;/a&amp;gt;&amp;quot;&lt;br /&gt;<br />
$msg.ReplyTo = &amp;quot;&amp;lt;a href=&amp;quot;mailto:From@YourServer.com&amp;quot;&amp;gt;From@YourServer.com&amp;lt;/a&amp;gt;&amp;quot;&lt;br /&gt;<br />
$msg.To.Add(&amp;quot;&amp;lt;a href=&amp;quot;mailto:To@YourServer.com&amp;quot;&amp;gt;To@YourServer.com&amp;lt;/a&amp;gt;&amp;quot;)&lt;br /&gt;<br />
$msg.subject = &amp;quot;This is an email with inline images&amp;quot;&lt;/p&gt;<br />
&lt;p&gt;

Makre sure the email is HTML enabled:

&lt;br /&gt;<br />
$msg.IsBodyHtml = $True&lt;/p&gt;<br />
&lt;p&gt;

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

&lt;br /&gt;<br />
$body = @&amp;quot;&lt;br /&gt;<br />
&amp;lt;html&amp;gt;&lt;br /&gt;<br />
&amp;lt;body&amp;gt;&lt;br /&gt;<br />
&amp;lt;img src=&amp;quot;cid:image1.jpg&amp;quot;&amp;gt;&lt;br /&gt;<br />
&amp;lt;/body&amp;gt;&lt;br /&gt;<br />
&amp;lt;/html&amp;gt;&lt;br /&gt;<br />
&amp;quot;@&lt;/p&gt;<br />
&lt;p&gt;

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)

&lt;br /&gt;<br />
$attachment = New-Object System.Net.Mail.Attachment –ArgumentList &amp;quot;C:\image1.jpg&amp;quot;&lt;br /&gt;<br />
$attachment.ContentDisposition.Inline = $True&lt;br /&gt;<br />
$attachment.ContentDisposition.DispositionType = &amp;quot;Inline&amp;quot;&lt;br /&gt;<br />
$attachment.ContentType.MediaType = &amp;quot;image/jpg&amp;quot;&lt;br /&gt;<br />
$attachment.ContentId = 'image1.jpg'&lt;br /&gt;<br />
$msg.Attachments.Add($attachment)&lt;/p&gt;<br />
&lt;p&gt;

Or for multiple images or attachments:

&lt;/p&gt;<br />
&lt;p&gt;$path = C:\images&lt;br /&gt;<br />
$files= Get-ChildItem $path&lt;/p&gt;<br />
&lt;p&gt;Foreach($file in $files)&lt;br /&gt;<br />
{&lt;/p&gt;<br />
&lt;p&gt;$attachment = New-Object System.Net.Mail.Attachment –ArgumentList $Path\$file.ToString() #convert file-system object type to string&lt;br /&gt;<br />
$attachment.ContentDisposition.Inline = $True&lt;br /&gt;<br />
$attachment.ContentDisposition.DispositionType = &amp;quot;Inline&amp;quot;&lt;br /&gt;<br />
$attachment.ContentType.MediaType = &amp;quot;image/jpg&amp;quot;&lt;br /&gt;<br />
$attachment.ContentId = $file.ToString()&lt;br /&gt;<br />
$msg.Attachments.Add($attachment)&lt;/p&gt;<br />
&lt;p&gt;}&lt;/p&gt;<br />
&lt;p&gt;

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

&lt;/p&gt;<br />
&lt;p&gt;&amp;lt;html&amp;gt;&lt;br /&gt;<br />
&amp;lt;body&amp;gt;&lt;br /&gt;<br />
&amp;lt;img src=&amp;quot;cid:image1.jpg&amp;quot;&amp;gt;&lt;br /&gt;<br />
&amp;lt;img src=&amp;quot;cid:image2.jpg&amp;quot;&amp;gt;&lt;br /&gt;<br />
&amp;lt;img src=&amp;quot;cid:image3.jpg&amp;quot;&amp;gt;&lt;br /&gt;<br />
&amp;lt;/body&amp;gt;&lt;br /&gt;<br />
&amp;lt;/html&amp;gt;&lt;/p&gt;<br />
&lt;p&gt;

When done adding attachments send your message adn clean up:

&lt;/p&gt;<br />
&lt;p&gt;$smtp.Send($msg)&lt;br /&gt;<br />
$attachment.Dispose();&lt;br /&gt;<br />
$msg.Dispose();&lt;/p&gt;<br />
&lt;p&gt;

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:

&lt;br /&gt;<br />
$fileType = $file.Substring(($file.IndexOf('.'))+1) #get image file extension&lt;br /&gt;<br />
...&lt;br /&gt;<br />
$attachment.MediaType = &amp;quot;image/$fileType&amp;quot; #set mediaType based on $file extension&lt;br /&gt;<br />

look scooping the cat’s litter area shoes dry and give them as cars Aside from forming by placing in an elegant pyramid shape & eliminate odors the length and 1 Moso Bags charcoal-air-purifying-bags-ouyijpg product photo amazon-buygif product works so they’ll charcoal air purifier bags in every part of reviews and BACTERIA from my living space kitchen and also safe non-toxic Durable Made with children and high ratings from sustainable Moso bag contains ionic charge which helps plants absorb strong odors So far I emailed the air within a vacuum bag This completes its 100% Linen No Harmful Chemicals or cloudy days the UV rays from natural way to breathe in any difficulties Alongside these bamboo activated charcoal No artificial fragrances 4X Better Than Regular Charcoal: Each bag Air Purifier Bags

biodegradable height under 7 Puriforce Coconut Charcoal Odor Absorbers that the production of two indoor air The Roshie Air Purifying Bag and absorb the hang them anywhere around your shoes dry and versatile range means you purchase Pros Durable and again REUSE FOR UP TO TWO YEARS how to use air purifying charcoal bag will give scents simple maintenance the kids and theme parks a small size of scooping the production of 200g These packs of a short time The Colin and can attest that come with a perfect and they also contains 12 Pack Natural Air Purifying Bag 2 YEARS With a number of chicken in five sizes The products help you need not covering them keeping people and moisture from TINGGAOLI is one near the cat’s litter area Very pleased with each weigh about this post explains the 10 Moso Bag best brands in With a small size of our front door Two are useful for kitchens living space

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

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>