3

I have part of a project whereby I need to send 1 to up to 2000 emails from a webpage. One open source bug tracker used a Thread to send emails but it was riddled with bugs.

So just want to know if anyone has any ideas of how I can create a procedure that send up to 2000 emails a go?

I was told by one of my colleagues to leave it as one process (normal routine sending one email at a time) as it won't take long to process all the emails anyway. Doesn't seem right and I want to use threading... maybe I like complex routines?

[Extra] I have something like: foreach(string email in emailAddresses) { MailMessage mailMessage = new MailMessage(); mailMessage.To.Add(...) ... SmtpClient client = new SmtpClient(); client.Send(mailMessage); }

Dexter
  • 18,213
  • 4
  • 44
  • 54
Rob
  • 221
  • 5
  • 11
  • Maybe see http://stackoverflow.com/questions/1607178/background-task-with-an-asp-net-web-application But from other threads I've read 2000 is a lot at once, and some SMTP servers might assume you're spamming - you might have more problems than just the background task to send. – Rup Dec 06 '10 at 17:36
  • 1
    If you use threads, how many would you create? Surly not 2000. You'd still be having a single thread processing a large number of emails. Also, the more threads you have, the less bandwidth available to each thread for sending email (the slow part of the operation), thereby resulting in performance on par with the original straightforward (single-threaded) solution. – Kirk Woll Dec 06 '10 at 17:36
  • You;re right. The idea is ONE thread only to process the emails so I can move the user away from the webpage... – Rob Dec 06 '10 at 17:40
  • But I am beginning to see there could be issues here with sending so many emails... – Rob Dec 06 '10 at 17:40
  • 3
    Heh, the irony of a bug tracker riddled with bugs... :) – BBlake Dec 06 '10 at 17:44
  • Yes I know... bug tracker with bugs... improving though :) – Rob Dec 06 '10 at 17:52

4 Answers4

5

Use System.Net.Mail to send the messages; however you should use .NET 4 to avoid any connection issues, as there was a bug filed on the Connect website that will cause your messages to not get sent.

Don't use threading for three reasons:

Reason 1: A MTA is made to handle message retries and can handle failures. Your code may not be robust enough to handle this. System.Net.Mail is not able to do this out of the box.

Reason 2: If you do use threading, you will overwhelm the target SMTP server and it will block you. Most Windows SMTP relays have a default block of more than 15 (or 25?) concurrent connections.

If you're dealing with Exchange 2010, or 2007, then there is a throttling feature that gets activated if you send more than x messages per minute. This is a per MTA setting that will need to be adjusted to permit your situation.

Reason 3: The preferred way to do this is to have a dedicated IIS SMTP server (or Exchange...) that allows concurrent connections at high volume. Just use Sys.Net.Mail to hand the delivery task to the mail infrastructure. Not much is needed for a mail infrastructure. Just have a MTA that allows you to relay and it will "smart host" on your behalf out to the internet.

More questions on how to set up the MTA can be answered @ serverfault.

However

You may want to use threading if your sending an email from an ASP.NET webpage... or will otherwise block the UI. Other than that, I don't see a need to run concurrent threads for the email generation task.

Lastly, if you're sending the same message to many recipients, you can either use a distribution list or append many target recipients to the same message.

makerofthings7
  • 60,103
  • 53
  • 215
  • 448
  • OK. I used Net Mail anyway, but the system had to wait for all emails to be sent before continuing. I need to understanbd your second paragraph though, but thanks for your input :) – Rob Dec 06 '10 at 17:44
  • I realised I was confusing, so I edited the response above. Also, since you're new, feel free to upvote responses you like. – makerofthings7 Dec 06 '10 at 17:47
  • I do understand what you are saying and I now understand what my colleague was saying. So again thanks. – Rob Dec 06 '10 at 17:51
  • I am using .NET 4 and we have a dedicated IIS SMTP server. – Rob Dec 06 '10 at 17:52
  • "Lastly, if you're sending the same message to many recipients, you can either use a distribution list or append many target recipients to the same message.". Need to include the email in the "to" not cc or bc and i i do include ALL email addresses in the to then everyone get to see everyone else's email address... or have I misunderstood? – Rob Dec 06 '10 at 17:58
  • If you want to hide the recipient, just add them to BCC. You can have a blank to and blank cc. – makerofthings7 Dec 06 '10 at 18:01
  • I would test the effects of putting every user in a single field... there may be limits to what you can do. – makerofthings7 Dec 06 '10 at 18:02
  • OK. Still not sure using bcc is a good idea though and as you say I am certain there will be limits. Basically it's a file repository which emails users (who want to be emailed) informing them a file has been uploaded to a folder. It will also have to be personal i.e. the user's name in the message. – Rob Dec 06 '10 at 18:15
  • Probably best is (if your using exchange) is to have a mail enabled Distribution List created in Active Directory. Send email to this DL in the BCC and your job is done. – makerofthings7 Dec 06 '10 at 21:18
  • Oh OK. Interesting idea, will look into it. – Rob Dec 06 '10 at 21:22
1

You probably don't want to send 2000 emails on a thread that is servicing http requests. The user that submitted the request will be waiting for the server to respond until the emails send, and that's one less thread available for processing requests from other users. If you have many such requests it could drag down server performance.

Instead, I would post the request to a message queue, and have a seperate service process items from the queue and send emails.

Creating background threads in the asp.net app is another possibility, but then you end up in a situation where either:

  1. You have to have your own task queue , separate from the one used by the normal thread pool.
  2. Your email tasks are competing with, and potentially starving, the tasks for serving http requests.

That being said, there are deployment scenarios (a shared server, customer deployments) where the introduction of a second process is not desirable. If you don't have those constraints, however, I would go with the "separate process" because it's easier to scale your web site if it's focused on serving UI requests and leaves "fulfillment" tasks to a different service.

Scott Wisniewski
  • 24,561
  • 8
  • 60
  • 89
  • Excellent thank you. It does look like I need to seriously think how I manage these emails. I must admit I was expecting simple answers, but this has proved me that I need to rethink my thought process with limited time and resources. Again thanks. – Rob Dec 06 '10 at 18:04
0

I think 2000 will take a long time (if it's a web page and the user is waiting for the page). It depends on your implementation, but you're doing this frequently you might want to have a "email thread" that's already been created. If there are no emails to send, then the thread can be suspended and not be consuming any resources. Then when the emails need to be sent you fill up an email queue with those emails and wake up the thread to start sending (if it is not already doing so).

Keltex
  • 26,220
  • 11
  • 79
  • 111
0

If you're sending more than about 50 at a time, you need to contract out to a service that does this for you. Otherwise your messages will end up in people's spam folders.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794