Bulk mailing using SMTP server in ASP.Net - c#

We are sending free newsletters to all users who have registered for this service. Since these newsletters are sent free of cost we expect at least 5000 subscribers within a month. I am worried whether bulk mailing using SMTP server concept will cause some issue. First we thought of developing a windows service which would automatically mail to subscribers on periodical basis but the business users have given requirement that the newsletters should be editable by the admin and then only mailed to users so we had to develop this functionality in website itself!. I get the subscribers for the particular user in data table and then mail to each user inside for loop, will this cause any performance issue?
The code is pasted below:
dsEmailds.Tables[0] has list of newsletter subscribers.
for (iCnt = 0; iCnt < dsEmailIds.Tables[0].Rows.Count; iCnt++)
{
MailMessage msg = new MailMessage();
msg.From = new MailAddress("newsletters#domainname.com", "test1");
msg.To.Add(dsEmailIds.Tables[0].Rows[iCnt]["mailid"]);
msg.IsBodyHtml = true;
msg.Subject = subject;
AlternateView av1 = AlternateView.CreateAlternateViewFromString(MailMsg, null, System.Net.Mime.MediaTypeNames.Text.Html);
av1.LinkedResources.Add(lnkResLogo);
av1.LinkedResources.Add(lnkResSalesProperty);
av1.LinkedResources.Add(lnkResLeaseProperty);
msg.AlternateViews.Add(av1);
SmtpClient objSMTPClient = new SmtpClient(System.Configuration.ConfigurationManager.AppSettings["mailserver"].ToString());
objSMTPClient.DeliveryMethod = SmtpDeliveryMethod.Network;
objSMTPClient.Send(msg);
}
Any suggestions would be great!

You should STOP and consider all sort of things:
Black List: with that amount you will for sure be balck listed in severeal ISP's / Mail Servers, and you need to prove that the received user asked for such email and wait 1 to 3 month process while they remove the flag
You need to send emails in blocks, not more than 250 at each time, use different IP's machines to send more emails (more blocks)
please read some nice guidelines for doing all this, you can find it in MailChimp and Campaign Monitor
Free Email Marketing Guides
You should use a service, like Mailchimp (now it's free to 1000 subscribes, 3000 sends a month) but prices are very cheap and they have an API that you can easily add, create, send and you will get all those nice reports on how opened, what did they do, etc ...
Campaign Monitor is fantastic as well, but a little bit more expensive but great as you can brand the entire UI and sell as a service to your customers (if you are thinking of doing such thing in the near future).
I hope it helps.
give them a try, I'm a happy customer.

The main problem i see is that you may encounter a page timeout. The best way to do it in my opinion would be to set up a service that will take care of mail-related uses (templating for example) by reading from a queue. Your website could just post the mails you expect to send in the queue, then offer a basic administration panel to manage the service and get some stats.
You can use open-source & xcopy-friendly systems for the queue like Rhino queue, or ServiceBus, and Topshelf for services if you want easy setup
But i'd recommend you not to send bulk emails in the webpage

There is a SendAsync method that will actually queue up these requests and send them async from your thread. This way you can prevent the timeout and you can probably send (ie. queue) 5000 emails within seconds.

Write to a pickup queue of an SMTP server running on the machine (IIS includes one). This is the fastest and most efficient method.
OR
Setup a custom thread pool in your code and offload the task to it. That way worker threads from ASP.NET thread pool are ready to serve incoming requests and won't be occupied with sending mails (that depends on how high your server load is, of course - go ahead with ASP.NET thread pool using async methods if you don't care about the load/can afford it).

Related

Call a webservice or run code every time a person is mentioned or receives private message on Yammer and Bot Framework

