Send out thousands of individual emails without looping - c#

I have a site that people put stuff for sale on.
Every month, every user who has something for sale will get sent an email by a windows service asking them if their item has been sold and giving them a custom link to click to confirm it hasn't (as it's against the user agreement for items to remain on the site that are sold).
First I must run a query to get all the unsold items and with the related users email.
Currently I am looping all these and generate a custom email for each person and sending them out as individual emails.
foreach (Item unsoldItem in unsoldItemsCollection)
{
//generate email
string email = GenerateUnsoldEmail(itemName, itemPrice);
Utils.Sendemail(unsoldItem .UserEmail, "no-reply#website.com", "Unsold Item", email);
}
(this is kind of pseudo code, but this is pretty much what I'm doing)
My problem is there could possibly be thousands ( if it takes off, maybe millions :) ) of items in that loop all requiring emails, which I think is going to cause problems.
What other way could I do this?
Bex

I would do this asynchronously so that the program is not halted until the current email is sent.
You can't mail merge since all emails are different; links inside it will be different... unless the body of the email has some sort of landing page that forces the user to log in and then redirects the user to a specific page where all the items for the user are listed and he is asked to remove the ones already sold. In that case, you could send an email instead of thousands.
SmtpClient has an async version of the Send method

If you want to do something for every item in a collection, you will have to use some kind of loop (or something equivalent, like recursion). There is no way around that.
You should stop worrying about potential problems. If you think this code will be a performance problem, measure it and find out how fast it actually is and how many emails it will handle.
You're worried it might take hours to send all the emails. Is that actually a problem? Why?
You're also worried it might take too much memory. If you can't fit all items into memory at once, you should process them in batches: get for example 1000 at a time, process them, and then get another 1000.

You can create a windows service which will send all your emails once a day.
Or, even simpler, you can create a small console utility which does the same and run it as a scheduled task.

Related

how to control the outugoing order of multiple emails from .NET sendgrid

If my .NET app sends out one email followed by another, sometimes the 2nd arrives 1st.
Is there a way to control the order they get sent.
Not really, email delivery is a function of the server. The best you can do is to delay the second email by some arbitrary amount of time, but even that is no guarantee. You could maybe use a scheduling component to facilitate that. Why does the order matter? Maybe knowing that will help us find an answer for you.

What is the best approach when caching info?

