Sending email with embedded image

There are 3 ways of embedding images inside email message:

  • Embedding image using multipart/related MIME object
  • Referencing remote web server (requires image maintenance for a long time)
  • Using BASE64 encoded inline images (not supported by many email clients)

In this article we’ll show how to use the first method. This method makes message bigger, but images don’t need to be stored on your web server. Furthermore this method is widely supported by email clients.

How this works

When MIME tree is build we specify that images added are in relation to HTML content of the message. We also specify content disposition as inline. This means that those images are not actual attachments, but rather should be displayed to user when he/she opens the message.

In Mail.dll it is quite simple as we just need to add the image to MailBuilder.Visualscollection using AddVisual method. Remember that you need to set the image’s Content-ID, as it is required in the next step.

HTML body of the message references those images by using special "cid:" protocol. It specifies Content-ID of the image that should be used:

This is our <strong>brand new</strong> logo: <br />
<img src="cid:logo@example.com" />

Create HTML message using MailBuilder

// Use builder class to create an email
MailBuilder builder = new MailBuilder();

// Set From, To
builder.From.Add(new MailBox("alice@mail.com", "Alice"));
builder.To.Add(new MailBox("bob@mail.com", "Bob"));
builder.Subject = "Test";

// Set HTML content (Notice the src="cid:..." attribute)
builder.Html = @"<html><body><img src=""cid:logo@example.com"" /></body></html>";

// Html automatically extracts plaint text from html so,
// unless you want to specify plain text explicitly, you don't need to use this line:
builder.Text = "This is text version of the message.";

// Add image and set its Content-Id
MimeData visual = builder.AddVisual(@"c:\image.jpg");
visual.ContentId = "logo@example.com";

IMail email = builder.Create();

And of course the VB.NET version of the same code:

' Use builder class to create an email
Dim builder As New MailBuilder()

' Set From, To
builder.From.Add(New MailBox("alice@mail.com", "Alice"))
builder.To.Add(New MailBox("bob@mail.com", "Bob"))
builder.Subject = "Test"

' Set HTML content (Notice the src="cid:..." attribute)
builder.Html = "<html><body><img src=""cid:logo@example.com"" /></body></html>"

' Html automatically extracts plaint text from html so,
' unless you want to specify plain text explicitly, you don't need to use this line:
builder.Text = "This is text version of the message."

' Add image and set its Content-Id
Dim visual As MimeData = builder.AddVisual("c:\image.jpg")
visual.ContentId = "logo@example.com"

Dim email As IMail = builder.Create()

HTML message using fluent interface

// C#

using Fluent = Limilabs.Mail.Fluent;

IMail email = Fluent.Mail.Html(@"<html><body><img src=""cid:logo@example.com"" /></body></html>")
        .From(new MailBox("alice@mail.com", "Alice"))
        .To(new MailBox("bob@mail.com", "Bob"))
        .Subject("Test")
        .AddVisual(@"c:\image.jpg")
        .SetContentId("logo@example.com")
        .Create();

And of course the VB.NET version using fluent interface:

' VB.NET

IMail email = Mail.Html("<html><body><img src=""cid:logo@example.com"" /></body></html>") _
	.From(New MailBox("alice@mail.com", "Alice")) _
	.To(New MailBox("bob@mail.com", "Bob")) _
	.Subject("Test").AddVisual("c:\image.jpg") _
	.SetContentId("logo@example.com") _
	.Create()

Sending email using SMTP

Now we can connect to SMTP server and send the HTML email with embedded image we recently created:

using (Smtp client = new Smtp())
{
    client.Connect("smtp.example.com"); // or ConnectSSL
    client.UseBestLogin("user", "password");
    client.SendMessage(email);
    client.Close();
}

You can download Mail.dll email client here.

Tags:    

Questions?

Consider using our Q&A forum for asking questions.

6 Responses to “Sending email with embedded image”

  1. Farooq Says:

    Hi,

    I have done the major part of reading emails, manipulating emails and so on. I wanted to forward the email to another address. That works fine for Gmail but when I try to deploy it to my server it is giving me 5.5.4 Invalid Address error. Do you have any idea, how can I correct it?

    Regards,
    Farooq

  2. Limilabs support Says:

    What is the stack-trace of the error?

    However unlikely your smtp server might block your connection because you provided incorrect EHLO/HELO domain parameter (check out the Exchange article: http://support.microsoft.com/kb/291828).

    Please try providing correct domain or use parameterless Ehlo method that uses your machine’s IP address.

    Edit:
    Mail.dll now issues correct EHLO/HELO automatically.

  3. Julian Says:

    Is it possible to embed multiple images? I am pulling images (files name) from sql.
    IMail email = Mail.Html(“”) _

  4. Limilabs support Says:

    @Julian,

    Of course, just add visual elements several times:

    IMail email = Fluent.Mail.Html(@"...")
        .AddVisual(@"c:\image1.jpg")
        .SetContentId("logo1@example.com")
        .AddVisual(@"c:\image2.jpg")
        .SetContentId("logo2@example.com")
        .Create()
    
    ...
    MimeData visual1 = builder.AddVisual(@"c:\image1.jpg");
    visual1.ContentId = "image1";
    
    MimeData visual2 = builder.AddVisual(@"c:\image2.jpg");
    visual2.ContentId = "image2";
    

    Remember to use different content ids.

  5. Andrzej Says:

    How to embed many pictures from database with IMail class?
    The following code works with MailMessage class. How to modify it to work with IMail?

    MailMessage msg = new MailMessage();
       
    foreach (DataRow row in dt.Rows)
    {
        byte[] image = (byte[])row["Data"];
        LinkedResource picture = new LinkedResource(new MemoryStream(image), "image/jpg");
        string conetntId = (string)row2["Name"];
        picture.ContentId = conetntId;
        htmlView.LinkedResources.Add(logo);
    }
    
    msg.AlternateViews.Add(htmlView);
    
  6. Limilabs support Says:

    @Andrzej

    You just need to set Html property and use AddVisual method (if you want to reference those images from html content):

    MailBuilder builder = new MailBuilder();
    builder.Html = ...;
    ...
    foreach(...)
    {
        byte[] imageData = ...;
        string contentId = ...;
        MimeData visual = builder.AddVisual(imageData);
        visual.ContentType = ContentType.ImageJpeg;
        visual.ContentId = contentId;
    }
    

    If you want to add those images as regular attachments use AddAttachment method.