I am a danish programmer living in Bangkok.
Read more about me @ rasmus.rummel.dk.
Webmodelling Home > ASP.NET > C# Utility Functions > Email - Send

Send Email

Updated Dec 2012. While sending synchroneous email is quite easy from within asp.net, it is often preferable to send it asynchronously to avoid waiting for the email to be send before the next code can execute. With the SynchronizationContextSwitcher class (defined below) it is possible to achieve asynchronously email.

References :

Usage

  • Example
    • I use this Send function in most if not all of my projects, eg. in my Discussions WebControl then sending notifications to users that request notifications on new posts for their selected discussions. To avoid the Forum becoming unresponsive after adding a post that triggers notifications, I secure that the emails are send asynchronously.
  • Example Code
    • Utils.Email.Send("rasmus@webmodelling.com""some subject""html encoded body"truetrue);
      
      Also you must have the following 5 web.config App.Settings : (here I show my real values, except for the SmtpPassword)
      <add key="Email:SmtpServer" value="mail.webmodelling.com"/>
      <add key="Email:SmtpPort" value="25"/>
      <add key="Email:SmtpUserName" value="rasmus@webmodelling.com"/>
      <add key="Email:SmtpPassword" value="MyPassword"/>
      <add key="Email:FromAddress" value="rasmus@webmodelling.com"/>
      

The Send function :

//First the actual Send function
public static void Send(string pToAddress, string pSubject, string pBody, bool pIsBodyHtml, bool pAsync, Attachment[] pAttachments)
{
	string smtpServer = ConfigurationManager.AppSettings["Email:SmtpServer"];
	int smtpPort = int.Parse(ConfigurationManager.AppSettings["Email:SmtpPort"]);
	string smtpUsername = ConfigurationManager.AppSettings["Email:SmtpUsername"];
	string smtpPassword = ConfigurationManager.AppSettings["Email:SmtpPassword"];
	string fromAddress = ConfigurationManager.AppSettings["Email:FromAddress"];

	System.Net.Mail.MailMessage mm = new System.Net.Mail.MailMessage(smtpUsername, pToAddress);
	mm.Subject = pSubject;
	mm.IsBodyHtml = pIsBodyHtml;
	mm.Body = pBody;
	mm.From = new System.Net.Mail.MailAddress(fromAddress);

	for (int a = 0; a < pAttachments.Length; a++)
	{
		mm.Attachments.Add(pAttachments[a]);
	}

	if (pAsync)
	{
		using (new SynchronizationContextSwitcher())
		{
			System.Net.Mail.SmtpClient smtpClient = new System.Net.Mail.SmtpClient(smtpServer);
			smtpClient.UseDefaultCredentials = false;
			smtpClient.Port = smtpPort; //not all MTA set the SMTP port to 25, eg. JodoHost MTA set it to 587
			smtpClient.Credentials = new System.Net.NetworkCredential(smtpUsername, smtpPassword);
 
			smtpClient.SendAsync(mm, null);
		}
	}
	else
	{
		System.Net.Mail.SmtpClient smtpClient = new System.Net.Mail.SmtpClient(smtpServer);
		smtpClient.UseDefaultCredentials = false;
		smtpClient.Port = smtpPort;
		smtpClient.Credentials = new System.Net.NetworkCredential(smtpUsername, smtpPassword);
 
		smtpClient.Send(mm);
	}
}

//Then a couple of handy overloads
public static void Send(string pToAddress, string pSubject, string pBody, bool pIsBodyHtml)
{
	Send(pToAddress, pSubject, pBody, pIsBodyHtml, falsenew Attachment[] { });
}

public static void Send(string pToAddress, string pSubject, string pBody, bool pIsBodyHtml, bool pAsync) //I use this overload most often
{
	Send(pToAddress, pSubject, pBody, pIsBodyHtml, pAsync, new Attachment[] { });
}

And here the SynchronizationContextSwitcher class :

public class SynchronizationContextSwitcher : IDisposable
{
	private ExecutionContext _executionContext;
	private readonly SynchronizationContext _oldContext;
	private readonly SynchronizationContext _newContext;
 
	public SynchronizationContextSwitcher() : this(new SynchronizationContext()){}
 
	public SynchronizationContextSwitcher(SynchronizationContext context)
	{
		_newContext = context;
		_executionContext = System.Threading.Thread.CurrentThread.ExecutionContext;
		_oldContext = SynchronizationContext.Current;
		SynchronizationContext.SetSynchronizationContext(context);
	}
 
	public void Dispose()
	{
		if (null != _executionContext)
		{
			if (_executionContext != Thread.CurrentThread.ExecutionContext)
			{
				throw new InvalidOperationException("Dispose called on wrong thread.");
			}
			if (_newContext != SynchronizationContext.Current)
			{
				throw new InvalidOperationException("The SynchronizationContext has changed.");
 
			}
			SynchronizationContext.SetSynchronizationContext(_oldContext);
			_executionContext = null;
		}
	}
}

Comments

You can comment without logging in
 
 B  U  I  S 
Words: Chars: Chars left: 
 Captcha 
 Nickname
Facebook
    
Thanks
--------------
      report  reply  
Awesome post