I am trying to find a way to run a piece of code (MS Bot Framework, C# hosted on Azure) every time a person is mentioned on Yammer or receives a direct message.
The two ways that I tried:
1) The best I came up with for now is to enable email notifications from Yammer, and watch a mailbox for emails from notifications#yammer.com. Microsoft's Bot Framework has a one-click setup for monitoring emails, so that works.
But notification emails arrive with a 15 minutes delay, which renders this pretty useless as I need near-instant performance.
Finally, it looks like this approach simply doesn't work because the MS Bot Framework seems to reply to the email address who sent the email, rather to the one that I specify:
if (activity.ChannelId == "email" && activity.From.Id == "notifications#yammer.com")
{
var newActivity = activity.CreateReply();
//doesn't work, sends email back to the activity.From.Id
newActivity.Recipient.Id = "k48#gmail.com";
newActivity.Text = "I got a message from " + activity.From.Name + "!";
BotUtils.SendActivityToChat(newActivity);
}
I could write my own code for sending emails to an arbitrary recipient, but then there is still the problem with 15 min delay.
2) Another approach I am using is to poll Yammer's API every minute to see if there are new messages, but this is still not instant, and I'm not sure if my account gets banned if I keep polling the API way too often. (Update: the official rate limit is 1 poll per minute, or else they ban you).
Is there something I missed? How else would you run a piece of code every time you get a message or mention on Yammer?
The BotFramework will not allow you to reply to a message to a different address than the sender. However, if the recipient is one that the bot has received a message from before, you can send them a Proactive Message. To send a proactive message, you can keep the ServiceUrl and the user’s ChannelAccount (extracted from one of the messages from that user) and use this data to send a new activity from your bot to that user.
Here is an example in C#
Here is an example in Node.js

Sending emails at certain time

I would like to send email using SMTP Server, but in the certain time.
Is there possibility to setup some option so it will be in the queue on SMTP Server until specific time and date?
Idea is to avoid using Windows Service or extra table in DB
MailMessage message = new MailMessage("no-reply#tttt.com", "xxxx#gmail.com");
message.BodyEncoding = System.Text.Encoding.UTF8;
message.IsBodyHtml = true;
message.Subject = "Publishing Notification";
message.Body = "tes";
message.DeliveryNotificationOptions = DeliveryNotificationOptions.Delay;
SmtpClient client = new SmtpClient("xxxx", Int32.Parse("25"));
client.Send(message);
Making something execute at a given time is an easy problem presuming you've got a process to host it. But it seems like your client is refusing to get there. Here are two ways to approach this without:
Use Sql Server Jobs to execute a database mail task. This could be a very easy on-ramp depending on where the data is coming from.
Use a scheduled task to execute a command line program. Or use the Sql Job Manager to execute the program for that matter if getting a sql job in there is easier than standing up a scheduled task.
Quartz.NET is a great library and we use it a lot but you still need a constantly running service to execute scheduled tasks there. So, if you can piggyback this on your web app Quartz would work but if not then you'd be looking at writing a service. And from there you'd be better off just making it a scheduled task since there is no reason for this to be a service other than scheduling.

C# Sending a large number of emails using System.Net.Mail

We have an ASP.NET MVC application that sends a number of reports via e-mail to clients each month. Each e-mail attaches a monthly statement. Currently we have around 70 clients but this will hopefully increase over time. We have been seeing issues that a number of e-mails are not getting sent. We use the System.Net.Mail API.
Here is the code we are using, is there a better approach?
foreach(string client in clients){
SmtpClient client = new SmtpClient("server.com");
BackgroundWorker emailInvoker = new BackgroundWorker();
emailInvoker.DoWork += delegate
{
// Delay to prevent flow control, try later Relay error
Thread.Sleep(TimeSpan.FromSeconds(2));
client.Send(message);
}
emailInvoker.RunWorkerAsync();
}
We have been seeing issues that a number of e-mails are not getting
sent.
The larger (and more likely) problem than some of them aren't getting sent is that many of them are not getting delivered.
...is there a better approach?
In most cases. Jeff Atwood goes over many of the problems with sending email in this blog post. That post was almost 3 years ago and even then, the first comment recommends using postmark. I've used postmark and it reliably handles the problem of getting your emails out through code at a good price. That said, there are better solutions on the market now, the one my company is currently very tempted to switch to is mandrill. Slightly better pricing, awesome analytics.
Because this is an ASP.NET MVC application, you need to be aware of your application pool. Creating multiple threads will exhaust your app pool quickly, and IIS maybe doing some funky things to keep things from literally grinding to a halt while emails are being sent. I would take a look at Can I use threads to carry out long-running jobs on IIS? if you're interested on learning more.
If I were to rewrite that, I would create one thread with the foreach and email sending, instead of a thread for each customer.
BackgroundWorker emailInvoker = new BackgroundWorker();
emailInvoker.DoWork += delegate
{
// get your clients here somehow
foreach(string client in clients){
SmtpClient client = new SmtpClient("server.com");
// Delay to prevent flow control, try later Relay error
Thread.Sleep(TimeSpan.FromSeconds(2));
client.Send(message);
}
}
emailInvoker.RunWorkerAsync();

