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