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

Use of MSMQ for Sending Bulk Mails

By , 29 Mar 2011
Rate this:
Please Sign up or sign in to vote.

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Amol Rawke Pune
Software Developer (Senior) Atos Origin
India India
Over 6+ years of experience in Software Design Development,Worked on C#, ADO.NET, ASP.NET, Rational XDE, UML, MS SQL Server - 2000,2005,2008, .Net FrameWork - 1.1,2.0,3.5, Crystal Reports.
 
Education - B.E - E&TC, CDAC - DAC.
 
Certifications:
 
Microsoft: MCTS - in .Net FrameWork 2.0.
IBM: Certified solution designer.
BrainBench: Certified in C#,Asp.Net,Framework 3.5,Asp.Net3.0.

Comments and Discussions

 
GeneralMy vote of 3 Pinmembergusdewa31-Mar-14 19:12 
GeneralMy vote of 5 Pinmemberchethan84200328-Apr-12 5:29 
Question"Format name is invalid" Pinmemberd8auriga22-May-11 7:35 
GeneralMy vote of 4 PinmemberMr. Mox5-Apr-11 5:33 
GeneralDon't get it Pinmemberdburr4-Apr-11 12:20 
GeneralRe: Don't get it PinmemberMr. Mox5-Apr-11 5:31 
QuestionFormat name is invalid Pinmemberleo.cba30-Mar-11 2:43 
AnswerRe: Format name is invalid PinmemberMember 32777604-Jun-13 23:54 
Generalgood Pinmemberalhambra-eidos29-Mar-11 21:12 
GeneralGood, Keep it up Pinmemberaamironline21-Mar-11 22:25 
GeneralNice and simple article PinmemberR_ashish9-Mar-11 0:21 
Generalvery good article Pinmemberamol.shewalkar From mumbai8-Mar-11 17:51 
GeneralRe: very good article PinmemberAmol Rawke Pune8-Mar-11 17:54 

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
Web04 | 2.8.140415.2 | Last Updated 30 Mar 2011
Article Copyright 2011 by Amol Rawke Pune
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid