Embed images in a mail message using C#
filed in Asp.net, C# on Feb.21, 2008
I was recently writing a webapplication for one of our clients. The application is a training management tool and thus involves sending loads of e-mail. This way people get reminded that they’ll be following a training in the next days or asked to write a review about their training. To make the mail look great, we wanted it to be in HTML and contain the company logo.
A first attempt was made by just writing the html for the mail and use an ordinary image-tag with a reference to the client’s intranet (like this: <img src=”http://intranet.client.com/logo.gif”/>). However, the kick-ass intranet-security of our client wouldn’t allow this and each time the mail was opened, the user was prompted for his credentials. Very annoying! So we had to include the image in the mail as an attachment. You see it every day, but apparently the code to do this in c# isn’t that widely spread. So here’s my function to accomplish it:
/// <summary>
/// Embeds the company logo into the given mail message
/// </summary>
/// <param name="message">Message in which the logo should be embedded</param>
private static void EmbedCompanyLogo(MailMessage message)
{
AlternateView av1 = AlternateView.CreateAlternateViewFromString(message.Body, null, System.Net.Mime.MediaTypeNames.Text.Html);
string strImageUrl = System.Web.HttpContext.Current.Server.MapPath("~/images/logo_print.gif");
LinkedResource logo = new LinkedResource(strImageUrl, System.Net.Mime.MediaTypeNames.Image.Jpeg);
logo.ContentId = "companylogo";
//To refer to this image in the html body, use <img src="cid:companylogo"/>
av1.LinkedResources.Add(logo);
message.AlternateViews.Add(av1);
}
As mentioned in the code comment, in your mail message you can refer to the image with a source equal to “cid:companylogo”.
If you have any thoughts, remarks or questions, the comments are open…
March 15th, 2008 on 16:19
[...] log.itto.be » Blog Archive » Embed images in a mail message using C# (tags: itto c# mail development asp.net image attachment) [...]
January 3rd, 2009 on 9:23
Tank u… It s working… fine
February 4th, 2009 on 17:11
Hi, inspired by this sample, i have created a class that provide a dynamic replace for all image tag embedded in html body.
i hope that help sommebody.
PS: sorry for my english
using System;
using System.Xml;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net.Mail;
using System.Net.Mime;
namespace MyNameSpace
{
public class Mailer
{
#region Constructeurs
public Mailer()
{
}
public Mailer(string sSmtp, string sFrom, string sTo, string sSubject, string sBodyText, string sBodyHtml)
{
this.Smtp = sSmtp;
this.From = sFrom;
this.To = sTo;
this.Subject = sSubject;
this.BodyText = sBodyText;
this.BodyHtml = sBodyHtml;
}
#endregion
MailMessage Message = new MailMessage();
SmtpClient SmtpMail = new SmtpClient();
#region Champs publics
string _sSmtp;
///
/// Serveur smtp
///
public string Smtp
{
get { return _sSmtp; }
set { _sSmtp = value; }
}
string _sFrom;
///
/// Adresse d’envoi
///
public string From
{
get { return _sFrom; }
set { _sFrom = value; }
}
string _sTo;
///
/// Destinataire du mail
///
public string To
{
get { return _sTo; }
set { _sTo = value; }
}
string _sSubject;
///
/// Sujet du mail
///
public string Subject
{
get { return _sSubject; }
set { _sSubject = value; }
}
string _sBodyText;
///
/// Mail text body
///
public string BodyText
{
get { return _sBodyText; }
set { _sBodyText = value; }
}
string _sBodyHtml;
///
/// Mail html body
///
public string BodyHtml
{
get { return _sBodyHtml; }
set { _sBodyHtml = value; }
}
#endregion
///
/// Envoi un mail alternatif, texte et html combinés
///
public void SendAlternateMail()
{
this.Message.From = new MailAddress(this.From);
this.Message.Sender = new MailAddress(this.From);
this.Message.To.Add(this.To);
this.Message.Subject = this.Subject;
//– Alternative Message Text/Plain–//
AlternateView alternateText = AlternateView.CreateAlternateViewFromString(this.BodyText, System.Text.Encoding.UTF8, MediaTypeNames.Text.Plain);
this.Message.AlternateViews.Add(alternateText);
//– Alternative Message Text/Html–//
AlternateView alternateHtml = GetAlternateViewLinkedResources(this.BodyHtml);
this.Message.AlternateViews.Add(alternateHtml);
this.SmtpMail.Host = this.Smtp;
this.SmtpMail.Send(this.Message);
}
///
/// Envoi un mail texte
///
public void SendTextMail()
{
this.Message.From = new MailAddress(this.From);
this.Message.Sender = new MailAddress(this.From);
this.Message.To.Add(this.To);
this.Message.Subject = this.Subject;
//– Message Text/Plain–//
AlternateView alternateText = AlternateView.CreateAlternateViewFromString(this.BodyText, System.Text.Encoding.UTF8, MediaTypeNames.Text.Plain);
this.Message.AlternateViews.Add(alternateText);
this.SmtpMail.Host = this.Smtp;
this.SmtpMail.Send(this.Message);
}
///
/// Envoi un mail HTML
///
public void SendHtmlMail()
{
this.Message.From = new MailAddress(this.From);
this.Message.Sender = new MailAddress(this.From);
this.Message.To.Add(this.To);
this.Message.Subject = this.Subject;
//– Message Text/Html–//
AlternateView alternateHtml = GetAlternateViewLinkedResources(this.BodyHtml);
this.Message.AlternateViews.Add(alternateHtml);
this.SmtpMail.Host = this.Smtp;
this.SmtpMail.Send(this.Message);
}
///
/// Return AlternateView object with Linked resources
///
///
///
private AlternateView GetAlternateViewLinkedResources(string sHtmlMessage)
{
XmlDocument oXml = new XmlDocument();
//Return the resources XML datas
oXml = EmbedHtmlImage(sHtmlMessage);
//Make the replace un html body
foreach (XmlNode oNode in oXml.SelectNodes(”/root/image”))
{
sHtmlMessage = sHtmlMessage.Replace(oNode.Attributes.GetNamedItem(”src”).Value.ToString(), oNode.Attributes.GetNamedItem(”srccid”).Value.ToString());
}
AlternateView oAlternateHtml = AlternateView.CreateAlternateViewFromString(sHtmlMessage, System.Text.Encoding.UTF8, MediaTypeNames.Text.Html);
//Add linked resources
foreach (XmlNode oNode in oXml.SelectNodes(”/root/image”))
{
LinkedResource oResource = null;//new LinkedResource(oNode.Attributes.GetNamedItem(”src”).Value.ToString());
sHtmlMessage = sHtmlMessage.Replace(oNode.Attributes.GetNamedItem(”src”).Value.ToString(), oNode.Attributes.GetNamedItem(”srccid”).Value.ToString());
switch(oNode.Attributes.GetNamedItem(”imagetype”).Value.ToString())
{
case “gif”:
oResource = new LinkedResource(System.Web.HttpContext.Current.Server.MapPath(oNode.Attributes.GetNamedItem(”src”).Value.ToString()), System.Net.Mime.MediaTypeNames.Image.Gif);
break;
case “jpg”:
oResource = new LinkedResource(System.Web.HttpContext.Current.Server.MapPath(oNode.Attributes.GetNamedItem(”src”).Value.ToString()), System.Net.Mime.MediaTypeNames.Image.Jpeg);
break;
case “tiff”:
oResource = new LinkedResource(System.Web.HttpContext.Current.Server.MapPath(oNode.Attributes.GetNamedItem(”src”).Value.ToString()), System.Net.Mime.MediaTypeNames.Image.Tiff);
break;
}
oResource.ContentId = oNode.Attributes.GetNamedItem(”uid”).Value.ToString();
//To refer to this image in the html body, use
oAlternateHtml.LinkedResources.Add(oResource);
}
return oAlternateHtml;
}
private XmlDocument EmbedHtmlImage(string sHtmlBody)
{
string sNewHtmlBody = sHtmlBody;
string sNewGuid = string.Empty;
string sSrcAttribute = string.Empty;
//Detect if email contain image html tag, i have choose to use XmlDocument for my convenience
XmlDocument oXml = new XmlDocument();
oXml.LoadXml(@”");
Int32 iStartImageTag = sNewHtmlBody.IndexOf(”", iEndImageSrcAttribute);
XmlNode oNode;
XmlAttribute oAtt;
if (CheckExtension(sNewHtmlBody, iStartImageSrcAttribute + 5, (iEndImageSrcAttribute - (iStartImageSrcAttribute + 5))))
{
sSrcAttribute = sNewHtmlBody.Substring(iStartImageSrcAttribute + 5, (iEndImageSrcAttribute - (iStartImageSrcAttribute + 5)));
oNode = oXml.CreateNode(XmlNodeType.Element, “image”, “”);
oAtt = oXml.CreateAttribute(”fulltag”);
oAtt.Value = sNewHtmlBody.Substring(iStartImageTag, (iEndImageTag - iStartImageTag) + 1);
oNode.Attributes.Append(oAtt);
oAtt = oXml.CreateAttribute(”src”);
oAtt.Value = sSrcAttribute;
oNode.Attributes.Append(oAtt);
sNewGuid = Guid.NewGuid().ToString();
oAtt = oXml.CreateAttribute(”uid”);
oAtt.Value = sNewGuid;
oNode.Attributes.Append(oAtt);
oAtt = oXml.CreateAttribute(”srccid”);
oAtt.Value = “cid:” + sNewGuid;
oNode.Attributes.Append(oAtt);
oAtt = oXml.CreateAttribute(”imagetype”);
if (sSrcAttribute.ToLower().EndsWith(”jpg”))
{
oAtt.Value = “jpg”;
}
if (sSrcAttribute.ToLower().EndsWith(”gif”))
{
oAtt.Value = “gif”;
}
if (sSrcAttribute.ToLower().EndsWith(”tiff”))
{
oAtt.Value = “tiff”;
}
oNode.Attributes.Append(oAtt);
//Add xml node to root
oXml.SelectSingleNode(”/root”).AppendChild(oNode);
}
while (iStartImageTag < sNewHtmlBody.LastIndexOf(@”<img”))
{
iStartImageTag = sNewHtmlBody.IndexOf(”", iEndImageSrcAttribute);
//Evite les doublons
XmlNode oExistNode = oXml.SelectSingleNode(@”/root/image[@src = '" + sNewHtmlBody.Substring(iStartImageSrcAttribute + 5, (iEndImageSrcAttribute - (iStartImageSrcAttribute + 5))) + @"']“);
if (oExistNode == null)
{
if (CheckExtension(sNewHtmlBody, iStartImageSrcAttribute + 5, (iEndImageSrcAttribute - (iStartImageSrcAttribute + 5))))
{
sSrcAttribute = sNewHtmlBody.Substring(iStartImageSrcAttribute + 5, (iEndImageSrcAttribute - (iStartImageSrcAttribute + 5)));
oNode = oXml.CreateNode(XmlNodeType.Element, “image”, “”);
oAtt = oXml.CreateAttribute(”fulltag”);
oAtt.Value = sNewHtmlBody.Substring(iStartImageTag, (iEndImageTag - iStartImageTag) + 1);
oNode.Attributes.Append(oAtt);
oAtt = oXml.CreateAttribute(”src”);
oAtt.Value = sSrcAttribute;
oNode.Attributes.Append(oAtt);
//Generation du Guid
sNewGuid = Guid.NewGuid().ToString();
oAtt = oXml.CreateAttribute(”uid”);
oAtt.Value = sNewGuid;
oNode.Attributes.Append(oAtt);
oAtt = oXml.CreateAttribute(”srccid”);
oAtt.Value = “cid:” + sNewGuid;
oNode.Attributes.Append(oAtt);
oAtt = oXml.CreateAttribute(”imagetype”);
if(sSrcAttribute.ToLower().EndsWith(”jpg”))
{
oAtt.Value = “jpg”;
}
if (sSrcAttribute.ToLower().EndsWith(”gif”))
{
oAtt.Value = “gif”;
}
if (sSrcAttribute.ToLower().EndsWith(”tiff”))
{
oAtt.Value = “tiff”;
}
oNode.Attributes.Append(oAtt);
//Add xml node to root
oXml.SelectSingleNode(”/root”).AppendChild(oNode);
}
}
}
return oXml;
}
private Boolean CheckExtension(string sNewHtmlBody, Int32 iBegin, Int32 iLength)
{
Boolean bRes = false;
bRes = (sNewHtmlBody.Substring(iBegin, iLength).ToLower().EndsWith(”.gif”)) ? true : bRes;
bRes = (sNewHtmlBody.Substring(iBegin, iLength).ToLower().EndsWith(”.jpg”)) ? true : bRes;
bRes = (sNewHtmlBody.Substring(iBegin, iLength).ToLower().EndsWith(”.tiff”)) ? true : bRes;
return bRes;
}
}
}
March 10th, 2009 on 20:14
Great info. I first looked at your sample code because who really reads instructions - simple and to the point for exactly what I needed to accomplish. Especially since msdn was utterly helpless on this topic.
Thanks!
February 13th, 2010 on 2:11
Interesting code, but it does not compile. The variables iEndImageSrcAttribute, iStartImageSrcAttribute, and iEndImageTag are not defined. They are referenced but never initialized or have a value set.
I’m interested in seeing the complete solution if Bosshog can post the fix.
June 9th, 2010 on 11:58
Omg … super!!
thx kristof
October 19th, 2010 on 22:03
Hi,
I am also interested in how to set the variables, could you please send me information?
November 4th, 2010 on 15:35
Very helpfull. To prevent a 10 min of worries, you should lose one space in the comment “//To refer to this image in the html body, use ” . It should be “… ” . In Outlook 2007 and hotmail the space a part of the ContentId.
Thanks alot!!!
November 4th, 2010 on 16:02
Thank you for the feedback, I’ve changed the comment.
April 18th, 2011 on 13:54
Hi,
Thanks for the code! It works fine and I can view the images in yahoo mails. But images are not displaying in Gmail and also in my outlook.
Can anyone help me on this..?
Regards,
Moses
July 12th, 2011 on 2:05
Hey - nice blog, just looking around some blogs, seems a pretty nice platform you are using. I’m currently using Wordpress for a few of my sites but looking to change one of them over to a platform similar to yours as a trial run. Anything in particular you would recommend about it?
November 18th, 2011 on 20:19
Thank you,
Congratulations for your information!
January 5th, 2012 on 9:12
leappad explorer tablet leapfrog explorer tablet
LeapFrog will start distribution apart their different LeapPad Traveler Understanding Pill ($100). An important pills made mainly for boys and girls, any LeapPad can take lots of the technologies brought in upon very last season’s Leapster Traveler (such as an ereader that is responsible for towards tots’ figuring out thresholds, standard and then range ability as a copywriter, along with high-resolution touch-screen) and then gives exciting different capabilities as being a tilt-sensor (the same as the ipad device), an much better ereader accompanied by a aesthetic glossary and then online games inlaid with the books, a bigger (five-inch) display screen, along with built-in camera. This company posted individuals a new pills to use, watch might know about notion here.
Who will be this system manufactured for? The manufacturer shows that made possible may be for youngsters age range Check out towards 9 years previous (might end up customized for about two to three boys and girls), however a new kid could fully grasp his particular process available the software, likewise.
leapfrog explorer tablet
January 7th, 2012 on 18:06
Hello, i think that i noticed you visited my web site thus i got here to ?return the favor?.I’m trying to to find issues to improve my web site!I suppose its ok to use some of your concepts!!
January 29th, 2012 on 10:45
Really appreciate you sharing this article.Thanks Again. Fantastic.
January 31st, 2012 on 19:16
[...] http://log.itto.be/?p=486 [...]
March 14th, 2012 on 16:27
Fantastic blog article.Many thanks again. Continue writing.