Question

I am in the process of launching a new version of a survey system on a Windows 2008 VPS, built with ASP.NET MVC (old version was ColdFusion).

An important part of the system's operation is to send out a batch of 10,000 emails per week to our subscribers, who then complete a short online survey.

I am using the VPS's own SMTP server for the mailout, same as with the old version, but have been finding much longer batch mailout times than before.

My investigations indicate that my looping code is efficient, and almost all of the delay is occurring during the actual SMTP send operation.

Research further indicates that this is to be expected when processing a long list of mails in sequence, and that email batches are usually done by feeding a managed list of multiple concurrent SMTP sessions operating asynchronously with callbacks. Presumably this is what the cfmail (which we used before) tag was doing under the hood.

So it looks like I will need to manage an array of System.Net.Mail.SmtpClent sessions in ASP.NET to replicate this behavior, and use the SendAsync method (which generates its own thread to complete each task).

My question is, can anyone see any potential issues with this approach of running multiple threads and up to 10, 20, 50 or 100 SMTP sessions simultaneously on our server, within the HTTP request that initiates the mailout?

Was it helpful?

Solution

That's a good approach, but you don't want to have too many concurrent SMTP sessions, for several reasons :

  1. You will exhaust your system resources if you create tens or hundreds of threads through SmtpClient.SendAsync(). The MSDN documentation for SendAsync doesn't state explicitly that one thread is created per call, but it tells that you can't call SendAsync until the previous call is completed. This sounds like the class spawns its own thread :

    "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."

  2. Having many simultaneous connections coming from the same IP address is a typical spammer behaviour. Most mailservers limit the number of simultaneous connections coming from the same IP address, and may eventually blacklist the address. If you have control over the destination SMTP server, this issue could be work around by disabling limits for your IP address.
  3. If you send too many messages too quickly, and that your IP address is not whitelisted by the targeted mail server, the latter may willingly slow you down to save resources for other SMTP clients. This technique is called "tarpiting". The server usually limits the number of messages received per second from a given IP. If this happens, increasing the number of threads won't make any difference, you'll have to talk to the mail server admin so that he whitelists your ip address, or increase limits.
So, go with your solution, but limit yourself to a handful of SmtpClient instances (I would start with 4 or 5). And use a shared thread-safe list of pending MailMessage, from which each SmtpClient will pick the next message to send when its SendAsync() completion callback is called.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top