Sending SMTP Email Messages with C#
This simple set of classes allows you to send an email using C#. It includes a collection object for adding attachment data, and allows the use of secured (password protected) SMTP servers. It is a decently robust emailer that is simple to use and will get the job done.
The first class is the Email class. It is the parent to the next class we will create. The reason we are going to create a parent class is so that if at any point other protocols are ended, the basics are there and do not need to be re-created. You could theoretically go on to create IMAP and POP3 support if so desired.
Here is the XML documented code for the Email class:
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using System.Net.Mail;
using System.Net.Mime;
namespace Emailer
{
/// <summary>
/// Base class for email functions
/// </summary>
public class Email
{
/// <summary>
/// The priority of the email
/// </summary>
public enum EmailPriority
{
Low = 0,
Normal,
High,
};
/// <summary>
/// Represents an email attachment object
/// </summary>
protected struct MyEmailAttachment
{
/// <summary>
/// The System.Net.Mail.Attachment object to attach
/// </summary>
public Attachment AttachmentData;
/// <summary>
/// The System.Net.Mime.ContentDisposition object which describes the attachment
/// </summary>
public ContentDisposition Disposition;
}
/// <summary>
/// Validates an mail address based on its format
/// </summary>
/// <param name="EmailAddress">Email address to validate</param>
/// <returns>True if valid, False if not</returns>
public static bool ValidateEmailAddressFormat(string EmailAddress)
{
string strRegex = @"^([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 re = new Regex(strRegex);
if (re.IsMatch(EmailAddress))
0; return true;
else
return false;
}
/// <summary>
/// Validates an email's domain
/// </summary>
/// <param name="EmailAddress">The email address to validate</param>
/// <returns>True on valid (can connect to end mail server), False if not valid</returns>
public static bool ValidateEmailDomain(string EmailAddress)
{
bool ReturnVal = false;
string[] Host = EmailAddress.Split('@');
string HostName = Host[1];
IPHostEntry IPHost = Dns.GetHostEntry(HostName);
IPEndPoint EndPoint = new IPEndPoint(IPHost.AddressList[0], 25);
Socket s = new Socket(EndPoint.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
try
{
s.Connect(EndPoint);
s.Disconnect(false);
ReturnVal = true;
}
catch (Exception)
{
ReturnVal = false;
}
finally
{
if (s.Connected)
s.Disconnect(false);
}
return ReturnVal;
}
}
}
The Email class provides address verification by checking to see if a valid email address was passed and it even goes as far as to connect to the domain’s email server to make sure it isn’t simply a spoofed email.
The next class is the SMTP class. Here is the source code for it:
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.Collections;
namespace Emailer
{
/// <summary>
/// SMTP email class, derived from Email
/// </summary>
public class SMTP : Email, IDisposable
{
private List<string> _To;
private List<string> _CC;
private List<string> _Bcc;
private string _From;
private string _SMTPServer;
private string _Subject;
private string _Body;
private string _SMTPUser;
private string _SMTPPassword;
private string _SMTPDomain;
private List<MyEmailAttachment> Attachments;
private bool _UsingSMTPAuth;
private MailPriority _Priority;
/// <summary>
/// The email address to send the message to
/// </summary>
public List<string> To
{
get { return this._To; }
}
/// <summary>
/// Email address to send the message from
/// </summary>
public string From
{
get { return this._From; }
set { this._From = value; }
}
/// <summary>
/// SMTP server to use for relaying the email message
/// </summary>
public string SMTPServer
{
get { return this._SMTPServer; }
set { this._SMTPServer = value; }
}
/// <summary>
/// The subject line of the message
/// </summary>
public string Subject
{
get { return this._Subject; }
set { this._Subject = value; }
}
/// <summary>
/// The body of the message
/// </summary>
public string Body
{
get { return this._Body; }
set { this._Body = value; }
}
/// <summary>
/// Gets or sets the carbon-copy address on the email
/// </summary>
public List<string> CC
{
get { return this._CC; }
}
/// <summary>
/// Gets or sets the blind carbon-copy addres on the email
/// </summary>
public List<string> Bcc
{
get { return this._Bcc; }
set { this._Bcc = value; }
}
/// <summary>
/// Gets or sets the message to be high priority
/// </summary>
public EmailPriority Priority
{
get
{
switch (_Priority)
{
case MailPriority.Low:
return EmailPriority.Low;
case MailPriority.High:
return EmailPriority.High;
default:
return EmailPriority.Normal;
}
}
set
{
switch (value)
{
case EmailPriority.Low:
this._Priority = MailPriority.Low;
break;
case EmailPriority.High:
this._Priority = MailPriority.High;
break;
default:
this._Priority = MailPriority.Normal;
break;
}
}
}
/// <summary>
/// Disposes the Email.SMTP object and clears up any memory used
/// </summary>
public void Dispose()
{
Attachments.Clear();
To.Clear();
CC.Clear();
Bcc.Clear();
}
/// <summary>
/// Default constructor
/// </summary>
public SMTP()
: this("", "", "", "", "")
{
}
/// <summary>
/// Constructor which can setup the entire mail object
/// </summary>
/// <param name="SMTPServer">SMTP server to use for relaying</param>
/// <param name="From">Email address the message is from</param>
/// <param name="To">Email address the message is to</param>
/// <param name="Subject">The subject line of the message</param>
/// <param name="Body">The body of the message</param>
public SMTP(string SMTPServer, string From, string To, string Subject, string Body)
: this(SMTPServer, From, To, Subject, Body, "")
{ }
public SMTP(string SMTPServer, string From, string To, string Subject, string Body, string CC)
: this(SMTPServer, From, To, Subject, Body, CC, "")
{ }
public SMTP(string SMTPServer, string From, string To, string Subject, string Body, string CC, string Bcc)
{
this._To = new List<string>();
this._CC = new List<string>();
this._Bcc = new List<string>();
this._SMTPServer = SMTPServer;
this._From = From;
this._To.Add(To);
if (CC != "")
this._CC.Add(CC);
if (Bcc != "")
this._Bcc.Add(Bcc);
this._Subject = Subject;
this._Body = Body;
this._UsingSMTPAuth = false;
Attachments = new List<MyEmailAttachment>();
Priority = EmailPriority.Normal;
}
/// <summary>
/// Sets SMTP connection credentials if required
/// </summary>
/// <param name="Username">Username to connect to the SMTP server</param>
/// <param name="Password">Password to connect to the SMTP server</param>
public void SetSMTPCredentials(string Username, string Password)
{
SetSMTPCredentials(Username, Password, "");
}
/// <summary>
/// Sets SMTP connection credentials if required
/// </summary>
/// <param name="Username">Username to connect to the SMTP server</param>
/// <param name="Password">Password to connect to the SMTP server</param>
/// <param name="Domain">Domain to connect to the SMTP server</param>
public void SetSMTPCredentials(string Username, string Password, string Domain)
{
if (Username != "" && Username != null)
{
this._SMTPUser = Username;
this._SMTPPassword = Password;
if (Domain != "" && Domain != null)
this._SMTPDomain = Domain;
else
this._SMTPDomain = "";
this._UsingSMTPAuth = true;
}
else
this._UsingSMTPAuth = false;
}
/// <summary>
/// Adds an attachment by a filename
/// </summary>
/// <param name="FileName">The full path of the file to add</param>
/// <returns>True on a successful add, false on failure</returns>
public bool AddAttachment(string FileName)
{
if (!File.Exists(FileName))
throw new MySMTPEmailException("Attachment file does not exist");
try
{
Attachment data = new Attachment(FileName, MediaTypeNames.Application.Octet);
ContentDisposition disposition = data.ContentDisposition;
disposition.CreationDate = File.GetCreationTime(FileName);
disposition.ModificationDate = File.GetLastWriteTime(FileName);
disposition.ReadDate = File.GetLastAccessTime(FileName);
MyEmailAttachment Attachment = new MyEmailAttachment();
Attachment.AttachmentData = data;
Attachment.Disposition = disposition;
Attachments.Add(Attachment);
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// Sends the message to its destination
/// </summary>
public void Send()
{
// Check the email object settings and make sure we're all set up before we even think about sending
if (To.Count <= 0)
throw new MySMTPEmailException("TO Email address is not set");
if (From == "")
throw new MySMTPEmailException("FROM Email address is not set");
if (Subject == "")
throw new MySMTPEmailException("Subject is not set");
if (Body == "")
throw new MySMTPEmailException("Body is not set");
if (SMTPServer == "")
throw new MySMTPEmailException("SMTP server is not set");
MailMessage mail = new MailMessage();
mail.Body = Body;
mail.Subject = Subject;
mail.From = new MailAddress(From);
mail.Priority = _Priority;
foreach (string address in To)
mail.To.Add(address);
if (CC.Count > 0)
{
foreach (string address in CC)
mail.CC.Add(address);
}
if (Bcc.Count > 0)
{
foreach (string address in Bcc)
mail.Bcc.Add(address);
}
SmtpClient client = new SmtpClient(SMTPServer);
// If using SMTP authentication, create the credential
if (_UsingSMTPAuth)
{
if (_SMTPDomain != "" && _SMTPDomain != null)
client.Credentials = new NetworkCredential(_SMTPUser, _SMTPPassword, _SMTPDomain);
else
client.Credentials = new NetworkCredential(_SMTPUser, _SMTPPassword);
}
// Add attachments
foreach (MyEmailAttachment Attachment in Attachments)
{
mail.Attachments.Add(Attachment.AttachmentData);
}
client.Send(mail);
}
}
/// <summary>
/// Custom exception for any problems with the SMTP class
/// </summary>
public class MySMTPEmailException : Exception
{
public MySMTPEmailException()
: base()
{ }
public MySMTPEmailException(string Message)
: base(Message)
{ }
public MySMTPEmailException(string Message, Exception Cause)
: base(Message, Cause)
{ }
}
}
There is also an exception class for methods which are executed in the SMTP class so that you can identify problems with methods inside of the class itself instead of getting some generic exception.
There are several ways to use this class. The easiest and most up-front way of using it is by simply using the constructor inside of a ‘using’ statement, building the object, then calling the Send() method. An example is below:
"mymailserver.mydomain.com",
"source@mydomain.com",
"destination@anotherdomain.com",
"Hello World! In the body of the email") )
{
MyMailer.Send();
}
Of course, you can send the fields manually if you use the default SMTP() constructor. To use the SMTP authentication part of the class, just make a call into SetSMTPCredentials() before you call the Send() method. Thats it! Pretty simple. You can even add an attachment if you want by calling AddAttachment() with a filename as a parameter. It will return true if the addition of the attachment is successful, false if not.

