February 5th, 2009 - by Golgotha

In this article you will learn how to send email using ASP.NET. Yes, there are plenty of other articles that cover sending email via .NET, but after spending a day doing research, I was amazed at how many articles failed to provide either a correct solution or a real world example. I found that many articles suggest you create your HTML email by using a string with the HTML markup in it. That’s crazy and not at all a real world solution, at least not for most situations. In this article we will look at a more realistic solution. One in which we use a regular HTML file as our template for the email. The template file will be a standard HTML file with the exception of some placeholders that we will use to populate our content and images right before we send the email. Think mail-merge in Microsoft Word. Finally, we will also learn how to send the email in such a way that if the email recipient’s mail-client can’t render HTML they will get an alternate plain text version.

Let’s start by looking at the code in its entirety; the people that just want to grab the code and use it can do so. I will then explain the code.

  1. // CREATE EMAIL
  2. // first we create a plain text version and set it to the AlternateView
  3. // then we create the HTML version
  4. MailMessage msg = new MailMessage();
  5.  
  6. msg.From = new MailAddress(TextBoxYourEmail.Text);
  7. msg.Subject = "Event: " + labelEventName.Text;
  8. msg.To.Add(TextBoxEmail1.Text);
  9.  
  10. // create a string to hold all email addresses
  11. StringBuilder sbEmailTo = new StringBuilder();
  12. sbEmailTo.Append(TextBoxEmail1.Text);
  13.  
  14. if (!String.IsNullOrEmpty(TextBoxEmail2.Text)) { msg.To.Add(TextBoxEmail2.Text); sbEmailTo.Append(", " + TextBoxEmail2.Text); }
  15. if (!String.IsNullOrEmpty(TextBoxEmail3.Text)) { msg.To.Add(TextBoxEmail3.Text); sbEmailTo.Append(", " + TextBoxEmail3.Text); }
  16. if (!String.IsNullOrEmpty(TextBoxEmail4.Text)) { msg.To.Add(TextBoxEmail4.Text); sbEmailTo.Append(", " + TextBoxEmail4.Text); }
  17. if (!String.IsNullOrEmpty(TextBoxEmail5.Text)) { msg.To.Add(TextBoxEmail5.Text); sbEmailTo.Append(", " + TextBoxEmail5.Text); }
  18.  
  19. String plainEmail = TextBoxYourName.Text + " has invited you to an event! \r\n \r\n" +
  20.     "Event Name: " + labelEventName.Text + "\n" +
  21.     "Event Date: " + eventTextBox.Text + "\n" +
  22.     "Event Description: " + labelEventDescription.Text + "\r\n \r\n" +
  23.     "Message: " + TextBoxPersonalMessage.Text;
  24.  
  25. //first we create the Plain Text part
  26. AlternateView plainView = AlternateView.CreateAlternateViewFromString(plainEmail, null, "text/plain");
  27. msg.AlternateViews.Add(plainView);
  28.  
  29. //now create the HTML version
  30. MailDefinition message = new MailDefinition();
  31. message.BodyFileName = "email.htm";
  32. message.IsBodyHtml = true;
  33. message.From = TextBoxYourEmail.Text;
  34. message.Subject = "Zoo Event: " + labelEventName.Text;
  35.  
  36. //embed images for the email
  37. EmbeddedMailObject emo = new EmbeddedMailObject();
  38. emo.Path = @"~\Images\email\hdr_roar.gif";
  39. emo.Name = "hdr";
  40.  
  41. EmbeddedMailObject emo2 = new EmbeddedMailObject();
  42. emo2.Path = @"~\Images\email\box_top.gif";
  43. emo2.Name = "box_top";
  44.  
  45. message.EmbeddedObjects.Add(emo);
  46. message.EmbeddedObjects.Add(emo2);
  47.  
  48. //Build replacement collection to replace fields in email.htm file
  49. ListDictionary replacements = new ListDictionary();
  50. replacements.Add("<%EVENTDATE%>", eventTextBox.Text);
  51. replacements.Add("<%EVENTNAME%>", labelEventName.Text);
  52. replacements.Add("<%FROMNAME%>", TextBoxYourName.Text);
  53. replacements.Add("<%EVENTDESCRIPTION%>", labelEventDescription.Text);
  54. replacements.Add("<%PERSONALMESSAGE%>", TextBoxPersonalMessage.Text);
  55.  
  56. //now create mail message using the mail definition object
  57. //the CreateMailMessage object takes a source control object as the last parameter,
  58. //if the object you are working with is webcontrol then you can just pass "this",
  59. //otherwise create a dummy control as below.
  60. MailMessage msgHtml = message.CreateMailMessage(sbEmailTo.ToString(), replacements, new LiteralControl());
  61.  
  62. AlternateView htmlView = AlternateView.CreateAlternateViewFromString(msgHtml.Body, null, “text/html”);
  63. msg.AlternateViews.Add(htmlView);
  64.  
  65. // send email now (check web.config)
  66. SmtpClient smtp = new SmtpClient();
  67. smtp.Send(msg);

