Sending Email with C#
Sending emails is a very common requirement within modern applications. In particular web based application send many emails in relation to registration and alerts of various kinds.
In this article we are going to build a simple WinForms application to send emails. The code can easily be applied to an asp.net application just by changing the GUI part - the underlying fundamental C# code would be the same.
This article has been written with Visual studio 2008 in mind so first fire up Visual Studio and create a new WinForms C# project with an appropriate name.
We now need to layout all of the controls on our form which will look like this:
If you can't be bothered to do all this then feel free to employ your copy and paste skills with the code below which is from my designer file:
Ok so now to look at the code.
When we are working with sending emails, we need to use the System.Net.Mail namespace. This used to be System.Web.Mail in earlier versions of the framework but Microsoft kindly moved it to keep us on our toes. We will also be using a regular expression within our code as well as some File IO operations so we need namespaces for those as well.
So the first thing to do is add the following using statements:
Now we can wire up an event handler for our Send button by clicking on it in design view and this will give us an empty event handler as follows:
We will need a boolean variable to keep track of whether our email is to be sent as HTML or Plain Text and we will also do some form validation. If we encounter form validation problems then we will build up a list of error messages and for this we will use a StringBuilder so we can add these like this:
As part of our form validation, we shall check that the format of email addresses entered into the To and From fields are ok.
To do this we will use a method which makes use of a regular expression. This method will look like this:
Regular expressions are beyond the scope of this article so please accept that this works or and have a study of regular expressions for yourself if you need a holistic understanding of this.
Now back to our button click event handler. The first bit of validation code will need to look like this:
So what we are doing here is checking if a value has been entered into the To field and if not then adding a message line to our StringBuilder. If an email address has been typed in then we also check if it is a valid email using the method we created earlier with the regular expression. And so we will build up a list of all of our error messages and then either show these to the user in a MessageBox or if there are no error messages then we will send the email.
The rest of our validation code looks like this.
if (string.IsNullOrEmpty(To.Text))
{
errorMessage.AppendLine("Please enter a recipient");
}
else if (!IsValidEmailFormat(To.Text))
{
errorMessage.AppendLine("The recipient email is not a valid format");
}
if (string.IsNullOrEmpty(From.Text))
{
errorMessage.AppendLine("Please enter a sender");
}
else if (!IsValidEmailFormat(From.Text))
{
errorMessage.AppendLine("The sender email is not a valid format");
}
if (string.IsNullOrEmpty(Subject.Text))
{
errorMessage.AppendLine("Please enter a subject");
}
if (string.IsNullOrEmpty(Body.Text))
{
errorMessage.AppendLine("Please enter a body for the message");
}
if (string.IsNullOrEmpty(Body.Text))
{
errorMessage.AppendLine("Please enter an SMTP Server");
}
if (!string.IsNullOrEmpty(AttachmentPath.Text))
{
if (!File.Exists(AttachmentPath.Text))
{
errorMessage.AppendLine("The specified attachment does not exist");
}
}
if (string.IsNullOrEmpty(EmailFormat.Text))
{
errorMessage.AppendLine("Please specify an email format");
}
else
{
isHTML = (EmailFormat.Text == "HTML");
}
if (UseAuthentication.Checked)
{
if (string.IsNullOrEmpty(Username.Text))
{
errorMessage.AppendLine("Please enter an SMTP username");
}
if (string.IsNullOrEmpty(Password.Text))
{
errorMessage.AppendLine("Please enter an SMTP password");
}
}
if (errorMessage.Length > 0)
{
MessageBox.Show(errorMessage.ToString(), "Form Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else if (!UseAuthentication.Checked)
{
}
else
{
}
The last bit will then try and send the email with a block of code for if authentication is not ticked and a block of code for when it is ticked.
Before filling in the blanks in the above bit of code we will write our methods for sending emails. Since we have different options for using authentication and not using authentication and sending an attachment or not sending an attachment, it seemd a reasonable idea to solve this problem by using method overloading.
So we will need method for the following sceanarios:
- Send an unauthenticated email with no attachment
- Send an unauthenticated email with an attachment
- Send an authenticated email with no attachment
- Send an authenticated email with an attachment
Our first method then will look like this:
private void SendMail(string to, string from, string subject, string body, bool isHTML, string smtpServer)
{
MailMessage mailMessage = new MailMessage(from, to, subject, body);
mailMessage.IsBodyHtml = isHTML;
SmtpClient smtpClient = new SmtpClient(smtpServer);
smtpClient.Send(mailMessage);
}
So whats happening here is that first we create an instance of a MailMessage class and we call our variable which references this mailMessage. The MailMessage class has a constructor which accepts 4 parameters which allows us to instantiate and populate the class instance all in one .
The MailMessage class determines if the mail is to be sent as plain text or html via a boolean property called IsBodyHtml. We set this to be equal to our passed in parameter which ultimatley comes from what is selected in our drop down list for email format on our form.
We then create an instance of a SmtpClient class. This has a constructor which allows you to pass in the email server we will be using. This comes from our form and is a string. It can be in the form of an IP adddess of a dns name eg 192.168.1.145 or myserver.mydomain.com.
We then finally call the send method of the SmtpClient object which takes our MailMessage object as a parameter and that's it we are done.
The next method overload for sending an unauthenticated email with an attachment is very simillar but with an extra parameter in the method signature and an extra line to add the attachment. This method looks like this:
private void SendMail(string to, string from, string subject, string body, bool isHTML, string smtpServer, string attachmentPath)
{
MailMessage mailMessage = new MailMessage(from, to, subject, body);
mailMessage.Attachments.Add(new Attachment(attachmentPath));
SmtpClient smtpClient = new SmtpClient(smtpServer);
smtpClient.Send(mailMessage);
}
The next overload is to send an authenticated email without an attachment so this is very simillar to our first method but with extra parameters for the username and password and a couple of extra lines to send authentication details to the server. It's very simple code wise so should be self explanatory as follows:
private void SendMail(string to, string from, string subject, string body, bool isHTML, string smtpServer, string username, string password)
{
MailMessage mailMessage = new MailMessage(from, to, subject, body);
SmtpClient smtpClient = new SmtpClient(smtpServer);
smtpClient.UseDefaultCredentials = false;
System.Net.NetworkCredential SMTPUserInfo = new System.Net.NetworkCredential(username, password);
smtpClient.Credentials = SMTPUserInfo;
smtpClient.Send(mailMessage);
}
And finally the very last overload is to send an authenticated email with an attachment. Nothing new to us here then and looking like this:
private void SendMail(string to, string from, string subject, string body, bool isHTML, string smtpServer, string username, string password, string attachmentPath)
{
MailMessage mailMessage = new MailMessage(from, to, subject, body);
SmtpClient smtpClient = new SmtpClient(smtpServer);
mailMessage.Attachments.Add(new Attachment(attachmentPath));
smtpClient.UseDefaultCredentials = false;
System.Net.NetworkCredential SMTPUserInfo = new System.Net.NetworkCredential(username, password);
smtpClient.Credentials = SMTPUserInfo;
smtpClient.Send(mailMessage);
}
Ok so now these method overloads are written we can and fill in the bit of code which calls these methods depending on what our form choices were.
And for completeness here is the entire thing:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Net.Mail;
using System.IO;
namespace EmailSender
{
public partial class EmailForm : Form
{
public EmailForm()
{
InitializeComponent();
}
private void Send_Click(object sender, EventArgs e)
{
StringBuilder errorMessage = new StringBuilder();
bool isHTML = false;
if (string.IsNullOrEmpty(To.Text))
{
errorMessage.AppendLine("Please enter a recipient");
}
else if (!IsValidEmailFormat(To.Text))
{
errorMessage.AppendLine("The recipient email is not a valid format");
}
if (string.IsNullOrEmpty(From.Text))
{
errorMessage.AppendLine("Please enter a sender");
}
else if (!IsValidEmailFormat(From.Text))
{
errorMessage.AppendLine("The sender email is not a valid format");
}
if (string.IsNullOrEmpty(Subject.Text))
{
errorMessage.AppendLine("Please enter a subject");
}
if (string.IsNullOrEmpty(Body.Text))
{
errorMessage.AppendLine("Please enter a body for the message");
}
if (string.IsNullOrEmpty(Body.Text))
{
errorMessage.AppendLine("Please enter an SMTP Server");
}
if (!string.IsNullOrEmpty(AttachmentPath.Text))
{
if (!File.Exists(AttachmentPath.Text))
{
errorMessage.AppendLine("The specified attachment does not exist");
}
}
if (string.IsNullOrEmpty(EmailFormat.Text))
{
errorMessage.AppendLine("Please specify an email format");
}
else
{
isHTML = (EmailFormat.Text == "HTML");
}
if (UseAuthentication.Checked)
{
if (string.IsNullOrEmpty(Username.Text))
{
errorMessage.AppendLine("Please enter an SMTP username");
}
if (string.IsNullOrEmpty(Password.Text))
{
errorMessage.AppendLine("Please enter an SMTP password");
}
}
if (errorMessage.Length > 0)
{
MessageBox.Show(errorMessage.ToString(), "Form Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else if (!UseAuthentication.Checked)
{
try
{
if (string.IsNullOrEmpty(AttachmentPath.Text))
{
SendMail(To.Text, From.Text, Subject.Text, Body.Text, isHTML, SMTPServer.Text);
}
else
{
SendMail(To.Text, From.Text, Subject.Text, Body.Text, isHTML, SMTPServer.Text, AttachmentPath.Text);
}
MessageBox.Show("The message has been sent", "Send Results", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show("There was a problem sending this email" + Environment.NewLine + Environment.NewLine + ex.Message);
}
}
else
{
try
{
if (string.IsNullOrEmpty(AttachmentPath.Text))
{
SendMail(To.Text, From.Text, Subject.Text, Body.Text, isHTML, SMTPServer.Text, Username.Text, Password.Text);
}
else
{
SendMail(To.Text, From.Text, Subject.Text, Body.Text, isHTML, SMTPServer.Text, Username.Text, Password.Text, AttachmentPath.Text);
}
MessageBox.Show("The message has been sent", "Send Results", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show("There was a problem sending this email" + Environment.NewLine + Environment.NewLine + ex.Message);
}
}
}
private void SendMail(string to, string from, string subject, string body, bool isHTML, string smtpServer)
{
MailMessage mailMessage = new MailMessage(from, to, subject, body);
mailMessage.IsBodyHtml = isHTML;
SmtpClient smtpClient = new SmtpClient(smtpServer);
smtpClient.Send(mailMessage);
}
private void SendMail(string to, string from, string subject, string body, bool isHTML, string smtpServer, string attachmentPath)
{
MailMessage mailMessage = new MailMessage(from, to, subject, body);
mailMessage.Attachments.Add(new Attachment(attachmentPath));
SmtpClient smtpClient = new SmtpClient(smtpServer);
smtpClient.Send(mailMessage);
}
private void SendMail(string to, string from, string subject, string body, bool isHTML, string smtpServer, string username, string password)
{
MailMessage mailMessage = new MailMessage(from, to, subject, body);
SmtpClient smtpClient = new SmtpClient(smtpServer);
smtpClient.UseDefaultCredentials = false;
System.Net.NetworkCredential SMTPUserInfo = new System.Net.NetworkCredential(username, password);
smtpClient.Credentials = SMTPUserInfo;
smtpClient.Send(mailMessage);
}
private void SendMail(string to, string from, string subject, string body, bool isHTML, string smtpServer, string username, string password, string attachmentPath)
{
MailMessage mailMessage = new MailMessage(from, to, subject, body);
SmtpClient smtpClient = new SmtpClient(smtpServer);
mailMessage.Attachments.Add(new Attachment(attachmentPath));
smtpClient.UseDefaultCredentials = false;
System.Net.NetworkCredential SMTPUserInfo = new System.Net.NetworkCredential(username, password);
smtpClient.Credentials = SMTPUserInfo;
smtpClient.Send(mailMessage);
}
private void UseAuthentication_CheckedChanged(object sender, EventArgs e)
{
Username.Enabled = UseAuthentication.Checked;
Password.Enabled = UseAuthentication.Checked;
}
public static bool IsValidEmailFormat(string emailAddress)
{
if (string.IsNullOrEmpty(emailAddress))
{
return false;
}
else
{
string regExpression = @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
Regex reg = new Regex(regExpression);
return reg.IsMatch(emailAddress);
}
}
private void AddAttachment_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
DialogResult result = openFileDialog.ShowDialog();
if (result == DialogResult.OK)
{
AttachmentPath.Text = openFileDialog.FileName;
}
}
}
Note also the methods for running when the use authentication checkbox is ticked and when the browse button is clicked to add an attachment. The code here should be trivial and self explanatory.
Any comments are welcome.