Jun 11
27
C# Email Client With Embedded Images
Introduction
Sending and receiving emails in C# is quite easy for plain text emails but handling embedded images can be a little tricky. In this post I will not go into the basics of sending and receiving emails but deal with displaying and sending embedded images. This post does not claim to be the best way to approach handling embedded email images but does work for both displaying and sending emails.
Getting Started
This post assumes that you have knowledge of using the webbrowser component to edit and display HTML and sending and receiving emails.
Displaying Embedded Images In Emails
To display images in an email using the webbrowser component, first download the email and save the attachments to a directory with temporary file names (use a GUID). Create a class and a collection to store this information such as:
public class Attachment
{
public long ID { get; set; }
public long EmailID { get; set; }
public bool IsInbox { get; set; }
public string FileName { get; set; }
public string TmpFileName { get; set; }
public byte[] Data { get; set; }
}
The ID and EmailID fields are used by my email client I have developed and are the identity fields in the database. IsInbox is a just to distinguish between inbox and sent items in the database.
So all that has to be done is change the src attribute value of the img tag in the email HTML. This is quite easy and I use a function like this:
private string DisplayImages(string html)
{
string rval = string.Empty;
string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Email Database");
for (int i = 0; i < html.Length - 1; i++)
{
// Advance to the first html tag.
while (html[i] != '<' && i < html.Length - 1) { rval += html[i]; i++; }
if (i < html.Length - 1) { rval += html[i]; i++; }
// Advance any empty spaces.
while (html[i] == ' ' && i < html.Length - 1) { rval += html[i]; i++; }
// Get the name of the html tag.
string tagname = string.Empty;
while (html[i] != ' ' && html[i] != '>' && html[i] != '/' && i < html.Length - 1)
{
rval += html[i];
tagname += html[i];
i++;
}
// Advance any empty spaces.
while (html[i] == ' ' && i < html.Length - 1) { rval += html[i]; i++; }
// Found an img tag.
if (tagname.ToLower() == "img")
{
// Advance to the src attribute.
while (html.Substring(i, 3).ToLower() != "src") { rval += html[i]; i++; }
// Advance to the value of the src attribute.
while (html[i] != '"' && html[i] != ''') { rval += html[i]; i++; }
if (i < html.Length - 1) { rval += html[i]; i++; }
// Remeber where the start of the src value is.
int srcValueStart = i;
while (html[i] != '"' && html[i] != ''') i++;
if (i < html.Length - 1) i++;
int srcValueEnd = i;
string srcValue = html.Substring(srcValueStart, (srcValueEnd - srcValueStart) - 1);
if (srcValue.ToLower().Contains("cid:") == true)
{
string[] split1 = srcValue.Split(new char[] { ':' });
string[] split2 = split1[1].Split(new char[] { '@' });
string fn = split2[0];
foreach (Attachment a in attach)
{
if (a.FileName.ToLower() == a.FileName.ToLower())
{
rval += "file://" + Path.Combine(path, a.TmpFileName) + """;
}
}
}
}
else rval += html[i];
}
return rval;
}
All this function does is look for img tags and change the src attribute value to the location where the image file was saved on the hard drive.
Sending Embedded Images In Emails
To send emails with embedded images the process has to be reversed with a couple of extra steps such as setting up an alternate view and adding linked resources to the message. The following function will change the src attribute value in the img tags of the email to the id of the linked resource and set up the alternate view.
private AlternateView EmbedImages(string html)
{
ArrayList al = new ArrayList();
string rval = string.Empty;
string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Email Database");
for (int i = 0; i < html.Length - 1; i++)
{
// Advance to the first html tag.
while (html[i] != '<' && i < html.Length - 1) { rval += html[i]; i++; }
if (i < html.Length - 1) { rval += html[i]; i++; }
// Advance any empty spaces.
while (html[i] == ' ' && i < html.Length - 1) { rval += html[i]; i++; }
// Get the name of the html tag.
string tagname = string.Empty;
while (html[i] != ' ' && html[i] != '>' && html[i] != '/' && i < html.Length - 1)
{
rval += html[i];
tagname += html[i];
i++;
}
// Advance any empty spaces.
while (html[i] == ' ' && i < html.Length - 1) { rval += html[i]; i++; }
// Found an img tag.
if (tagname.ToLower() == "img")
{
// Advance to the src attribute.
while (html.Substring(i, 3).ToLower() != "src") { rval += html[i]; i++; }
// Advance to the value of the src attribute.
while (html[i] != '"' && html[i] != ''') { rval += html[i]; i++; }
if (i < html.Length - 1) { i++; }
// Remeber where the start of the src value is.
int srcValueStart = i;
while (html[i] != '"' && html[i] != ''') i++;
if (i < html.Length - 1) i++;
int srcValueEnd = i;
string srcValue = html.Substring(srcValueStart, (srcValueEnd - srcValueStart) - 1);
if (srcValue.ToLower().Contains("file:") == true) srcValue = srcValue.Substring(srcValue.ToLower().IndexOf("file:") + 5, srcValue.Length - 5);
int slashcnt = 0;
while(srcValue[slashcnt] == '/') slashcnt++;
srcValue = srcValue.Substring(slashcnt, srcValue.Length - slashcnt);
string sfile = Path.GetFileName(srcValue);
foreach (Attachment a in attach)
{
if (a.TmpFileName == sfile)
{
// Create a linked resource with a guid as the id.
LinkedResource lr = new LinkedResource(Path.Combine(path, a.TmpFileName));
lr.ContentId = Guid.NewGuid().ToString();
// Add the alternate view to the temp collection.
al.Add(lr);
// Set the new source in the email html.
rval += ""cid:" + lr.ContentId + """;
// Do not advance the index in the for statement.
i--;
}
}
}
else rval += html[i];
}
// Create an alternate view for the email.
AlternateView av = AlternateView.CreateAlternateViewFromString(rval, null, "text/html");
// Add the linked resources to the alternate view.
foreach (LinkedResource lr in al) av.LinkedResources.Add(lr);
return av;
}
This function will return an alternate view that can be added to the mail message and sent. The embedded images are visible in Outlook, KMail, GMail to name a few.
