4

Optimized way to send a daily digest email to my user at a time of 11.30am according to their time zone,

Sending a Email to a user is working fine but to send at a specific time with their timezone?

What i have

UserProfile with timezoneid,emailid
Dynamic daily email content

Currently i am doing with a console application to send at 11.30am at utc time,

but how to handle in multiple timezone?can anyone help me out?

tereško
  • 58,060
  • 25
  • 98
  • 150
Tony Stark
  • 156
  • 12
  • what about scheduling a task with user e-mail address and the e-mail content to the windows scheduler taking into account particular time zone shift? http://stackoverflow.com/questions/10052638/schedule-task-in-windows-task-scheduler-c-sharp – Yaugen Vlasau Mar 24 '14 at 09:03
  • 1
    Consider using a scheduler like [Quartz.net](http://quartznet.sourceforge.net/) – Matt Johnson-Pint Mar 25 '14 at 04:54

1 Answers1

5

I have achieved this type of functionality via a console application running as a scheduled task that polls the database every X minutes to see if any emails need to be sent.

I am assuming UserProfile is a database table holding your user list.

To achieve this I would add an additional column to this table to store the last sent Date/Time. This is necessary as when you start sending by timezone you obviously cannot send all the emails at the same time each day and will need to track which ones have been sent or which ones need to be sent.

Also due to the nature of this type of task if for some reason it fails or isn't running for some reason you may need to "catch-up" i.e. send any missed emails (although this may not be a requirement for you) which can also be achieved by checking the last sent column.

Assuming you want to send an email at (or as close to) 11:30am local time to each user the following code should work:

IList<UserProfile> users = // Load user profile from database

foreach(UserProfile user in user){

    // Work out this users local time by converting UTC to their local TimeZone
    DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, user.TimeZoneId);

    if(user.LastSent.HasValue && user.LastSent.Value.Date == localDateTime.Date){
       // Already sent an email today
       continue;
    }

    if(localDateTime.Hour >= 11 && localDateTime.Minute >= 30){
       // After 11:30am so send email (this could be much later than 11:30 depending on other factors)
       if(SendEmail(user.EmailId)){
           // Update last sent that must be in local time
           user.LastSent = Converter.ToLocalTime(DateTime.UtcNow, user.TimeZoneId);

           // Save User entity
           // UserPersistence.Save(user);
       }

    }

}

Now as a caveat the code above will send an email as soon as 11:30 has been reached PROVIDED that the code is running and dependent on volume of users/latency of sending each email etc. If you have a scheduled task running every 5 minutes then obviously the accuracy is going to be to the nearest 5 minutes so it may not send until 11:35am. You could run the scheduled task more frequently if you want more accuracy. Another consideration is that if you have 30000 users in the same time zone then the latency of sending that volume of emails will naturally mean that not all can be sent at exactly 11:30am.

That said the code above should get you started in the right direction.

connectedsoftware
  • 6,987
  • 3
  • 28
  • 43
  • is Converter.ToLocalTime means [TimeZoneInfo.ConvertTimeBySystemTimeZoneId](http://msdn.microsoft.com/en-us/library/bb382058(v=vs.110).aspx) – Tony Stark Mar 24 '14 at 13:45
  • 1
    Sorry that is a wrapper function that I use, basically it uses this TimeZoneInfo.ConvertTimeFromUtc - have updated answer. – connectedsoftware Mar 24 '14 at 13:47