We have been having issues when sending mass emails out (roughly 60k ~ 70k). We usually get the Out of Memory exception at the 30k mark. We loop through a list of clients and we modify a string by passing parameters according to the client which is later loaded into the body of the MailMessage object. This error happens when we use threads to accelerate the process. We dont get the error when not using threads however the process takes about 9 hours, which is not acceptable to us. What could we do to control memory behaviour or anything that could get through the whole list without having this error? Please see parts of our code below:
foreach (var candidate in z)
{
var mailer1 = new MailerProto();
string jobList = "";
foreach (var item in candidate)
{
string title = item.title;
jobList += "<a href='" + "https://mydomain/" + "job/" + title + "-" + item.jobId + "?emailId=" + item.accountId + "'>" + title + " </a><br class='br' />";
}
string[] args = new string[]
{
AppConfig.Url,
candidate.FirstOrDefault().firstName,
jobList,
candidate.FirstOrDefault().accountId.ToString()
};
tasks[taskCounter] = mailer1.SendEmail(
from: AppConfig.NoReplyMail,
to: candidate.FirstOrDefault().email,
subject: "We have found jobs just for you!",
htmlContent: content,
args: args,
skipSubscription: true
);
taskCounter += 1;
if (taskCounter == 5000)
{
Task.WhenAll(tasks);
tasks = new Task[5000];
taskCounter = 0;
GC.Collect();
//System.Threading.Thread.Sleep(500);
}
}
Then part of the SendMail function
for (int i = 0; i < args.Length; i++)
{
htmlContent = htmlContent.Replace("{" + i + "}", args[i]);
}
try
{
using (SmtpClient smtpClient = new SmtpClient())
{
MailMessage messageMail = new MailMessage();
messageMail.To.Add(to);
messageMail.From = new MailAddress(from, displayName);
messageMail.Subject = subject;
messageMail.IsBodyHtml = true;
messageMail.Body = htmlContent;
if (attachments != null)
{
foreach (var item in attachments)
{
messageMail.Attachments.Add(new Attachment(item.Value, item.Key));
}
}
smtpClient.SendCompleted += (s, e) =>
{
smtpClient.Dispose();
messageMail.Dispose();
};
await smtpClient.SendMailAsync(messageMail);
smtpClient.Dispose();
messageMail.Dispose();
}
catch (Exception e)
{
MailMessage messageMail = new MailMessage();
messageMail.To.Add("errors@mydomain");
messageMail.From = new System.Net.Mail.MailAddress(AppConfig.NoReplyMail);
messageMail.Subject = "Api Error";
messageMail.IsBodyHtml = true;
messageMail.Body = e.Message + "\n " + e.InnerException + "\n" + "to: " + to + "\n subject:" + subject + "\args: " + result;
using (var smtpClient = new SmtpClient())
{
smtpClient.Send(messageMail);
}
}
}
Yes we understand that we are using "using" and multiple "Dispose", but none of them have any effects. This is just part of our tests.