private void RunTask() { Letter letter = new Letter(this.letterGuid); if (letter.LetterGuid == Guid.Empty) { log.Error("LetterSendTask letter not found so ending."); ReportStatus(); return; } if (letter.SendCompleteUtc > DateTime.MinValue) { log.Error("LetterSendTask SendCompleteUtc already set so ending."); ReportStatus(); return; } if (letter.SendClickedUtc == DateTime.MinValue) { log.Error("LetterSendTask SendClickedUtc has an invalid value so ending."); ReportStatus(); return; } LetterInfo letterInfo = new LetterInfo(letter.LetterInfoGuid); SubscriberRepository subscriptions = new SubscriberRepository(); if ( (ConfigurationManager.AppSettings["NewsletterTestMode"] != null) && (ConfigurationManager.AppSettings["NewsletterTestMode"] == "true") ) { testMode = true; log.Info("using NewsletterTestMode=true in config so no real emails will be sent for newsletter " + letterInfo.Title); } // TODO: this could be a very large recordset if the list is very large // might be better to get a page at a time instead of all at once. List <LetterSubscriber> subscribers = subscriptions.GetSubscribersNotSentYet( letter.LetterGuid, letter.LetterInfoGuid); nextStatusUpdateTime = DateTime.UtcNow.AddSeconds(updateFrequency); totalSubscribersToSend = subscribers.Count; if ((totalSubscribersToSend > 0) && (letter.SendStartedUtc == DateTime.MinValue)) { letter.TrackSendStarted(); } if (totalSubscribersToSend < 100) { testSleepMilliseconds = 3000; } if (totalSubscribersToSend > 300) { testSleepMilliseconds = 500; } if (totalSubscribersToSend > 500) { testSleepMilliseconds = 100; } SmtpSettings smtpSettings = new SmtpSettings(); smtpSettings.Password = password; smtpSettings.Port = port; smtpSettings.PreferredEncoding = preferredEncoding; smtpSettings.RequiresAuthentication = requiresAuthentication; smtpSettings.UseSsl = useSsl; smtpSettings.User = user; smtpSettings.Server = server; foreach (LetterSubscriber subscriber in subscribers) { SendLetter(smtpSettings, letterInfo, letter, subscriber); subscribersSentSoFar += 1; if (DateTime.UtcNow > nextStatusUpdateTime) { ReportStatus(); } } ReportStatus(); }