Click here to Skip to main content
15,885,954 members
Articles / Programming Languages / C#
Article

Message Dispatcher

Rate me:
Please Sign up or sign in to vote.
4.00/5 (1 vote)
27 Nov 2011CPOL6 min read 22.3K   495   16  
Send e-mails asynchronously
Message Dispatcher

Introduction

While programming various WEB applications, I have many times come across the need to send a message to interested users. For example, when a customer purchases a good from my e-shop, I want to send him an e-mail with the order details.

The piece of code that I am publishing here helps me out with this task as follows:

  • It is a DLL that offers me an API to send an e-mail.

  • Delivery is asynchronous. Hence, the application returns immediately and the actual delivery of the e-mail takes place later on. This has serious advantages over a synchronous delivery. Such as:

    • E-mail delivery may take some time, since it requires connection to SMTP server. With asynchronous delivery, the user does not perceive this delay.

    • SMTP server might be down and not responding to e-mail delivery. With asynchronous communication, I can build a nice retry mechanism.

Using the Code

In order to use it in your programs, you need to take care of the following:

  • Prepare your database. You need a Microsoft SQL Database. This is used to hold the messages that are queued for delivery. Note that in the folder database of MessageDispatcherDAL project, you will find the script named create_and_initialize_tables.sql that you can use to create and initialize the tables. IMPORTANT: The script DOES NOT create the database neither the login to access it. You have to do that. This is done, because it assumes that the whole set of the necessary tables would be most probably live inside a bigger database, designed to serve the needs of the application that would host the Message Dispatcher. What does the script do?

    • Creates the table Messages. It holds the messages that you want to be delivered.

    • Creates the table MessageTypes. Currently only email is really supported. But in the future, I may introduce the features to support sms too. You may find the value sms in the table, but this is not supported yet.

    • Creates the table MessageStatuses. It contains the values of the statuses of the messages. The supported statuses are:

      • NEW: Non-final Status. This is the status of a message that has just been put in the queue.

      • SENT: Final Status. This is the status of a message that has been successfully sent out.

      • FAILED: Non-Final Status. This is the status of a message that has not been sent out, due to some error. However, this is not a final status. MessageDispatcher will retry the delivery.

      • ERROR: Final Status. This is a final status that indicates that the message has failed to be delivered, even if MessageDispatcher has tried more than once.

    • Creates the table MessageBodyTypes. This is a lookup table that contains two values:

      • plain

      • html

      If you are delivering an e-mail that contains HTML content, then you need to use html. If not, but just plain text, you need to use plain. Note that if you choose html then both plain text and HTML versions are combined in the same message.

    • Schema: The schema in which all objects are created is dbo. If you want to change the default schema name, you need to:

      • Edit MessageDispatcherDAL.edmx file in project MessageDispatcherDAL and change the Schema entries to have the value you want, when now they have the value dbo.

      • Also, in the same file, change the value of DefaultDatabaseSchema from dbo to whatever you want.

      • Save and rebuild project MessageDispatcherDAL.

  • Install the Message Dispatcher Windows Service. Messages are being processed asynchronously with the help of a Windows Service. So, you need to install it. These are the instructions:

    • Project MessageDispatcherWindowsServiceSetup creates the setup.exe that you can use to install the service.

      OR

    • You can run the setup.exe that exists inside the zip MessageDispatcherWindowsServiceInstaller.zip that you can download from the top of the article.

    Note that the installer installs the windows service and sets its Startup Type to be Manual. After the installation on your production server, change this to Automatic, so that whenever your server starts up, this service is started up automatically too.

  • Configure Message Dispatcher Windows Service. Message Dispatcher windows service needs to know:

    • How to connect to the database to find out the messages that need to be processed.

    • How to connect to the SMTP Server in order to send the e-mails.

    Configuration of the Message Dispatcher Windows Service is done by setting appropriately the values in the configuration file with name MessageDispatcherWindowsService.exe.config that resides in the folder where the service has been installed.

    • Configure database connection: Set the appropriate connection string with name MessageDispatcherDALContainer. An example is given below:

      XML
      <connectionStrings>
          <add name="MessageDispatcherDALContainer" 
      	connectionString="metadata=res://*/MessageDispatcherDAL.csdl|
      	res://*/MessageDispatcherDAL.ssdl|res://*/MessageDispatcherDAL.msl;
      	provider=System.Data.SqlClient;
      	provider connection string="Data Source=MYSQLSERVER,50708\SQLEXPRESS;
      	Initial Catalog=my_db;Persist Security Info=True;User ID=my_db;
      	Password=my_db;MultipleActiveResultSets=True"" 
      	providerName="System.Data.EntityClient"/>
      </connectionStrings>
    • SMTP Connection settings: In the same file, MessageDispatcherWindowsService.exe.config sets the following values appropriately, as in the example:

      XML
      <appSettings>
          <add key="MessageDispatcherWindowsService.Smtp.Server" 
      	value="mail.foo.com"/>
          <add key="MessageDispatcherWindowsService.Smtp.Username" 
      	value="user@foo.com"/>
          <add key="MessageDispatcherWindowsService.Smtp.Password" value="password"/>
      </appSettings>

      If your SMTP server does not require authentication, then set an empty string as value for both MessageDispatcherWindowsService.Smtp.Username and MessageDispatcherWindowsService.Smtp.Password.

    • Other minor service configuration settings:

      • Sleep Between Processing: The seconds between processing messages. Windows service sleeps this number of seconds before checking again for new messages.
        XML
        <appSettings>
            <add key="MessageDispatcherWindowsService.MainThreadSleepSeconds" 
        	value="3"/>
        </appSettings>  
      • Maximum number of failures before error: For each message that fails to be delivered, the service will retry that maximum number of times. If it fails all the times, the status of the message becomes ERROR.
        XML
        <appSettings>
            <add key="MessageDispatcherWindowsService.
        	MaximumNumberOfFailuresBeforeError" value="3"/>
        </appSettings>
      • Timeout Between Retries In Minutes: For each message that fails delivery, the next retry will be later than this amount of minutes.
        XML
        <appSettings>
            <add key="MessageDispatcherWindowsService.
        	TimeoutBetweenRetriesInMinutes" value="3"/>
        </appSettings>
  • Integrate in your Code. You need to use the MessageDispatcher API in your project in order to be able to send messages from your project. Follow the next instructions alongside the MessageDispatcherWindowsConsoleDemo project:

    • Reference MessageDispatcherDAL.dll in your project.

    • Create a database connection configuration string. This is necessary so that MessageDispatcherDAL knows where is the persistence storage of the message queues.

      For example, you can configure that in your app.config file (<configuration> section), if you have a Windows Console Application, as follows:

      XML
      <connectionStrings>
         <add name="MessageDispatcherDALContainer" 
      	connectionString="metadata=res://*/MessageDispatcherDAL.csdl|
      	res://*/MessageDispatcherDAL.ssdl|res://*/MessageDispatcherDAL.msl;
      	provider=System.Data.SqlClient;
      	provider connection string="Data Source=MYSQLSERVER,50708\SQLEXPRESS;
      	Initial Catalog=my_db;Persist Security Info=True;User ID=my_db;
      	Password=my_db;MultipleActiveResultSets=True"" 
      	providerName="System.Data.EntityClient"/>
      </connectionStrings>         

      Make sure you set correctly the server host name, the server port, the initial catalog, the user id and the password.

    • Create a message using the Message.CreateEmailMessage(...) method, as in the following example:

      C#
      // sender: no_reply@foo.com
      // receivers: customer1@gmail.com;customer2@yahoo.gr
      // ccReceivers: null
      // bccReceivers: null
      // Plain Text Example (last parameter is 'false')
      Message.CreateEmailMessage(no_reply@foo.com, 
      	"customer1@gmail.com;customer2@yahoo.gr", null, null,
             	"Your Order Details", "Order ID: 5, 
      	Date of Purchase: 25-Nov-2011, Amount: 29.00 Euro", false);

      This will create a new entry in the table Messages and on status NEW. Message Dispatcher Windows Service will take care from there.

    • Catch exception. Don't forget to wrap Message.CreateEmailMessage(....) in a try { ... } catch (...) {...} block. Otherwise, make sure you catch any exception that this method might throw. You do not want your application to crash just because a message cannot be saved. Here is another example of using this method to send HTML message, wrapped to catch exceptions:

      C#
      try
      {
          Message.CreateEmailMessage(no_reply@foo.com, 
      	"customer1@gmail.com;customer2@yahoo.gr", null, null,
             	"Your Order Details", 
      	"<html><head></head><body><b>Order ID:</b> 5<br />
      	<b>Date of Purchase:</b> 25-Nov-2011<br /><b>Amount:</b> 
      	29.00 Euro<body></body></html>", true);
      }
      catch (EntityException ex)
      {
          System.Console.WriteLine("Cannot create message: " + ex.Message);
      }  

Summary

I believe it is quite easy for you to send your e-mails asynchronously, using this DLL and Windows Service.

  • Install the Windows Service
  • Configure Windows Service
  • Integrate in your code

Your comments are welcome and thanks for reading this far.

History

  • 27th November, 2011: Initial post

License

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


Written By
Greece Greece
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --