Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Use of MSMQ for Sending Bulk Mails

0.00/5 (No votes)
29 Mar 2011 1  
Use of MSMQ for Sending bulk mails

Introduction

I was working on a web application; one of the requirements was to send bulk mails to multiple users.

Earlier, I was using SMTP client object to send the mail. But when the number of recipients increased, the application was stuck for a long time. Also the same SMTP server was used among multiple applications, so load on Server was very high.

For performance optimization, I created a new queue using MSMQ on a separate server where all the mails are queued and then created one application which would read emails one by one and send it via SMTP client. Now my original web application is not directly connecting to SMTP server, due to which wait time for sending bulk mail will be very low and load on SMTP server will be less.

Background

MSMQ is essentially a messaging protocol that allows applications running on separate servers or processes(s) to communicate in a failsafe manner. A queue is a temporary storage location from which messages can be sent and received reliably. They can be used for communication across heterogeneous networks and between computers which may not always be connected. Steps to create MSMQ – Queue manually are as follows:

  1. Right click on “My Computer”
  2. Click on “Manage”
  3. Expand Services And Application
  4. Now you can see the “Message Queuing”
  5. Expand “Private Queue”, click on “New Private queue” – Enter the name “emailqueue”

This will create a new Queue, please refer to the attached document for details. Now we will see how to create it programmatically.
Please note: Namespaces required are: ‘System.Messaging’ for MSMQ and ‘System.Net.Mail' for sending mail using SMTP client. Also MSMQ must be installed on your machine.

Using the Code

Now we will see how to use MSMQ to send mail programmatically. I have divided the application in two parts:

  1. Application which will create MSMQ queue and hold all mail - information as an object
  2. Application which will read mail info from Queue and send email via SMTP.

Part 1

First we will look into the Email Sender part: Here, I have created Windows form which will take inputs from user like “To Address”, “From Address”,”Subject”,”Body”, etc. On the “Send Button” click, call method QueueMessage from EmailService.

QueueMessage is used to create the transactional Queue, if it does not exist, it also pushes the data inside this queue.

string msmqQueuePath = @".\Private$\EmailQueue";
// Create new instance of Message object
Message msmqMsg = new Message();

// Assign email information to the Message body
msmqMsg.Body = emailMessage;
//set Recoverable which indicates message is guaranteed 
msmqMsg.Recoverable = true;
//Set Formatter to serialize the object,I’m using binary //serialization
msmqMsg.Formatter = new BinaryMessageFormatter();
//Create message queue instance 
MessageQueue msmqQueue = new MessageQueue();
//If the Message queue does not exists at specified 
//location create it

if (!MessageQueue.Exists(msmqQueuePath))
{
    msmqQueue =  MessageQueue.Create(msmqQueuePath);
}
 
//  Set Formatter to serialize the object. 
msmqQueue.Formatter = new BinaryMessageFormatter();

//Send the message object in the created queue
msmqQueue.Send(msmqMsg);		

Part 2

Email Receiver:

Here, I have created a console application, which will be running continuously to read any new message.

We need an instance of message queue, which will read the email message object from specified path. Please note, Message path in receiver must be the same as sender. Then raise receive complete event of message queue.

as: _msmqQueue.ReceiveCompleted+= In msmqQueue_ReceiveCompleted event : 
extract the actual message like: (EmailEntities.EmailMessage)e.Message.Body. 

Now create the instance of “MailMessage” and set the appropriate properties. Create instance of SMTP client and call Send method. This will send the actual message from the queue.

//message path must be same as sender
string messageQueuePath = @".\private$\EmailQueue";
//create message queue instance
                    _msmqQueue = new MessageQueue(messageQueuePath);
//set formatter same as sender
                    _msmqQueue.Formatter =  new BinaryMessageFormatter();
                    _msmqQueue.MessageReadPropertyFilter.SetAll();
//Raise receive completed event 
_msmqQueue.ReceiveCompleted+=new ReceiveCompletedEventHandler(msmqQueue_ReceiveCompleted);
//start receiving messages
                    _msmqQueue.BeginReceive();
//In msmqQueue_ReceiveCompleted
//Extract the actual message 
EmailEntities.EmailMessage emailMsg = (EmailEntities.EmailMessage)e.Message.Body;
//Create mail message instance 
MailMessage mailMesage = new MailMessage();
//Set the properties
mailMesage.Subject = emailMsg.Subject;
mailMesage.Body = emailMsg.Body;
//Create Smtp client instance
SmtpClient oclient = new SmtpClient();
//call the send method 
oclient.Send(mailMesage);

Points of Interest

Some readers asked me how we can add attachments in this mail? As per analysis, we cannot directly serialize the attachment, but there are alternatives:

  1. We can create a separate class which will help to serialize the entire attachment: something like:
    class SerializeableAttachment 
    { String ContentId; SerializeableContentDisposition ContentDisposition; 
    SerializeableContentType ContentType; ..... 
  2. Instead of serializing the entire attachment, just store that attachment in a database with key value pair and add corresponding property in Send email class. In receiver part, read that key for attachment and get actual attachment from db.
    For more information, refer to this link.

History

  1. Initial version
  2. Minor changes
  3. Minor code changes

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here