The Setup

Add the System.Net.Mail namespace. The System.Net.Mail namespace contains everything we need to send email using a Simple Mail Transfer Protocol (SMTP) server for delivery.

Modify the Web.config file to include the below:

  1. <system.net>
  2.     <mailSettings>
  3.       <smtp from="admin@company.com">
  4.         <network host="localhost" port="25"  />
  5.       </smtp>
  6.     </mailSettings>
  7.   </system.net>

The kicker and not well documented part to note is the from=”admin@company.com” in the smtp tag. You can change the from address later, but the MailDefinition class needs this here.

That’s it for setup. Now let’s look at the first chunk of code.

Create The Plain Text Version

  1. MailMessage msg = new MailMessage();

The MailMessage class represents an email message that can be sent using the SmtpClient class.

  1. msg.From = new MailAddress(TextBoxYourEmail.Text);
  2. msg.Subject = "Event: " + labelEventName.Text;
  3. msg.To.Add(TextBoxEmail1.Text);

Pretty straight-forward. This just assigns the From, Subject and To properties to our mail message.

  1. // create a string to hold all email addresses
  2. StringBuilder sbEmailTo = new StringBuilder();
  3. sbEmailTo.Append(TextBoxEmail1.Text);
  4.  
  5. if (!String.IsNullOrEmpty(TextBoxEmail2.Text)) { msg.To.Add(TextBoxEmail2.Text); sbEmailTo.Append(", " + TextBoxEmail2.Text); }
  6. if (!String.IsNullOrEmpty(TextBoxEmail3.Text)) { msg.To.Add(TextBoxEmail3.Text); sbEmailTo.Append(", " + TextBoxEmail3.Text); }
  7. if (!String.IsNullOrEmpty(TextBoxEmail4.Text)) { msg.To.Add(TextBoxEmail4.Text); sbEmailTo.Append(", " + TextBoxEmail4.Text); }
  8. if (!String.IsNullOrEmpty(TextBoxEmail5.Text)) { msg.To.Add(TextBoxEmail5.Text); sbEmailTo.Append(", " + TextBoxEmail5.Text); }

In this example they have the option of sending the email to more than one recipient. So we perform a check on the four optional text-boxes to see if they have email addresses and if they are not empty then we add them to our MailMessage instance. In addition, we append them to our StringBuilder instance which we will end up using later.

  1. String plainEmail = TextBoxYourName.Text + " has invited you to an event! \r\n \r\n" +
  2.     "Event Name: " + labelEventName.Text + "\n" +
  3.     "Event Date: " + eventTextBox.Text + "\n" +
  4.     "Event Description: " + labelEventDescription.Text + "\r\n \r\n" +
  5.     "Message: " + TextBoxPersonalMessage.Text;
  6.  
  7. //first we create the Plain Text part
  8. AlternateView plainView = AlternateView.CreateAlternateViewFromString(plainEmail, null, "text/plain");
  9. msg.AlternateViews.Add(plainView);

Here we simply create a string which we’ll use as our plain-text email message. But remember, we only want to use the plain-text version of the email if their mail client does not support HTML. Therefore we use the AlternateView class and add it to our MailMessage instance. We could have chosen not to use the alternate view and just made it the body of our MailMessage instance, but not this time.

That’s it for the plain-text version, now we will handle the HTML version.

Create The HTML Version

  1. //now create the HTML version
  2. MailDefinition message = new MailDefinition();
  3. message.BodyFileName = "email.htm";
  4. message.IsBodyHtml = true;
  5. message.From = TextBoxYourEmail.Text;
  6. message.Subject = "Zoo Event: " + labelEventName.Text;

