Send mass SMTP emails is slow and give error after sending 10-12 emails

989 Views Asked by At

I am sending SMTP email using code:

protected void btnSendEmailToAll_Click(object sender, EventArgs e)
{
    string username = Master.User;

    //Create a temporary DataTable
    DataTable dtCustomers = new DataTable();
    dtCustomers.Columns.AddRange(new DataColumn[3] { new DataColumn("name", typeof(string)),
                new DataColumn("email",typeof(string)), new DataColumn("EmailSentOn",typeof(string)) });

    //Copy the Checked Rows to DataTable
    foreach (GridViewRow row in Grid.Rows)
    {
        // Only look in data rows, ignore header and footer rows
        if (row.RowType == DataControlRowType.DataRow)
        {
            CheckBox ChkBoxRows = (CheckBox)row.FindControl("chkrow");

            if (ChkBoxRows.Checked == true)
            {
                string Name = (row.FindControl("lblname") as Label).Text.ToLower();

                dtCustomers.Rows.Add(Name, (row.FindControl("lblemail") as Label).Text, (row.FindControl("lblEmailsentOn") as Label).Text);

                var id = Grid.DataKeys[row.RowIndex].Value;
                using (var db = new DatabaseHelper())
                {
                    db.ExecNonQuery(Queries.UpdateReminderEmailSentData, "@RW", id);
                }
            }
        }
    }

    string subject = "My Subject";

    //Using Parallel Multi-Threading send multiple bulk email.
    Parallel.ForEach(dtCustomers.AsEnumerable(), row =>
    {
        string body = this.PopulateBody(row["name"].ToString(), row["EmailSentOn"].ToString(), username);
        SendMassEmail(row["email"].ToString(), subject, body.ToString());
    });

    ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "alertMessage", "alert('Email Sent Successfully')", true);
    BindGrid();
}

PopulateBody fuction:

private string PopulateBody(string name, string date, string username)
{
    string body = string.Empty;
    using (StreamReader reader = new StreamReader(Server.MapPath("~/followupemailtemplate.html")))
    {
        body = reader.ReadToEnd();
    }
    body = body.Replace("{Name}", name);
    body = body.Replace("{Date}", date);
    body = body.Replace("{UserName}", username);

    return body;
}

SendMassEmail Function:

private bool SendMassEmail(string recipient, string subject, string body)
{
    var smtp = new SmtpClient()
    {
        Host = WebConfigurationManager.AppSettings["Host"],//smtp.gmail.com
        EnableSsl = Convert.ToBoolean(WebConfigurationManager.AppSettings["EnableSsl"]),//true
        UseDefaultCredentials = true,
        Credentials = new System.Net.NetworkCredential(WebConfigurationManager.AppSettings["UserName"], WebConfigurationManager.AppSettings["Password"]),
        Port = int.Parse(WebConfigurationManager.AppSettings["Port"])//587
    };
    using (MailMessage mailMessage = new MailMessage())
    {
        mailMessage.From = new MailAddress(WebConfigurationManager.AppSettings["UserName"], "My Email");
        mailMessage.Subject = subject;
        mailMessage.Body = body;                    
        mailMessage.IsBodyHtml = true;
        mailMessage.To.Add(new MailAddress(recipient));
        smtp.Send(mailMessage);
    }
    return true;
}

It takes 30s to send five emails:(

I tried using Threads like(even i have been suggested that there's no need to use threads if we are using parallel.foreach):

Thread T1 = new Thread(delegate ()
            {
                using (MailMessage mailMessage = new MailMessage())
                {
                    mailMessage.From = new MailAddress(WebConfigurationManager.AppSettings["UserName"], "My Email");
                    mailMessage.Subject = subject;
                    mailMessage.Body = ShowBody;
                    mailMessage.IsBodyHtml = true;
                    mailMessage.To.Add(new MailAddress(recepientEmail));

                 smtp.Send(mailMessage);                   
                }
        });
T1.Start();

That is fast but not send all email some gone unsent.

i.e. after sending 10-12 emails or sometimes even less it throws exception:

An unhandled exception of type 'System.Net.Mail.SmtpException' occurred in System.dll Additional information: Service not available, closing transmission channel. The server response was: 4.7.0 Temporary System Problem. Try again later (WS). u12sm5363862pfg.146 - gsmtp

Don't know whats wrong. Any help regarding this would be appreciated.

Plz dont mark it duplicate or anything as i searched lot solutions but coudn't find correct one.Thanks in advance!!

2

There are 2 best solutions below

1
On

I'm using this on my project. Its working good. no any error appear after send 10-12 emails or more.

public static void Send(string from, string to, string cc, string subject, string message, string[] attachment, byte[] fileByte, string fileByteName)
        {
            string ccChar;
            if (!string.IsNullOrEmpty(cc) && cc.EndsWith(","))
                ccChar = cc.Remove(cc.Length - 1, 1);
            else
                ccChar = cc;

            if (smtp_address == "")
            {
                smtp_address = ConfigurationManager.AppSettings["smtp_address"];
                smtp_port = int.Parse(ConfigurationManager.AppSettings["smtp_port"]);
                smtp_user = ConfigurationManager.AppSettings["smtp_user"];
                smtp_password = ConfigurationManager.AppSettings["smtp_password"];
                smtp_ssl = bool.Parse(ConfigurationManager.AppSettings["smtp_ssl"]);
            }

            MailMessage mm = new MailMessage(from, to, subject, message);
            mm.Bcc.Add(ConfigurationManager.AppSettings["mailAlertMonitor"]);

            mm.IsBodyHtml = true;
            if (!string.IsNullOrEmpty(ccChar)) mm.CC.Add(ccChar);

            if (fileByte.Length != 0 && !string.IsNullOrEmpty(fileByteName))
            {
                mm.Attachments.Add(new Attachment(new MemoryStream(fileByte), fileByteName));
            }

            if (attachment != null)
            {
                foreach (string file in attachment)
                {
                    if (!string.IsNullOrEmpty(file))
                    {
                        Attachment attc = new Attachment(file);
                        mm.Attachments.Add(attc);
                    }
                }
            }

            SmtpClient smtp = new SmtpClient(smtp_address, smtp_port);
            smtp.Credentials = new NetworkCredential(smtp_user, smtp_password);
            smtp.EnableSsl = smtp_ssl;

            smtp.Send(mm);
            InsertSendEmailLog(from, to, cc, ConfigurationManager.AppSettings["mailAlertMonitor"], subject, message);
        }

I hope it help you.

3
On

try like this and let me know.

        private static string smtp_address = "";
        private static int smtp_port = 587;
        private static string smtp_user = "";
        private static string smtp_password = "";
        private static bool smtp_ssl = false;
        private bool SendMassEmail(string from, string to, string cc, string subject, string message, string body)
        {
            smtp_address = WebConfigurationManager.AppSettings["Host"];
            smtp_port = int.Parse(WebConfigurationManager.AppSettings["Port"]);
            smtp_user = new System.Net.NetworkCredential(WebConfigurationManager.AppSettings["UserName"];
            smtp_password = WebConfigurationManager.AppSettings["Password"]);
            smtp_ssl = smtp_ssl;

            MailMessage mm = new MailMessage(from, to, subject, message);
            SmtpClient smtp = new SmtpClient(smtp_address, smtp_port);
            smtp.Credentials = new NetworkCredential(smtp_user, smtp_password);
            smtp.EnableSsl = smtp_ssl;

            smtp.Send(mm);
            return true;
        }