My app sends emails. I currently:
get a list of customers from the DB (objects)
get a list of their email types from the DB (ditto)
get a list of email recipients/unique data for the email from the DB (again)
use the data above to generate mailmessages
loop through the mailmessages and send them out while logging the smtp status
Now this behavior is fine when your sending off 500 emails, but what is the impact if it's 10,000+ emails? I imagine at some point the amount of objects I am storing until I get to step 5 is considerable. How can I measure it to know I am approaching capacity? I figure I can at least time this whole scenario to understand how long it takes as a clue toward when it is becoming a drag on the system.
Would it be better to run this scenario on a per customer basis? It seems that would be less efficient, hitting the DB potentially hundreds of times instead of 3 or so. I know the logging will be one off hits back to the DB.
I am looking for an approach, not a code resolution. I got in trouble last time I didn't specify that.
I guess this depends on several things, such as how big/powerful your system is (database capacity, processing/memmory and more?), and how important it is to send out these mails quickly, among other things.
An idea might be to use a temporary DB table to store the info from steps 1-4. You could do this in batches(as Blogobeard mentioned), or all at once, depending on efficiency. The actual mailing-job could then also be split into batches, and when a mail is sent, that customer`s info would be deleted from the temp-table.
There are probably several ways to fine-tune this, and it's probably easier to give a better advice once you've tried something, and have some specific results to act on.

Changing the status of an item based on time constraints

I built a bidding website for a client in which a user posts an item and sets the auction duration. The item is first in Pending state until an admin approves it or after 12 hours have passed since the user first posts it. From then on, the item gets Published and other users can bid on it. Once the auction period is over, the item should be Closed and the highest bidder wins the item...
In addition to that, I need to send email notifications...
To the admin once a new item is posted.
To the winner once he wins an item.
To the item's owner once the auction is closed.
To the admin once an auction has been closed and there was a winner (i.e: people actually bid on it).
Currently what I'm doing is to call some method in my business layer which checks whether there are any pending items that have passed the 12 hours period to make them published, and whether there are published items that have passed their auction duration to close them. This method is called from several places such as the website's home page, the item's search page and others... This is actually causing me problems (Refer to this question). So I think it's worth finding an alternative solution that would help me get rid of all these issues that are most likely due to poor design.
Should I centralize this by calling that method from one single place and sending the emails accordingly?
Should I delegate this whole thing to some sort of scheduled task? In this case, what time-frame would be reasonable to run this task?
Any other suggestions?
Should I delegate this whole thing to some sort of scheduled task? In
this case, what time-frame would be reasonable to run this task?
Yes, this seems like the best approach. Offload the email sending to a separate process than your ASP.NET MVC application. As far as the time-frame is concerned, this will depend on your business requirements. You may take a look at Quartz.NET which could be used as a task scheduling mechanism.
You should definitely offload this to another process like a scheduled task or a service. You don't say how many users you currently have or how many are likely to be doing something at the same time, but if you find your userbase to be growing having loads of emails being sent out on a web request will eventually time out.
A separate task/service will also allow you greater control over what emails get sent and when.

Dealing with bounce-backs emails (only POP3, without IMAP)

I want to ask about dealing with bounce-backs emails (but on server without IMAP, only with POP3, and without an Outlook on my machine).
I don’t want to read all emails from server every time.
So I thought, At first:
1. read e-mails from the oldest to the newest, checking whether there are bounce-backs.
2. save the date of the latest e-mail to the variable "TEMPDATA"
//This process will be executed only once, at the beginning
And then in timer loop (in another thread):
3. read e-mails from the "TEMPDATA" to the newest, checking whether there are bounce-backs (check if there is a subject “"Undelivered Mail Returned to Sender"”.)
The pseudo-code of my idea:
TIMER( Tick every 5minutes )
{
(LOCK)
loop(on inbox from the "TEMPDATA" to the newest)
{
// Read single email
if (the subject is "Undelivered Mail Returned to Sender")
{
// Here I will parse message so that I will know the addresse
// And removie that addresse from my list.
}
}
(UNLOCK)
}
I’m just curious if there is some better solution.
If you are planning to use IMAP protocol I'd rather use email UID than date.
Checking only the subject is not the bast way to check, if the message is delivery failure report.
Some emails will have different subject (different language).
Gmail for example uses additional header.
Most delivery failure emails however follow RFC3464 specification and use Delivery Status Notification (DSN) format.
You can try using Mail.dll component for this:
http://www.lesnikowski.com/blog/index.php/bounce-handling/
Please note that this is a commercial product I created.
I know this is an old question, but it shows up high in search results, so here's to hoping it helps others.
I found this open source solution:
https://mailsystem.codeplex.com/
Seems to be working well for us so far. Documentation is pretty much non-existent, though the Visual Studio intelli-sense is pretty detailed.

Email Notification Architecture Questions

We are looking to develop an email notification service where emails can be scheduled daily, weekly, or hourly based on certain actions that happen within our system (User Registration) or summary emails sent every Friday for example.
What is the best way to handle making sure duplicate emails are not sent? We thought about maybe having the application write a record to a queue whenver a system action happens but this would seem to have one more point of failure. Or maybe just making all notifications data driven, for example, select all users where created on date is greater than now. But with this scenario we need a way to make sure if the service runs again duplicate emails are not sent..
any ideas would be great!
My 2 cents
1) Queues. Queues are great for the tasks where you want to have a 'single entry and single exit' type of architecture. Queues decouple the systems and allow you to load balance the system. They are usually used with the multiple workers on one and another end. You will just add (maybe a lot) of messages to the queue, and later run a bulk dequeue. IMO that is irrational memory and resource consumption.
2) Data-driven via Users. Much easier to implement, however for each notification you will check every user and will put heavy load on db.
3) Data-driven via UserNotifications. Alternatively, you can create a separate table UserNotifications, where each user will be added once he has registered. It is much easier to select the needed users within given time frame and you don't store them in memory. Once notification sent, you remove the user from UserNotifications table.

Categories