Notice we use the MailDefinition class this time and not the MailMessage class as we did with the plain-text version. That’s because it’s the MailDefinition class that allows us to to create an email from an HTML file. Notice the BodyFileName property that we have set to our “email.htm” file. This is just a regular old HTML file. Lastly, we set the IsBodyHtml property to true.

  1. //embed images for the email
  2. EmbeddedMailObject emo = new EmbeddedMailObject();
  3. emo.Path = @"~\Images\email\hdr_roar.gif";
  4. emo.Name = "hdr";
  5.  
  6. EmbeddedMailObject emo2 = new EmbeddedMailObject();
  7. emo2.Path = @"~\Images\email\box_top.gif";
  8. emo2.Name = "box_top";
  9.  
  10. message.EmbeddedObjects.Add(emo);
  11. message.EmbeddedObjects.Add(emo2);

The above code adds two images to the HTML file. The EmbeddedMailObject represents an item to embed in a mail message. Notice the Name property. This is important because in our HTML file (email.htm) we have this <img src=”cid:hdr” alt=”" /> code which is where it maps to the image. This way of adding images to our MailDefinition object will send the images with the email. If you don’t wish to send images with your email you may choose to simply add absolute paths to your images in your HTML file like normal. Just make sure the paths are absolute.

  1. //Build replacement collection to replace fields in email.htm file
  2. ListDictionary replacements = new ListDictionary();
  3. replacements.Add("<%EVENTDATE%>", eventTextBox.Text);
  4. replacements.Add("<%EVENTNAME%>", labelEventName.Text);
  5. replacements.Add("<%FROMNAME%>", TextBoxYourName.Text);
  6. replacements.Add("<%EVENTDESCRIPTION%>", labelEventDescription.Text);
  7. replacements.Add("<%PERSONALMESSAGE%>", TextBoxPersonalMessage.Text);

This is an important part. This is where we pass in fields to our HTML template. Within our HTML file we find this <%EVENTDATE%> . This is a placeholder that we use to pass in content. Pretty cool eh? Almost like a mail-merge in Word. So all the above gets mapped into our HTML template. Now we see the power of this solution. It sure beats creating a huge string. We have a regular old HTML file with the placeholders that we pass in the content. Any future changes can be done right in the HTML file. Nice…

Now the last code section:

  1. //now create mail message using the mail definition object
  2. //the CreateMailMessage object takes a source control object as the last parameter,
  3. //if the object you are working with is webcontrol then you can just pass "this",
  4. //otherwise create a dummy control as below.
  5. MailMessage msgHtml = message.CreateMailMessage(sbEmailTo.ToString(), replacements, new LiteralControl());
  6.  
  7. AlternateView htmlView = AlternateView.CreateAlternateViewFromString(msgHtml.Body, null, “text/html”);
  8. msg.AlternateViews.Add(htmlView);
  9.  
  10. // send email now (check web.config)
  11. SmtpClient smtp = new SmtpClient();
  12. smtp.Send(msg);

The CreateMailMessage method creates the email message and does the merging of our replacement list with the placeholders. We also pass in the string that we created earlier. Remember the string held all the email recipient addresses. The last parameter is looking for a control that owns the MailDefinition. We don’t have one so we just pass in a dummy control.

All that remains is to send the email message via the smtp protocol. If everything in your Web.config file is set up correctly your email should be on the way.

Be Sociable, Share!

34 Responses to “ASP.NET – Sending Email Both in HTML and Plain Text”

1 Mark

Thank you! Was looking for this exact solution.

2 Al

Very helpful thanks!
One thing tho, in the above it seems that the call to
msg = message.CreateMailMessage(..) essentially creates a new MailMessage thus wiping out the PlainText AlternateView that had been previously added to the msg.AlternateViews collection.

I adjusted for this by using message.CreateMailMessage(..) to create another MailMessage which I then use to create a html AlternateView to add to the collection.
MailMessage msgHtml = message.CreateMailMessage

AlternateView htmlView = AlternateView.CreateAlternateViewFromString(msgHtml.Body, null, “text/html”);
msg.AlternateViews.Add(htmlView);

3 Chris

I have copied your code into a page and tried to run it but I keep getting compiler errors saying
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.

Compiler Error Message: BC30451: Name ‘EVENTDATE’ is not declared.

Source Error:

