Click here to Skip to main content
Click here to Skip to main content

Email Notification Framework

By , 4 Oct 2009
Rate this:
Please Sign up or sign in to vote.

Introduction

I have been working in the industry for a while and I have come to learn that there is no application which doesn't need to send emails. Now a lot of work has been done on making free SMTP servers and there is a rich API set in .NET for SMTP support, but I am yet to find a simple framework in which I can send emails.

Now what do I look for in such a framework? I am looking for the ability to send simple text and HTML emails, the ability to customize the email content with some parameters, the ability to configure email authentication (anonymous, basic or integrated). Further, most email messages sent automatically by a system have templates in which few keys are replaced at run time, having a framework provide such features is also desired.

With these design goals, this framework has been designed and I believe it can be readily used as is out of the box, it may be extended at various extension points. The framework can be deployed as a WCF component.

Layout of this Article

This article is primarily in four sections:

  1. Architecture - This section barely qualifies as architecture as it is in detail, however it will give a good flow.

  2. Design - Deals with the design of the application, the responsibility of methods, etc.

  3. Code - In this section, the more interesting code snippets are discussed from the attached solution.

  4. How do I - In this section, the steps required to configure and send emails is described. In case you want to use this as an out of box utility, you may skip the architecture, design and the code section.

Architecture

Architecture.png

The diagram given above shows the architecture of the notification sub system. It is evident that this emailing system is a client proxy, the email server is an external component.

The notification system allows in process and out of process invocation by being deployed as an in process DLL or a WCF service.

The notification system block contains a message creator which is also exposed as a WCF service, a set of messaging APIs, an enumeration of message types and a Message Template Data store. This section details out the flow along with the responsibility of each component.

WCF Interface - This interface / implemented class provides the business specific methods which can be invoked by the component.

Message Creator - This is the heart of the system, the external systems (WCF client or the local process) invoke this to create and send message. It is responsible to load the message template from the Message template data store, replace the keys with actual values (for example, the name of the person to whom the message is being sent) and invoke the Messaging API.

Notification Types -This is a strongly typed mapping between the business methods and the notification template.

Message Template - This is a data store in which the raw message templates are present.

Messaging API - This is the .NET notification API.

Clients - The clients of this system can be WCF clients or in process applications which refer to the application as a DLL.

Email Server - This is an SMTP server which will send the email.

Design

This section details out the design of the framework. We primarily start off with the object model and keep our discussion to the high level and points which are important for the logical design. For instance, we will not get carried away with the details of how config creation would work or which protocol we will use for WCF communication or how the Notification API will be used.

The Class Model

Class.png

This section details out the responsibility of the classes used to implement the above stated architecture for notification framework.

  • BusinessNotificationAdapter - This class contains methods used by the business. It is also exposed on the WCF end as a service. Its responsibility is to intercept incoming business requests, identify their enumeration and call the Notification controller.
  • AbstractNotificationController - This class is the general orchestrator of show. It fetches the email template (body and subject), prepares the email message without any knowledge of transportation mechanism or authentication mechanism and invokes the EmailNotificationProvider.
  • ResxNotificationController - This class is a specific implementation of the AbstractNotificationController, it uses a pair of RESX files as the template store.
  • EmailNotificationProvider - This class is responsible for the actual notification of the message using the server. It finds the configuration of the notification mechanism such as the SMTP server address, SMTP port, email priority, etc.

The Sequence Diagram

Sequence.png

The diagram given above shows a typical control flow for sending a message. A business object requests a notification to be sent. The business notification adapter finds out the Enum for the notification type and calls Notify on the notification controller. The configuration defines which concrete class will be used for notification. The notify method prepares the message and requests the Email notification provider which is essentially a wrapper on notification API to send out the email message.

The Code

In this section, we will discuss some of the more important code snippets. The code has been developed using Visual Studio 2010 however it should compile in VS 2008. We will not discuss the entire code, however you will find that the code attached is completely documented.

BusinessNotificationAdapter

This class contains business specific methods. The method creates generic lists of placeholder and finds the enum corresponding to the email to be sent. It prepares the generic method and dispatches the call. The primary reason for this class is to shield the details of the email message preparation from business and provide simple structured and type safe methods to send emails.

public void SendSampleNotification(string from, string subjectPlaceholde1, 
	string subjectPlaceholder2, string bodyPlaceholder1, string bodyPlaceholder2, 
	IList<string> toList) { 
List<KeyValuePair<string, string>> placeholdersDataForBody = 
				new List<KeyValuePair<string, string>>(); 

placeholdersDataForBody.Add(new KeyValuePair<string, 
			string>("@Placeholder1", bodyPlaceholder1)); 

placeholdersDataForBody.Add(new KeyValuePair<string, 
			string>("@Placeholder2", bodyPlaceholder2)); 

List<KeyValuePair<string, string>> placeholdersDataForSubject = 
				new List<KeyValuePair<string, string>>(); 

placeholdersDataForSubject.Add(new KeyValuePair<string, 
			string>("@Placeholder1", subjectPlaceholde1)); 

placeholdersDataForSubject.Add(new KeyValuePair<string, string>
			("@Placeholder2", subjectPlaceholder2)); 

//hard coding for now, we can use factory if desired 
AbstractNotificationController notificationController = 
			new ResxNotificationController.ResxNotificationController(); 
notificationController.PrepareAndSendEmail
	(NotificaionType.SampleNotification, placeholdersDataForBody, 
	placeholdersDataForSubject, toList, null, null, from, null); 
}

