Question

I need to send different e-mails to different people. A different body of the e-mail is generated for every recipient and then I call the following method. That is, if there are 10 recipients, the following method is called 10 times:

        public int Send_Mail(string send_from_bc, string send_to_bc, string subject_bc, string body_bc)
        {
            try
            {
                int count_returned = 0;
                var send_from = new MailAddress(send_from_bc, "The Admin");
                var send_to = new MailAddress(send_to_bc);
                string subject = subject_bc;
                string body = body_bc;

                var smtp = new SmtpClient
                {
                    Host = "**my smtp host**",
                    Port = 25,
                    DeliveryMethod = SmtpDeliveryMethod.Network,
                    Timeout = 300000
                };

                using (var message = new MailMessage(send_from, send_to)
                {
                    Subject = subject,
                    Body = body
                })
                {
                    message.IsBodyHtml = true;
                    smtp.Send(message);
                    count_returned += 1;
                }

                return count_returned;
            }
            catch (Exception ex)
            {
                throw new Exception("Exception caught in Send_Mail", ex);
            }
        }

The problem is that this is taking an incredible amount of time to send even a few mails (like 10 or 15 mails). It takes around 2-5 minutes to send a single mail. Now, I do believe that partly the SMTP host provided to me is at fault. But what can I do to speed things up?

Also, is there some way to achieve this: Right now, the user clicks on a button and then say, for sending two mails, he/she has to wait 2-5 minutes (sometimes even more) before control is returned and the value of a label is changed to "E-mails sent.". Can something be done so that the user just clicks on the button, and the e-mail sending is initiated and he/she could just close the window and get on with his work?

I'm stuck on a critical stage right now and any help would be appreciated.

Was it helpful?

Solution

First thing first - don't make the user wait for this action. The session could well time out if you have to wait 2-5 minutes. Instead make this action an asynchronous task that runs in the background.

I'd then consider popping up a notification stating that the emails have been sent to the user later on, rather than forcing them to wait.

A starter for 10 - move your sending email code into a separate class:

public class EmailSender
{
    public EmailSender(/* Parameters required, e.g. list of emails */)
    { }

    public void SendEmails()
    {
        // Long running task
    }       
}

Then in your page, say a button is clicked:

protected void btn_SendEmails_Clicked(object sender, EventArgs e)
{
     EmailSender emailSender = new EmailSender(/* Any setup code required */);
     ThreadPool.QueueUserWorkItem(emails  => emailSender.SendEmails());
}

To handle the notifications back to the user you'll want to raise an Event when the emails have finished and probably using something like SignalR to alert the browser.

Note that I've not tried compiling this code but should give you the general idea.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top