Hi,
I have a newsletter tool that I am trying to setup to run as a background process to send out the emails. The code below works without any issues but the problem I have is that it is slow.
If there are 50 emails to send it can be very slow for the end user as they have to stare at the screen for up to 1min 30secs. This becomes a bigger problem for me if they client is sending an email to a larger group of people.
The reason I send each mail individually as apposed to sending 1 and bcc'ing the email list is that each email contains certain specific content for each user - like unsubscribe link codes, personal name at the start of the mail, etc.
I am looking for a solution where I can let the user click on a button and have .net run the sending email part in the background while the front end user is brought to a page saying that their email is being sent. Ideally, it should take no longer than a regular postback for all that to occur - not the current few minutes.
Any thoughts on how best to achieve this?
Thanks for your help, Rich
if (Page.IsPostBack)
{
if (JustMeButton.Checked)
{
SendMail("emailme@address", EmailTemplate);
}
if (EveryoneButton.Checked)
{
//setup background process
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = false;
bw.WorkerSupportsCancellation = false;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.RunWorkerAsync();
//bring user to next screen and display message
Response.Redirect("emailSendingMessageScreen.aspx");
}
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
DataTable emailTable = (DataTable)Session["emailTable"];
foreach (DataRow row in emailTable.Rows)
{
SendMail(row["email"], row["name"], EmailTemplate);
}
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (!(e.Error == null))
{
SendMail("admin@address", "Error sending <br><br>" + e.Error.Message);
}
else
{
SendMail("admin@address", "emails sent successfully.");
}
//clear out the sessions created for sending this email
Session.Remove("emailTable");
}
private void SendMail(string email, string emailMessage)
{
MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress("from@address");
mailMessage.To.Add(new MailAddress(email));
mailMessage.Subject = Server.HtmlEncode(EmailSubject.Text.Trim());
mailMessage.Body = emailMessage;
mailMessage.IsBodyHtml = true;
SmtpClient smtpClient = new SmtpClient();
Object userState = mailMessage;
smtpClient.SendCompleted += new SendCompletedEventHandler(smtpClient_SendCompleted);
smtpClient.Timeout = 10000;
try
{
smtpClient.SendAsync(mailMessage, userState);
}
catch (SmtpException smtpExc)
{
MailMessageTxt.Text += "Error Code: " + smtpExc.StatusCode;
MailMessageTxt.Visible = true;
}
catch (Exception ex)
{
MailMessageTxt.Text += "Error is: " + ex;
MailMessageTxt.Visible = true;
}
}
void smtpClient_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
MailMessage mailMessage = e.UserState as MailMessage;
if (e.Error != null)
{
MailMessageTxt.Text = "Error occured, info=" + e.Error.Message;
MailMessageTxt.Visible = true;
}
}