Introduction
Some time ago, I had written an ASP.NET website showing some reports generated from a database. The reports contained tables, as well as dynamically generated graphs. To get a larger number of people to read the reports, it seemed like a good idea to send them as a weekly email newsletter. To be able to re-read the newsletter in a later stage, it was necessary to include the images, since they are changing over time. Embedding the images makes it also possible to send the mail to people that do not have access to the website.
This article shows a way to retrieve images from a web server and embed them into your email message.
Usage
This is how you can send a web page with the mailer class provided in this article:
Uri uri = new Uri("http://about.com/");
Fmd.Mail.WebpageMailer mailer = new Fmd.Mail.WebpageMailer();
mailer.SmtpServerName = "mail.somesmptserver.com";
mailer.Delay = 0;
mailer.MailMessage.From = new MailAddress("noreply@somedomain.com");
mailer.MailMessage.To.Add(new MailAddress("recipient@somedomain.com"));
mailer.MailMessage.Subject = "Automatic Mail Message " +
DateTime.Now.ToShortDateString();
mailer.MailMessage.Priority = MailPriority.Normal;
mailer.SendMailMessage(uri);
The main methods of the class
Sending the mail message
SendMailMessage
is the main method in the class. It retrieves the contents of the web page to be sent. Next, it retrieves the images to embed. These parts are inserted into a mail message which is sent in the end.
public void SendMailMessage(Uri uri)
{
string htmlbody = GetBody(uri);
string modifiedbody;
List<linkedResource> foundResources;
ExtractLinkedResources(uri, htmlbody, out modifiedbody,
out foundResources);
MemoryStream stream = new MemoryStream();
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(modifiedbody);
stream.Write(bytes, 0, bytes.Length);
stream.Position = 0;
_mailMessage.Body = "This is a html mail - use an" +
" email client that can read it";
AlternateView altView = new AlternateView(stream,
System.Net.Mime.MediaTypeNames.Text.Html);
foreach (LinkedResource linkedResource in foundResources)
{
altView.LinkedResources.Add(linkedResource);
}
_mailMessage.AlternateViews.Add(altView);
SmtpClient client = new SmtpClient(_smptServerName);
client.Send(_mailMessage);
}
Filling the LinkedResource
This code snippet from ExtractLinkedResources
shows how the images are embedded:
LinkedResource data = new LinkedResource(imageStream);
string generatedName = null;
if (contentType.ToLower().IndexOf("image/gif") >= 0)
{
data.ContentType.MediaType = System.Net.Mime.MediaTypeNames.Image.Gif;
generatedName = "image" + imageID.ToString() + ".gif";
}
else if (contentType.ToLower().IndexOf("image/jpeg") >= 0)
{
data.ContentType.MediaType = System.Net.Mime.MediaTypeNames.Image.Jpeg;
generatedName = "image" + imageID.ToString() + ".jpeg";
}
if (generatedName == null)
continue;
string generatedSrc = "cid:" + generatedName;
data.ContentType.Name = generatedName;
data.ContentId = generatedName;
data.ContentLink = new Uri(generatedSrc);
linkedResources.Add(data);
Getting a web page
This downloads the HTML contents:
public static string GetBody(Uri uri)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.MaximumAutomaticRedirections = 4;
request.MaximumResponseHeadersLength = 4;
request.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream receiveStream = response.GetResponseStream();
StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
string body = readStream.ReadToEnd();
readStream.Close();
response.Close();
return body;
}
Glueing everything together
To make everything work together, there are a few things that need to be tackled. Since the images may be in some virtual directory on the web server, different from the page itself, their relative paths need to be changed. The program follows these steps to get everything together:
- Read the HTML body
- Analyze the HTML body to extract what images need to be retrieved
- Download the images, and make them available as a
MemoryStream
to embed into the mail message
- Modify the HTML so the image URLs are relative to the mail message instead of being relative to the web page
- Put everything into the mail message and send it away
Final remarks
This article can do two things for you. It can get you started when you want to send web pages as an email message, and the sample code may help you when you are struggling on how to embed images into a mail message. I hope you find it useful!