AWS / SES Email sending... What's been your experience?

Anyone using AWS SES for bulk email sending?
We have a company mailing list, and i am using a multi-threaded application (.NET SDK) to send emails concurrently, to get the emails out to our list as quickly as possible.
We have been able to send aproximately 8 emails per second... seems pretty low, especially considering an SES inposed limit of 90/second... We are nowhere near that.
Can anyone tell me the maximum number of emails they have managed to send per second, using SES?
Trying to set a reasonable benchmark.
Thanks!
Update
You are currently using the AWS SDK for .NET for sending via SES, which facilitates the original API internally still. AWS meanwhile introduced SMTP Support for the Amazon Simple Email Service (SES), which supposedly makes it even easier for you to send transactional or bulk email:
You no longer need to write any code to gain the efficiency and
deliverability benefits of SES. Instead, you use the SES tab of the
AWS Management Console to create an SMTP user and a set of
credentials, and then you use those credentials to configure the email
client of your choice:
A simplistic C# example (i.e. without throttling etc.) is provided in Sending Email From Application Programs:
public static void SendWithSMTP(string username, string password, string host,
int port)
{
using (var client = new System.Net.Mail.SmtpClient(host, port))
{
client.Credentials = new System.Net.NetworkCredential(username, password);
client.EnableSsl = true;
client.Send("from#example.com", "to#example.com", "This is a test subject.",
"This is a test email message body.");
}
}
To take this even further you might want to add your own MTA into the mix, see Integrating with Your Existing Email Server:
If you currently administer your own email server, you can use the
Amazon SES SMTP endpoint to send all of your outgoing email to Amazon
SES. There is no need to modify your existing email clients and
applications; the changeover to Amazon SES will be transparent to
them.
This would relieve your application from handling the SES throttling at all and provide respective wiggle room eventually, however, it obviously requires the MTA administrator to manage this in turn by tuning its sending/relay queues accordingly - this may or may not be knowledge floating around in your organization already, but should provide a more robust SES experience in comparison to handling this per application.
Initial Answer
You might be aware of that already, but since there is likely no definite answer regarding your question, I'd like to highlight the dynamic Amazon SES approach to this again (which is basically independent from any specific AWS SDK in use):
1) You'll need to Request Production Access to Amazon SES before even thinking about bulk mailings:
To help protect our customers from fraud and abuse and to help you
establish your trustworthiness to ISPs and email recipients, we do not
immediately grant unlimited Amazon SES usage to new users. New users
are initially placed in the Amazon SES sandbox. [...] the following restrictions are in effect:
Emails can be sent only to and from verified email addresses.
You can send a maximum of 200 messages per 24-hour period.
You can send a maximum of one message per second.
2) Once granted, your sending limits will be gradually increased based on a number of factors as explained and illustrated in How Amazon SES Sets Sending Limits - particular noteworthy are:
If you have recently been granted production access to Amazon SES, you
can initially send up to 10,000 emails per 24-hour period. After a few
days, if you continue to send high-quality email, your quota will
quickly be raised into the tens of thousands. [emphasis mine]
Furthermore, initially you should be able to send at a maximum rate of 1 email per second. Your maximum sending rate should increase to 10/s in 3 day, 50/s in 10 days and 90/s in 2 weeks, as per the table they provide.
The aggressive quota adjustment pattern in use initially is apparently reduced a bit later on:
Subsequent quota increases occur more gradually; you will need to
continue increasing your sending volume. If your volume stays close to
your quota without exceeding it. Amazon SES will detect this usage
pattern and automatically increase your quota. [emphasis mine]
We had good success with obeying the latter specifically, i.e. as long as we stayed significantly below our sending limits, these limits didn't change at all, but started to do so as soon as we approached them indeed.
Obviously you should supervise this process to ensure you are operating within the current limits and produce low or no bounces etc. - this is addressed in Monitoring Your Sending Limits as well as Monitoring Usage Statistics accordingly:
We strongly encourage you to monitor your usage of Amazon SES to
ensure that you operate within your sending limits. You also need to
be aware of any bounces or complaints that occur, so that you can
determine and resolve the root causes. As you successfully send more
email, you should notice that Amazon SES is gradually adjusting your
sending limits so that you can send still more email, and at a faster
per-second rate. [emphasis mine]
Good luck!
Here is an example I'm using to do bulk email with AWS Simple Email Service
public SendEmailResult SendEmail(ArrayList toemail, string subject, string bodystring, Enums.EmailTypes emailtype)
{
var awsConfig = new AmazonSimpleEmailServiceConfig
{
UseSecureStringForAwsSecretKey = true
};
var awsClient = new AmazonSimpleEmailServiceClient(RoleEnvironment.GetConfigurationSettingValue("AwsAccessKeyId"),
RoleEnvironment.GetConfigurationSettingValue("AwsSecretKey"),
awsConfig);
//EXAMPLE
var to = new ArrayList
{
"email1#example.com",
"email2#example.com",
"email3#example.com"
};
var dest = new Destination();
dest.WithToAddresses((string[]) to.ToArray(typeof (string)));
var body = new Body
{
Html = new Content(bodystring)
};
string fromemail=string.Empty;
switch (emailtype)
{
case Enums.EmailTypes.Notification:
fromemail = "notification#example.com";
break;
case Enums.EmailTypes.Support:
fromemail = "support#example.com";
break;
}
var title = new Content(subject);
var message = new Message(title, body);
var ser = new SendEmailRequest(fromemail, dest, message);
SendEmailResponse seResponse = awsClient.SendEmail(ser);
return seResponse.SendEmailResult;
}

