patterncsharpMinor
Using SendAsync to send multiple emails
Viewed 0 times
usingemailsmultiplesendsendasync
Problem
My method for sending emails with
Sample
1 (1 sec)
2 (2 sec)
3 (4 sec)
4 (8 sec) and so on...
so I started to try
Additional Information about my methods:
will be translated to
Questions:
Send() is getting very slow when I send more than ten messages.Sample
1 (1 sec)
2 (2 sec)
3 (4 sec)
4 (8 sec) and so on...
so I started to try
SendAsync()public Boolean sendSMTPMail(string subject, string body, customer[] recipients, string attachmentFileName = null)
{
string css = "*{font-family: Arial, Helvetica, sans-serif;}";
SmtpClient client = new SmtpClient();
//some client settings..
MailMessage mm = new MailMessage();
mm.IsBodyHtml = true;
mm.From = new MailAddress(MainForm.from, MainForm.fromName, Encoding.UTF8);
mm.Subject = subject;
foreach (var recipient in recipients)
{
Application.DoEvents();
mm.To.Clear();
mm.To.Add(new MailAddress(recipient.getEmail()));
mm.AlternateViews.Add(getEmbeddedImages(css + doReplacements(body, recipient)));
try
{
//client.Send(mm);
client.SendAsync(mm, "userToken");
//client.SendMailAsync(mm);
}
catch (Exception)
{
return false;
}
}
return true;
}Additional Information about my methods:
getEmbeddedImages replaces imagePath with needed cid:xxxx and adds the image so it can be sent as a part of the email and not only as attachment.doReplacements replaces strings in my body to get the email text more recipient specific:Hello my name is %name%,
I am %age% years old.will be translated to
Hello my name is John Doe,
I am 100 years old.Questions:
- Is this the right way to do it?
- Is it important to send different userTokens?
- For what is this token needed anyway? Obviously it doesn't matter what I fill in there.
Solution
From the SendAsync docs:
After calling SendAsync, you must wait for the e-mail transmission to
complete before attempting to send another e-mail message using Send
or SendAsync.
So no, this may not work properly. You need to register an event handler on the
I'm going to be frank about this, the SmtpClient has an awful API. Your confusion is not your fault.
Your best bet would be to create a dictionary of recipients to use as a queue.
This is going to be a slow, fairly synchronous process, so you may want to spin up a background thread or task to run this on, if your program has other work to do while this is going on.
I really encourage you to thoroughly read through the documentation I linked to. It's an old part of the framework and not very user (or async) friendly.
Or forget all that and just use the newer SendMailAsync(MailMessage) method.
Just be sure to await the result.
Which means that you'll need to modify the signature of your method to be compatible with async/await.
After calling SendAsync, you must wait for the e-mail transmission to
complete before attempting to send another e-mail message using Send
or SendAsync.
So no, this may not work properly. You need to register an event handler on the
SmtpClient.SendCompleted event so that you know the message has sent successfully. I'm going to be frank about this, the SmtpClient has an awful API. Your confusion is not your fault.
Your best bet would be to create a dictionary of recipients to use as a queue.
- Send the first message and pass the dictionary key in as the token.
- When the message completed event occurs, use the token to remove the recipient from the dictionary and send the next message.
- Repeat until the queue is empty.
This is going to be a slow, fairly synchronous process, so you may want to spin up a background thread or task to run this on, if your program has other work to do while this is going on.
I really encourage you to thoroughly read through the documentation I linked to. It's an old part of the framework and not very user (or async) friendly.
Or forget all that and just use the newer SendMailAsync(MailMessage) method.
Just be sure to await the result.
try
{
await client.SendMailAsync(mm);
}Which means that you'll need to modify the signature of your method to be compatible with async/await.
Code Snippets
try
{
await client.SendMailAsync(mm);
}Context
StackExchange Code Review Q#150766, answer score: 8
Revisions (0)
No revisions yet.