Line 98: ListDictionary replacements = new ListDictionary();
Line 99: 50.
Line 100: replacements.Add(“”, eventTextBox.Text);
Line 101: 51.
Line 102: replacements.Add(“”, labelEventName.Text);

4 Alex

Thank you! This is a very helpful article and the best I’ve found so far!

I have 1 question that I can’t seem to find an answer to anywhere. I want to send an “order confirmation” email that lists out products and prices for each item a person has ordered. I have the order items and details stored in an ArrayList.

For example, if an order has 2 widgets, 1 black and 1 brown, I would want to list the following in the email:

1 black widget $20
1 brown widget $20

I can’t seem to find a way to do this other than creating a set number of fields in the html template. Do you know a way to do this dynamically so that I can display a list of 1 to n items?

Thanks in advance.

5 Al

Hey Alex,
You could create 1 field in the html template and in code iterate thru your collection and generate the html there. Then you can pass in the html string as the replacement for that field.
HTH

6 Alex

Thanks! I tried it out tonight and it worked perfectly. I pasted the section of my code below that constructs the string to replace the field in my email.html file:

string orderDetails = “”;

foreach (Piece piece in order.pieces)
{
orderDetails = orderDetails + “”;
orderDetails = orderDetails + “” + piece.quantity.ToString() + “”;
orderDetails = orderDetails + “” + piece.shape + “”;
orderDetails = orderDetails + “” + piece.chainType + “”;
orderDetails = orderDetails + “” + piece.chainLength + “”;
orderDetails = orderDetails + “” + piece.patternOne + “”;
orderDetails = orderDetails + “” + piece.patternTwo + “”;
orderDetails = orderDetails + “”;
}
orderDetails = orderDetails + “”;

7 Alex

All of the html was removed from my post above when I submitted the message, but I put in table, tr and td elements

8 San Nayak

This seems to be awesome and a clean description yet. Probably use it in one of my app and let you know how it works. Hopefully others here found it solving their problems at least.

9 B3

Great topic, and great post!

10 Sen

Is there any way to attach a MHT file instead of html?

11 Josh

Great example. But I was noticing the same issue as Al. The “MailMessage” and “MailDefinition” seem to be out of order. It would be great if you could modify the post to reflect that. I was stuck on it for quite a while

12 Golgotha

@Josh – Sorry, my bad. I missed that one. I have now updated the post.

@Al – Thanks for the heads up; much appreciated.

13 Craig

When I include the
EmbeddedMailObject the HTML message body is null.

But if I exclude it, everything works. I’ve double checked my paths.

Any Ideas? Thanks

14 Dan

Perhaps I’m trying to run when I should be walking (since I’m new to asp.net) but you say your article will explain things and I find I’m still very very confused. I think if you had included the email.htm file somewhere it would have been helpful for people like me. Maybe that’s cheating, but I”m a one man band here and don’t have a lot of time to decipher things. I do think, in concept, that your solution is a good one, I just need to figure it out.

15 Thai nisit

this article very helpful!
Thx

16 Ngocdv

This Article is very useful. I tried but only sent a blank body. Coult you tell me the reason? Thanks a lot!

17 ANUPAMA

instead of using message.BodyFileName = “email.htm” i passed html message but it shows error

18 Ngocdv

Instead of using a HTML file, i use html code with css. It’s very good. only i can’t use BodyFileName as a html file.

19 Tomas

Hi, thanks for this article, the only one I ve found by now that explains how to send html emails.

I have a same problem as ANUPAMA, it keep sending blank body, any idea why?

I checked if htlm file.exists before i load it.

Is there any catch with html file? does it have to have ?

Thanks a lot!

20 .NET Junkie

Thanks for the code and explanation. It helped me out!

21 Kjetil Myhre

Excellent walk-through! Just what I needed to keep going strong :)

22 Doris

When I include the
EmbeddedMailObject the HTML message body is null.

But if I exclude it, everything works. I’ve double checked my paths.

Any Ideas? Thanks

23 shalimar

I first thank you very much for this venture. But I would like to mention that I copied your code and tried to run it in visual studio. Mail is sending with out any content in body. I don’t know why the content is not coming.

I am very thankful if you send a downloadable copy of the working code is mailed to me.

24 lien

How do you get rid of the .dat attachment when you send mail as html? Thoughts?

25 John A Davis

Just what I needed. I was wondering about the Alerternate View stuff since I KNOW some email programs don’t display HTML

thank you!

26 Steve from MI

Unfortunately, this doesn’t work at all for me because the .CreateMailMessage is requiring a Control to find the file, but this is running in an independent thread – so I get an error indicating that the basepath cannot be null.

Isn’t there some way to give the full url to the html file instead of relying on the call to find it on its own from a control’s basepath?

27 dvn of Mass

I really enjoyed and learnt alot form your post. To epxand the topic further, i would like to know how would i implement the codes where i want to populate the content of the email dynamically when the user
1. click to open the email
or
2. click on a button inside the body of the email.
I would appreciate any comments or guide from any expert out there
Thank you and keep up the good post folks.

28 Michael

Blast. Ive been working on this for 5 hours straight now.

I get the same error as other people in this thread..

If i include the embeddedobject it just sends a blank email.

if i remove it. the email sends great. (although i neeeeeeeeed a embedded picture)

Any Ideas?

29 John A Davis

Private Sub sSendInvoiceEmail(ByVal strHTMLBody As String)

Dim avHtml As AlternateView = AlternateView.CreateAlternateViewFromString(strHTMLBody, Nothing, MediaTypeNames.Text.Html)
‘ Create a LinkedResource object for each embedded image

Dim imageResource As LinkedResource
‘For i As Integer = 0 To aPics.Count – 1
‘ newBody = newBody.Replace(imageNVC.Get(i).ToString, “cid:” & imageNVC.GetKey(i).ToString)
‘Next

‘htmlView = CreateHtmlView(newBody) ‘ text/html

For i As Integer = 0 To aPics.Count – 1

imageResource = New LinkedResource(aPics(i).ToString(), MediaTypeNames.Image.Jpeg)
imageResource.ContentId = “Pic” & (i)
‘imageResource.TransferEncoding = TransferEncoding.Base64
avHtml.LinkedResources.Add(imageResource)

Next

Dim mail As New MailMessage

mail.AlternateViews.Add(avHtml)

mail.From = New System.Net.Mail.MailAddress(txtEmailFrom.Text)
mail.To.Add(New System.Net.Mail.MailAddress(txtEmailTo.Text))
mail.Subject = txtSubject.Text.ToString()
mail.IsBodyHtml = True

mail.Body = strHTMLBody

30 Michael Tippett

is that the solution John?

any chance you know it in C#? My vb is very rusty

31 John A Davis

I don’t have time to change it to C#, but I bet you could. Just paste it into your C# code and change the object declarations, etc.
Shouldn’t really be that hard. VS will underline what is wrong. I use the code to send out 4 pictures shrunken in an email body.

32 John A Davis

I’m using an array list “aPic” that holds the picture locations. I guess this code isn’t complete. The part I gave you works, but I can’t look at the rest right now.

33 michael

Use MailMessage and SmtpClient class to build the sending mail program.
I already answered in other website. See the below link :

http://www.hyperneed.com/ShowSearchAnswers.aspx?searchstring=&category=Programming&questionid=b507b018-e456-4be6-b037-ec416c9eb712

34 Ranjithprasad

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net.Mail ;

namespace mail
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

}

protected void Button1_Click(object sender, EventArgs e)
{
MailDefinition message = new MailDefinition();
System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage();
msg.To.Add(“To_mail@gmail.com”);

msg.From = new MailAddress(“From_mail@gmail.com”, “”, System.Text.Encoding.UTF8);

msg.Subject = “That’s Your Password”;
msg.SubjectEncoding = System.Text.Encoding.UTF8;

msg.Body = “asd123y”;

msg.BodyEncoding = System.Text.Encoding.UTF8;

msg.IsBodyHtml = false;
msg.Priority = MailPriority.High;

SmtpClient client = new SmtpClient();
client.Credentials = new System.Net.NetworkCredential(“yourmail_id@gmail.com”, “your_password”);
client.Port = 587;

client.Host = “smtp.gmail.com”;
client.EnableSsl = true;

client.Send(msg);

}
}
}

Share your thoughts...

mulberry sale spyder womens jacket cheap new balance 574 mulberry outlet cheap new balance 574 arcteryx outlet mulberry sale spyder womens jacket mulberry sale spyder womens jacket mulberry outlet mulberry outlet new balance 574

Popular Articles

Top 10 Commentators


Subscribe to this feed! Subscribe by Email!

Random Bits Podcast

You need to download the Flash player from Adobe

Blogs Worth Reading