+3  A: 

According to MSDN:

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 you could reuse the same instance but you must wait for the first mail to be sent.

Darin Dimitrov
Yes but doesn't that defeat the whole purpose of SendAsync? You may aswell call Send. What I am getting at is shouldn't SendAsnyc queue each message and send when the resources are available?
James
If you want to send emails in parallel you need different instances. Probably that's due to the way `SmtpClient` class is designed.
Darin Dimitrov
...all you have done is restated the question and agreed that it is factual.
David Pfeffer
I think my issue is really with how SmtpClient is designed. As if technically if you have 1000's of emails to send, that means you need to create 1000 SmtpClient's that are pretty much going to have the same configuration...seems a tad wasteful to me.
James
You could send the next message from the completed callback. That way you avoid locking up your program (or spawning millions of clients).
envalid
@James: No, Async means that your main thread is free to do something else, like preparing the next mail. It does not imply that SendAsync is re-entrant.
Henk Holterman
I think that's an intentional design limiting to you to think about sending emails. Not just fire up the SmtpClient and locks up the response stream while you're at it but *think* about really doing the Async stuff right.
chakrit
Right so say I need to send out loads of emails at any one time AND catch the callback of each email. Is the only plausible way to create multiple instances of SmtpClient?
James
@James, you could also write your custom class implementing the SMTP protocol class that can send many emails, but I think that creating multiple instances wouldn't be so much of a problem.
Darin Dimitrov
+4  A: 

According to the MSDN page on SmtpClient, the only purpose for SendAsync is to allow your current thread to continue processing instead of waiting for the transmission to process. The purpose of SendAsync isn't to allow you to send multiple messages at once, it's to allow you to continue processing while it sends the message. SendAsync and Send are both using the same pipeline, SendAsync just allows you to do other things while the message is sent.

Alexander Kahoun
So what would be the best workaround if you want to send multiple emails in the one go and still catch the callback? Creating multiple instances of SmtpClient?
James
+1  A: 

To address the underlying problem, you want to send (a lot of) emails as fast as possible. That means using a limited number of threads, and that number should be configurable. The optimum depends on hardware and bandwidth etc.

So, create N threads (you can use ThreadPool or BackgroundWorker), and let each thread process mails form a Queue, using SmtpClient.Send(), not SendAsync(). Feeding and using the queue is a standard Producer/Consumer problem, Fx4 has a set of nice classes for that. For Fx3.x you will have to shop around.

Henk Holterman
Thanks henk I think that should do what I am looking for!
James