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.
- // CREATE EMAIL
- // first we create a plain text version and set it to the AlternateView
- // then we create the HTML version
- MailMessage msg = new MailMessage();
- msg.From = new MailAddress(TextBoxYourEmail.Text);
- msg.Subject = "Event: " + labelEventName.Text;
- msg.To.Add(TextBoxEmail1.Text);
- // create a string to hold all email addresses
- StringBuilder sbEmailTo = new StringBuilder();
- sbEmailTo.Append(TextBoxEmail1.Text);
- if (!String.IsNullOrEmpty(TextBoxEmail2.Text)) { msg.To.Add(TextBoxEmail2.Text); sbEmailTo.Append(", " + TextBoxEmail2.Text); }
- if (!String.IsNullOrEmpty(TextBoxEmail3.Text)) { msg.To.Add(TextBoxEmail3.Text); sbEmailTo.Append(", " + TextBoxEmail3.Text); }
- if (!String.IsNullOrEmpty(TextBoxEmail4.Text)) { msg.To.Add(TextBoxEmail4.Text); sbEmailTo.Append(", " + TextBoxEmail4.Text); }
- if (!String.IsNullOrEmpty(TextBoxEmail5.Text)) { msg.To.Add(TextBoxEmail5.Text); sbEmailTo.Append(", " + TextBoxEmail5.Text); }
- String plainEmail = TextBoxYourName.Text + " has invited you to an event! \r\n \r\n" +
- "Event Name: " + labelEventName.Text + "\n" +
- "Event Date: " + eventTextBox.Text + "\n" +
- "Event Description: " + labelEventDescription.Text + "\r\n \r\n" +
- "Message: " + TextBoxPersonalMessage.Text;
- //first we create the Plain Text part
- AlternateView plainView = AlternateView.CreateAlternateViewFromString(plainEmail, null, "text/plain");
- msg.AlternateViews.Add(plainView);
- //now create the HTML version
- MailDefinition message = new MailDefinition();
- message.BodyFileName = "email.htm";
- message.IsBodyHtml = true;
- message.From = TextBoxYourEmail.Text;
- message.Subject = "Zoo Event: " + labelEventName.Text;
- //embed images for the email
- EmbeddedMailObject emo = new EmbeddedMailObject();
- emo.Path = @"~\Images\email\hdr_roar.gif";
- emo.Name = "hdr";
- EmbeddedMailObject emo2 = new EmbeddedMailObject();
- emo2.Path = @"~\Images\email\box_top.gif";
- emo2.Name = "box_top";
- message.EmbeddedObjects.Add(emo);
- message.EmbeddedObjects.Add(emo2);
- //Build replacement collection to replace fields in email.htm file
- ListDictionary replacements = new ListDictionary();
- replacements.Add("<%EVENTDATE%>", eventTextBox.Text);
- replacements.Add("<%EVENTNAME%>", labelEventName.Text);
- replacements.Add("<%FROMNAME%>", TextBoxYourName.Text);
- replacements.Add("<%EVENTDESCRIPTION%>", labelEventDescription.Text);
- replacements.Add("<%PERSONALMESSAGE%>", TextBoxPersonalMessage.Text);
- //now create mail message using the mail definition object
- //the CreateMailMessage object takes a source control object as the last parameter,
- //if the object you are working with is webcontrol then you can just pass "this",
- //otherwise create a dummy control as below.
- MailMessage msgHtml = message.CreateMailMessage(sbEmailTo.ToString(), replacements, new LiteralControl());
- AlternateView htmlView = AlternateView.CreateAlternateViewFromString(msgHtml.Body, null, “text/htmlâ€);
- msg.AlternateViews.Add(htmlView);
- // send email now (check web.config)
- SmtpClient smtp = new SmtpClient();
- 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:
- <system.net>
- <mailSettings>
- <smtp from="admin@company.com">
- <network host="localhost" port="25" />
- </smtp>
- </mailSettings>
- </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
- MailMessage msg = new MailMessage();
The MailMessage class represents an email message that can be sent using the SmtpClient class.
- msg.From = new MailAddress(TextBoxYourEmail.Text);
- msg.Subject = "Event: " + labelEventName.Text;
- msg.To.Add(TextBoxEmail1.Text);
Pretty straight-forward. This just assigns the From, Subject and To properties to our mail message.
- // create a string to hold all email addresses
- StringBuilder sbEmailTo = new StringBuilder();
- sbEmailTo.Append(TextBoxEmail1.Text);
- if (!String.IsNullOrEmpty(TextBoxEmail2.Text)) { msg.To.Add(TextBoxEmail2.Text); sbEmailTo.Append(", " + TextBoxEmail2.Text); }
- if (!String.IsNullOrEmpty(TextBoxEmail3.Text)) { msg.To.Add(TextBoxEmail3.Text); sbEmailTo.Append(", " + TextBoxEmail3.Text); }
- if (!String.IsNullOrEmpty(TextBoxEmail4.Text)) { msg.To.Add(TextBoxEmail4.Text); sbEmailTo.Append(", " + TextBoxEmail4.Text); }
- 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.
- String plainEmail = TextBoxYourName.Text + " has invited you to an event! \r\n \r\n" +
- "Event Name: " + labelEventName.Text + "\n" +
- "Event Date: " + eventTextBox.Text + "\n" +
- "Event Description: " + labelEventDescription.Text + "\r\n \r\n" +
- "Message: " + TextBoxPersonalMessage.Text;
- //first we create the Plain Text part
- AlternateView plainView = AlternateView.CreateAlternateViewFromString(plainEmail, null, "text/plain");
- 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
- //now create the HTML version
- MailDefinition message = new MailDefinition();
- message.BodyFileName = "email.htm";
- message.IsBodyHtml = true;
- message.From = TextBoxYourEmail.Text;
- 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.
- //embed images for the email
- EmbeddedMailObject emo = new EmbeddedMailObject();
- emo.Path = @"~\Images\email\hdr_roar.gif";
- emo.Name = "hdr";
- EmbeddedMailObject emo2 = new EmbeddedMailObject();
- emo2.Path = @"~\Images\email\box_top.gif";
- emo2.Name = "box_top";
- message.EmbeddedObjects.Add(emo);
- 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.
- //Build replacement collection to replace fields in email.htm file
- ListDictionary replacements = new ListDictionary();
- replacements.Add("<%EVENTDATE%>", eventTextBox.Text);
- replacements.Add("<%EVENTNAME%>", labelEventName.Text);
- replacements.Add("<%FROMNAME%>", TextBoxYourName.Text);
- replacements.Add("<%EVENTDESCRIPTION%>", labelEventDescription.Text);
- 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:
- //now create mail message using the mail definition object
- //the CreateMailMessage object takes a source control object as the last parameter,
- //if the object you are working with is webcontrol then you can just pass "this",
- //otherwise create a dummy control as below.
- MailMessage msgHtml = message.CreateMailMessage(sbEmailTo.ToString(), replacements, new LiteralControl());
- AlternateView htmlView = AlternateView.CreateAlternateViewFromString(msgHtml.Body, null, “text/htmlâ€);
- msg.AlternateViews.Add(htmlView);
- // send email now (check web.config)
- SmtpClient smtp = new SmtpClient();
- 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.
February 7th, 2009 at 2:20 am
Thank you! Was looking for this exact solution.
February 13th, 2009 at 8:21 am
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);
March 3rd, 2009 at 5:15 pm
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);
March 4th, 2009 at 9:40 am
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.
March 5th, 2009 at 11:22 am
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
March 6th, 2009 at 7:25 pm
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 + “”;
March 6th, 2009 at 7:26 pm
All of the html was removed from my post above when I submitted the message, but I put in table, tr and td elements
March 16th, 2009 at 10:51 am
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.
March 18th, 2009 at 12:12 pm
Great topic, and great post!
April 9th, 2009 at 1:34 pm
Is there any way to attach a MHT file instead of html?
April 19th, 2009 at 12:13 am
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
April 20th, 2009 at 10:28 am
@Josh – Sorry, my bad. I missed that one. I have now updated the post.
@Al – Thanks for the heads up; much appreciated.
May 11th, 2009 at 1:18 pm
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
May 29th, 2009 at 9:30 am
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.
June 22nd, 2009 at 7:42 pm
this article very helpful!
Thx
July 4th, 2009 at 3:32 am
This Article is very useful. I tried but only sent a blank body. Coult you tell me the reason? Thanks a lot!
July 23rd, 2009 at 2:31 am
instead of using message.BodyFileName = “email.htm” i passed html message but it shows error
July 27th, 2009 at 9:09 pm
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.
August 3rd, 2009 at 12:06 pm
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!
November 5th, 2009 at 9:54 pm
Thanks for the code and explanation. It helped me out!
November 25th, 2009 at 3:00 pm
Excellent walk-through! Just what I needed to keep going strong 🙂
January 29th, 2010 at 2:03 pm
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
January 30th, 2010 at 12:27 am
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.
February 16th, 2010 at 3:45 pm
How do you get rid of the .dat attachment when you send mail as html? Thoughts?
May 28th, 2010 at 3:14 pm
Just what I needed. I was wondering about the Alerternate View stuff since I KNOW some email programs don’t display HTML
thank you!
June 21st, 2010 at 7:48 pm
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?
August 11th, 2010 at 9:40 am
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.
January 7th, 2011 at 6:36 am
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?
January 7th, 2011 at 9:31 am
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
January 9th, 2011 at 12:29 am
is that the solution John?
any chance you know it in C#? My vb is very rusty
January 9th, 2011 at 11:07 pm
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.
January 9th, 2011 at 11:09 pm
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.
March 14th, 2011 at 5:28 am
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
August 1st, 2011 at 10:33 am
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);
}
}
}