Is there a way to perpetuate the email session in a C# application?

Using this code, I can send emails to people. However, every time I press the send button, I think I log back in, correct?
Is there a way to perpetuate my login session, or is the way it's always been done ("I'm making a newbie assumption")?
var client = new SmtpClient("smtp.gmail.com", 587)
{
Credentials = new NetworkCredential("papuccino1#gmail.com", "password"),
EnableSsl = true
};
client.Send("papuccino1#gmail.com", "stapia.gutierrez#gmail.com", "test", "testbody");
Console.WriteLine("Sent");
Console.ReadLine();
The code you have is fine. Yes, the smtp service is sending the credentials to the smtp server each time you send the email.
From a coding perspective, this is the preferred way of doing things. If you are batching emails, then you would simply put the .Send method call inside the loop while the new SmtpClient call is above it.
You only want to leave the connection open long enough to do the job then you close it. Otherwise you run the risk of the app blowing up or otherwise failing to close the connection later. Servers only have a limited number of connections that they can handle. If most apps left them open for long periods of time then other users would have a hard time getting in.
Most mail clients, open the connection, send any emails in the outbox, grab any new emails, then close the connection. When a timer goes off, it will do the process over again.
Outlook tied to Exchange works slightly differently because there is a push component (from the server).
Each SMTP session starts with authentication usually. As far as I know there is no way to keep a session open to a SMTP server. It is possble to send a number of emails in a batch though, this is probably what happens when you use an email client.

Categories