AbstractNotificationController

This class primarily contains methods to prepare and send an email. The class requires a concrete implementation for finding method subject, body and a mechanism to replace placeholders with actual data.

public void PrepareAndSendEmail(NotificaionType typeOfNotification, 
	IList<KeyValuePair<string, string>> placeholdersDataForBody, 
	IList<KeyValuePair<string, string>> placeholdersDataForSubject, 
	IList<string> sendToAddress, IList<string> ccList, IList<string> bccList, 
	string sendFromAddress, IList<string> attachmentList) 
{ 
EmailNotificationProvider emailNotificationProvider = new EmailNotificationProvider(); 
string mailBody = ReplaceBodyPlaceholders
	(GetBodyTemplate(typeOfNotification), placeholdersDataForBody); 
string subject = ReplaceSubjectPlaceholders
	(GetSubjectTemplate(typeOfNotification), placeholdersDataForSubject); 

//Fix this method to get encoding and priority from config 
emailNotificationProvider.SendNotification
   (sendFromAddress, sendToAddress, ccList, bccList, mailBody, subject, attachmentList);

ResxNotificationController

This class is responsible for an exact implantation of finding templates and replacing the placeholder data. The current implementation uses resource files, however databases or flat file templates may be used.

protected override string GetSubjectTemplate(NotificaionType typeOfNotification) 
{ 
switch (typeOfNotification) 
{ 
case NotificaionType.SampleNotification: 
return EmailSubjectDataStore.SampleNotification; 
break; 
} 
throw new ArgumentException(); 
}

EmailNotificationProvider

This class uses the .NET SMTP client API to send messages. Its primary responsibility is twofold; manage configurations such as how to get SMTP server address etc. and present a wrapper for the SMTP client for the framework.

How Do I

This section details how one may use this framework from a config and development of new email templates:

  1. Configuration:

    1. Open the App.Config/Web.Config of the hosting assembly

    2. Add the following keys (Please refer to the sample app.config for the NotificationTestingUtility project):

      Key Description Possible values
      MailFormat This is the format of the email that will be sent

      HTML

      Text

      MailPriority The priority of the email message

      Low

      Normal

      High

      MailEncoding

      This is the encoding format

      0

      SmtpServer

      The IP address or the name of the SMTP server

      SmtpPort

      The port on which server is listening. If this is not specified, then it is defaulted to 25

      AuthenticationType

      Type of authentication for the SMTP server. If the type is Basic, then SMTP user name, domain and password must be specified

      Basic

      Anonymous

      IntegratedAuthentication

      SMTPUserName

      The name of the user

      SMTPPassword

      The password of the user

      SMTPDOmain

      The domain of the user

  2. Development of new templates

    1. Prepare the Subject and Body template with placeholders having unique characters such as % or @.

    2. Add the Subject and the Body to the EmailBodyDataStore andEmailSubjectDataStore resource files.

    3. Add a new enum value in the NotificationTypeEnum for the newly added templates.

    4. Update the ResxNotificationController methods to return the body and subject for the new notification types.

    5. Add a new business method which takes the values for placeholder in templates.

With a few tricks, you can even populate a list of values. Let me know if you get stuck on that.

History

  • 5th October, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

gaurav_verma_mca
Architect Imfinity
India India
Hi I have been working on enterprise applications for last six years.

Comments and Discussions

 
SuggestionAlternativesd PinmemberNicals Ericsson18-Jan-12 2:36 
GeneralMy vote of 1 PinmemberTop_Coder12-Feb-10 23:49 
GeneralRe: My vote of 1 Pinmembergaurav_verma_mca30-May-10 10:20 
RantCoding Horror PinmemberDaveOMacalroy14-Oct-09 4:10 
Hi,
 
Just reading through some of the source included with this article and came across this little gem of a line:
 
EmailNotificationProvider.cs : line 116

Regex mailExpression = new Regex(@"^\s*(([a-zA-Z0-9]+([_\-\.][a-zA-Z0-9]+)*)@([a-zA-Z0-9]+([_\-\.][a-zA-Z0-9]+)*)\.([a-zA-Z]{2,5}))\s*$");
return Convert.ToBoolean(mailExpression.IsMatch(address) ? true : false);

 
Deary me, you should submit that to the Coding Horror forum, what are you trying to do there?
 
'mailExpression.IsMatch()' returns a boolean.
Then you have that in an in-line if which if 'mailExpression.IsMatch()' has returned true, returns true else returns false.
Then that goes into 'Convert.ToBoolean()' which takes the boolean result from the in-line if and converts it to.... a boolean!
 
For shame.
GeneralRe: Coding Horror Pinmembergaurav_verma_mca14-Oct-09 7:08 
GeneralRe: Coding Horror PinmemberDaveOMacalroy14-Oct-09 22:00 
GeneralRe: Coding Horror Pinmembergaurav_verma_mca14-Oct-09 22:22 
GeneralRe: Coding Horror PinmemberDaveOMacalroy14-Oct-09 22:37 
GeneralRe: Coding Horror Pinmembergaurav_verma_mca14-Oct-09 22:39 
GeneralRe: Coding Horror Pinmembergaurav_verma_mca14-Oct-09 7:12 
GeneralMessage Creator with MailMergeLib PinmemberNorbert Bietsch7-Oct-09 9:24 
GeneralRe: Message Creator with MailMergeLib Pinmembergaurav_verma_mca7-Oct-09 17:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140421.2 | Last Updated 5 Oct 2009
Article Copyright 2009 by gaurav_verma_mca
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid