public LetterSubscriber Fetch(Guid siteGuid, Guid letterInfoGuid, string email) { using (IDataReader reader = DBLetterSubscription.GetByEmail(siteGuid, letterInfoGuid, email.ToLower())) { if (reader.Read()) { LetterSubscriber letterSubscriber = new LetterSubscriber(); letterSubscriber.SubscribeGuid = new Guid(reader["Guid"].ToString()); letterSubscriber.SiteGuid = new Guid(reader["SiteGuid"].ToString()); letterSubscriber.LetterInfoGuid = new Guid(reader["LetterInfoGuid"].ToString()); letterSubscriber.VerifyGuid = new Guid(reader["VerifyGuid"].ToString()); letterSubscriber.UserGuid = new Guid(reader["UserGuid"].ToString()); letterSubscriber.UseHtml = Convert.ToBoolean(reader["UseHtml"]); letterSubscriber.BeginUtc = Convert.ToDateTime(reader["BeginUtc"]); letterSubscriber.EmailAddress = reader["Email"].ToString(); letterSubscriber.Name = reader["Name"].ToString(); letterSubscriber.IsVerified = Convert.ToBoolean(reader["IsVerified"]); letterSubscriber.IpAddress = reader["IpAddress"].ToString(); letterSubscriber.FirstName = reader["FirstName"].ToString(); letterSubscriber.LastName = reader["LastName"].ToString(); return(letterSubscriber); } } return(null); }
private void LoadSettings() { subscriptionGuid = WebUtils.ParseGuidFromQueryString("s", subscriptionGuid); if (subscriptionGuid != Guid.Empty) { subscription = subscriptions.Fetch(subscriptionGuid); if ((subscription != null) && (subscription.SiteGuid == siteSettings.SiteGuid)) { subscriptions.Verify(subscription.SubscribeGuid, true, Guid.Empty); if (subscription.UserGuid == Guid.Empty) { SiteUser user = SiteUser.GetByEmail(siteSettings, subscription.EmailAddress); if (user != null) { subscription.UserGuid = user.UserGuid; subscriptions.Save(subscription); } } LetterInfo.UpdateSubscriberCount(subscription.LetterInfoGuid); } else { subscription = null; } } AddClassToBody("administration"); AddClassToBody("eletterconfirm"); }
public bool Delete(LetterSubscriber subscription, bool createHistory) { if (subscription == null) { return(false); } if (createHistory) { DBLetterSubscription.CreateHistory( Guid.NewGuid(), subscription.SiteGuid, subscription.SubscribeGuid, subscription.LetterInfoGuid, subscription.UserGuid, subscription.EmailAddress, subscription.IsVerified, subscription.UseHtml, subscription.BeginUtc, DateTime.UtcNow, subscription.IpAddress); } return(DBLetterSubscription.Delete(subscription.SubscribeGuid)); }
public void Save(LetterSubscriber subsciption) { if (subsciption == null) { return; } if (subsciption.SubscribeGuid == Guid.Empty) { subsciption.SubscribeGuid = Guid.NewGuid(); DBLetterSubscription.Create( subsciption.SubscribeGuid, subsciption.SiteGuid, subsciption.LetterInfoGuid, subsciption.UserGuid, subsciption.EmailAddress.ToLower(), subsciption.IsVerified, subsciption.VerifyGuid, DateTime.UtcNow, subsciption.UseHtml, subsciption.IpAddress); } else { DBLetterSubscription.Update( subsciption.SubscribeGuid, subsciption.UserGuid, subsciption.UseHtml); } }
private void RunTask() { Letter letter = new Letter(this.letterGuid); if (letter.LetterGuid == Guid.Empty) { return; } if (letter.SendCompleteUtc > DateTime.MinValue) { return; } if (letter.SendClickedUtc == DateTime.MinValue) { return; } LetterInfo letterInfo = new LetterInfo(letter.LetterInfoGuid); // TODO: this could be a very large recordset if the kist is very large // might be better to get a page at a time instead of all at once. List <LetterSubscriber> subscribers = LetterSubscriber.GetSubscribersNotSentYet( letter.LetterGuid, letter.LetterInfoGuid); nextStatusUpdateTime = DateTime.UtcNow.AddSeconds(updateFrequency); totalSubscribersToSend = subscribers.Count; if ((totalSubscribersToSend > 0) && (letter.SendStartedUtc == DateTime.MinValue)) { letter.TrackSendStarted(); } 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(); }
private string ReplaceTextTokens(string textBody, LetterSubscriber subscriber) { // mail merge if (unsubscribeUrl.Length > 0) { string mergedMessage = textBody.Replace( Letter.UnsubscribeToken, unsubscribeUrl + "?u=" + subscriber.UserGuid.ToString() + "&l=" + subscriber.LetterInfoGuid.ToString()).Replace(Letter.UserNameToken, subscriber.Name); return(mergedMessage); } return(textBody); }
private string ReplaceHtmlTokens(string htmlBody, LetterSubscriber subscriber) { // mail merge if (unsubscribeUrl.Length > 0) { string mergedMessage = htmlBody.Replace( Letter.UnsubscribeToken, "<a href='" + unsubscribeUrl + "?u=" + subscriber.UserGuid.ToString() + "&l=" + subscriber.LetterInfoGuid.ToString() + "'>" + unsubscribeLinkText + "</a>").Replace(Letter.UserNameToken, subscriber.Name); return(mergedMessage); } return(htmlBody); }
public bool Delete(LetterSubscriber subscription, bool createHistory) { if (subscription == null) { return false; } if (createHistory) { DBLetterSubscription.CreateHistory( Guid.NewGuid(), subscription.SiteGuid, subscription.SubscribeGuid, subscription.LetterInfoGuid, subscription.UserGuid, subscription.EmailAddress, subscription.IsVerified, subscription.UseHtml, subscription.BeginUtc, DateTime.UtcNow, subscription.IpAddress); } return DBLetterSubscription.Delete(subscription.SubscribeGuid); }
//public List<LetterSubscriber> GetListByUser(Guid siteGuid, Guid userGuid) //{ // IDataReader reader = DBLetterSubscription.GetByUser(siteGuid, userGuid); // return LoadFromReader(reader); //} private List <LetterSubscriber> LoadFromReader(IDataReader reader) { List <LetterSubscriber> letterSubscriberList = new List <LetterSubscriber>(); try { while (reader.Read()) { LetterSubscriber letterSubscriber = new LetterSubscriber(); letterSubscriber.SubscribeGuid = new Guid(reader["Guid"].ToString()); letterSubscriber.SiteGuid = new Guid(reader["SiteGuid"].ToString()); letterSubscriber.LetterInfoGuid = new Guid(reader["LetterInfoGuid"].ToString()); letterSubscriber.VerifyGuid = new Guid(reader["VerifyGuid"].ToString()); letterSubscriber.UserGuid = new Guid(reader["UserGuid"].ToString()); letterSubscriber.UseHtml = Convert.ToBoolean(reader["UseHtml"]); letterSubscriber.BeginUtc = Convert.ToDateTime(reader["BeginUtc"]); letterSubscriber.EmailAddress = reader["Email"].ToString(); letterSubscriber.Name = reader["Name"].ToString(); letterSubscriber.IsVerified = Convert.ToBoolean(reader["IsVerified"]); letterSubscriber.IpAddress = reader["IpAddress"].ToString(); letterSubscriber.FirstName = reader["FirstName"].ToString(); letterSubscriber.LastName = reader["LastName"].ToString(); letterSubscriberList.Add(letterSubscriber); } } finally { reader.Close(); } return(letterSubscriberList); }
void btnSavePreferences_Click(object sender, EventArgs e) { foreach (LetterInfo availableSubscription in siteAvailableSubscriptions) { string controlID = "chk" + availableSubscription.LetterInfoGuid.ToString(); if (Request.Params.Get(controlID) != null) { if (!IsSubscribed(availableSubscription.LetterInfoGuid)) { //subscribe LetterSubscriber subscriber = new LetterSubscriber(); subscriber.SiteGuid = siteSettings.SiteGuid; subscriber.LetterInfoGuid = availableSubscription.LetterInfoGuid; subscriber.UserGuid = siteUser.UserGuid; subscriber.EmailAddress = siteUser.Email.ToLower(); subscriber.IsVerified = true; subscriber.UseHtml = rbHtmlFormat.Checked; subscriber.IpAddress = SiteUtils.GetIP4Address(); subscriptions.Save(subscriber); LetterInfo.UpdateSubscriberCount(availableSubscription.LetterInfoGuid); } else { // user is subscribed already foreach (LetterSubscriber s in userSubscriptions) { if (s.LetterInfoGuid == availableSubscription.LetterInfoGuid) { if (s.UseHtml != rbHtmlFormat.Checked) { s.UseHtml = rbHtmlFormat.Checked; subscriptions.Save(s); } if (!s.IsVerified) { subscriptions.Verify(s.SubscribeGuid, true, Guid.Empty); LetterInfo.UpdateSubscriberCount(availableSubscription.LetterInfoGuid); } } } } } else { if (IsSubscribed(availableSubscription.LetterInfoGuid)) { // unsubscribe foreach (LetterSubscriber s in userSubscriptions) { if (s.LetterInfoGuid == availableSubscription.LetterInfoGuid) { subscriptions.Delete(s); } } LetterInfo.UpdateSubscriberCount(availableSubscription.LetterInfoGuid); } } } GetSubscriptions(); BindPreferences(); lblUnverifiedWarning.Visible = false; //btnSavePreferences.Text = Resource.NewsletterSavePreferencesButton; System.Threading.Thread.Sleep(1000); UpdatePanel1.Update(); }
private void DoSubscribe(LetterInfo letter, string email) { if (email == "*****@*****.**") { return; } //I've been seeing a lot of this from a bot LetterSubscriber s = subscriptions.Fetch(siteSettings.SiteGuid, letter.LetterInfoGuid, email); bool needToSendVerification = false; if (s == null) { s = new LetterSubscriber(); s.SiteGuid = siteSettings.SiteGuid; s.EmailAddress = email; s.LetterInfoGuid = letter.LetterInfoGuid; if (showFormatOptions) { s.UseHtml = rbHtmlFormat.Checked; } else { s.UseHtml = htmlIsDefault; } if ((currentUser != null) && (string.Equals(currentUser.Email, email, StringComparison.InvariantCultureIgnoreCase))) { s.UserGuid = currentUser.UserGuid; s.IsVerified = true; } else { // user is not authenticated but may still exist // attach userguid but don't flag as verified // because we don't know that the user who submited the form is the account owner SiteUser siteUser = SiteUser.GetByEmail(siteSettings, email); if (siteUser != null) { s.UserGuid = siteUser.UserGuid; } } s.IpAddress = SiteUtils.GetIP4Address(); subscriptions.Save(s); LetterInfo.UpdateSubscriberCount(s.LetterInfoGuid); if (WebConfigSettings.LogNewsletterSubscriptions) { log.Info(s.EmailAddress + " just subscribed to newsletter " + letter.Title); } if(!s.IsVerified) { needToSendVerification = true; } } else { // we found an existing subscription if (!s.IsVerified) { // if the current authenticated user has the same email mark it as verified if ((currentUser != null) && (string.Equals(currentUser.Email, email, StringComparison.InvariantCultureIgnoreCase))) { s.UserGuid = currentUser.UserGuid; if (showFormatOptions) { s.UseHtml = rbHtmlFormat.Checked; } subscriptions.Save(s); subscriptions.Verify(s.SubscribeGuid, true, Guid.Empty); } else if (s.BeginUtc < DateTime.UtcNow.AddDays(-WebConfigSettings.NewsletterReVerifcationAfterDays)) { // if the user never verifed before and its been at least x days go ahead and send another chance to verify needToSendVerification = true; // TODO: maybe we should log this in case some spam script is using the same email over and over // or maybe we should add a verification sent count on subscription } } } //added 2012-05-16 to support intranet scenarios where verification is not required if (!WebConfigSettings.NewsletterRequireVerification) { if (!s.IsVerified) { s.IsVerified = true; subscriptions.Save(s); } needToSendVerification = false; } if (needToSendVerification) { NewsletterHelper.SendSubscriberVerificationEmail( siteRoot, email, s.SubscribeGuid, letter, siteSettings); } }
private string ReplaceTextTokens(string textBody, LetterSubscriber subscriber) { // mail merge if (unsubscribeUrl.Length > 0) { string mergedMessage = textBody.Replace( Letter.UnsubscribeToken, unsubscribeUrl + "?u=" + subscriber.UserGuid.ToString() + "&l=" + subscriber.LetterInfoGuid.ToString()).Replace(Letter.UserNameToken, subscriber.Name); return mergedMessage; } return textBody; }
private void DoSubscribe(LetterInfo letter, SiteUser siteUser) { LetterSubscriber s = new LetterSubscriber(); s.SiteGuid = siteSettings.SiteGuid; s.EmailAddress = siteUser.Email; s.UserGuid = siteUser.UserGuid; s.LetterInfoGuid = letter.LetterInfoGuid; s.UseHtml = true; s.IsVerified = true; s.IpAddress = SiteUtils.GetIP4Address(); subscriptions.Save(s); LetterInfo.UpdateSubscriberCount(s.LetterInfoGuid); }
private void SendLetter( SmtpSettings smtpSettings, LetterInfo letterInfo, Letter letter, LetterSubscriber subscriber) { // TODO: use multi part email with both html and plain text body // instead of this either or approach bool testMode = false; if ( (ConfigurationManager.AppSettings["NewsletterTestMode"] != null) && (ConfigurationManager.AppSettings["NewsletterTestMode"] == "true") ) { testMode = true; } LetterSendLog mailLog = new LetterSendLog(); mailLog.EmailAddress = subscriber.EmailAddress; mailLog.LetterGuid = letter.LetterGuid; mailLog.UserGuid = subscriber.UserGuid; if (testMode) { Thread.Sleep(3000); // sleep 3 seconds per message to simulate } else { try { if (subscriber.UseHtml) { Email.SendEmail( smtpSettings, letterInfo.FromAddress, subscriber.EmailAddress, string.Empty, string.Empty, letter.Subject, ReplaceHtmlTokens(letter.HtmlBody, subscriber), subscriber.UseHtml, "Normal"); } else { Email.SendEmail( smtpSettings, letterInfo.FromAddress, subscriber.EmailAddress, string.Empty, string.Empty, letter.Subject, ReplaceTextTokens(letter.TextBody, subscriber), subscriber.UseHtml, "Normal"); } } catch (Exception ex) { // TODO: catch more specific exception(s) figure out what ones can be thrown here mailLog.ErrorOccurred = true; mailLog.ErrorMessage = ex.ToString(); log.Error(ex); } } mailLog.Save(); }
public bool Delete(LetterSubscriber subscription) { return Delete(subscription, true); }
//public List<LetterSubscriber> GetListByUser(Guid siteGuid, Guid userGuid) //{ // IDataReader reader = DBLetterSubscription.GetByUser(siteGuid, userGuid); // return LoadFromReader(reader); //} private List<LetterSubscriber> LoadFromReader(IDataReader reader) { List<LetterSubscriber> letterSubscriberList = new List<LetterSubscriber>(); try { while (reader.Read()) { LetterSubscriber letterSubscriber = new LetterSubscriber(); letterSubscriber.SubscribeGuid = new Guid(reader["Guid"].ToString()); letterSubscriber.SiteGuid = new Guid(reader["SiteGuid"].ToString()); letterSubscriber.LetterInfoGuid = new Guid(reader["LetterInfoGuid"].ToString()); letterSubscriber.VerifyGuid = new Guid(reader["VerifyGuid"].ToString()); letterSubscriber.UserGuid = new Guid(reader["UserGuid"].ToString()); letterSubscriber.UseHtml = Convert.ToBoolean(reader["UseHtml"]); letterSubscriber.BeginUtc = Convert.ToDateTime(reader["BeginUtc"]); letterSubscriber.EmailAddress = reader["Email"].ToString(); letterSubscriber.Name = reader["Name"].ToString(); letterSubscriber.IsVerified = Convert.ToBoolean(reader["IsVerified"]); letterSubscriber.IpAddress = reader["IpAddress"].ToString(); letterSubscriber.FirstName = reader["FirstName"].ToString(); letterSubscriber.LastName = reader["LastName"].ToString(); letterSubscriberList.Add(letterSubscriber); } } finally { reader.Close(); } return letterSubscriberList; }
private string ReplaceHtmlTokens(string htmlBody, LetterSubscriber subscriber) { // mail merge if (unsubscribeUrl.Length > 0) { string mergedMessage = htmlBody.Replace( Letter.UnsubscribeToken, "<a href='" + unsubscribeUrl + "?u=" + subscriber.UserGuid.ToString() + "&l=" + subscriber.LetterInfoGuid.ToString() + "'>" + unsubscribeLinkText + "</a>").Replace(Letter.UserNameToken, subscriber.Name); return mergedMessage; } return htmlBody; }
private string ReplaceTextTokens(string textBody, LetterSubscriber subscriber, LetterInfo letterInfo) { StringBuilder mergedMessage = new StringBuilder(); mergedMessage.Append(textBody); // mail merge if (unsubscribeUrl.Length > 0) { if (subscriber.UserGuid != Guid.Empty) { mergedMessage.Replace( Letter.UnsubscribeToken, unsubscribeUrl + "?u=" + subscriber.UserGuid.ToString() + "&l=" + subscriber.LetterInfoGuid.ToString()); } else { mergedMessage.Replace( Letter.UnsubscribeToken, unsubscribeUrl + "?s=" + subscriber.SubscribeGuid.ToString() + "&l=" + subscriber.LetterInfoGuid.ToString()); } } if (webPageUrl.Length > 0) { mergedMessage.Replace(Letter.WebPageLinkToken, webPageUrl); } else { mergedMessage.Replace(Letter.WebPageLinkToken, string.Empty); } mergedMessage.Replace(Letter.UserNameToken, subscriber.Name.Coalesce(subscriber.EmailAddress)); mergedMessage.Replace(Letter.UserEmailToken, subscriber.EmailAddress); if (subscriber.UserGuid != Guid.Empty) { // site member if ((subscriber.FirstName.Length > 0) && (subscriber.LastName.Length > 0)) { // if both first and last have values replace the tokens mergedMessage.Replace(Letter.UserFirstNameToken, subscriber.FirstName); mergedMessage.Replace(Letter.UserLastNameToken, subscriber.LastName); } else if (subscriber.FirstName.Length > 0) { // if only first name has a value then replace last name with empty string and first name with first name mergedMessage.Replace(Letter.UserFirstNameToken, subscriber.FirstName); mergedMessage.Replace(Letter.UserLastNameToken, string.Empty); } else { // if neither first name nor last name has a value replace last with empty string and first with display name mergedMessage.Replace(Letter.UserFirstNameToken, subscriber.Name); mergedMessage.Replace(Letter.UserLastNameToken, string.Empty); } } else { //non site member // currently non site members do not have first or last name data fields // but in case we add those this logic will already be here if ((subscriber.FirstName.Length > 0) && (subscriber.LastName.Length > 0)) { // if both first and last have values replace the tokens mergedMessage.Replace(Letter.UserFirstNameToken, subscriber.FirstName); mergedMessage.Replace(Letter.UserLastNameToken, subscriber.LastName); } else if (subscriber.FirstName.Length > 0) { // if only first name has a value then replace last name with empty string and first name with first name mergedMessage.Replace(Letter.UserFirstNameToken, subscriber.FirstName); mergedMessage.Replace(Letter.UserLastNameToken, string.Empty); } else { // this is the expected path for non site members since we don't have data fields for first and last // replace with token defaults from letterInfo (ie Valued Customer could be the first and last token defaults) mergedMessage.Replace(Letter.UserFirstNameToken, letterInfo.FirstNameDefault); mergedMessage.Replace(Letter.UserLastNameToken, letterInfo.LastNameDefault); } } mergedMessage.Replace(Letter.UserDisplayNameToken, subscriber.Name.Coalesce(letterInfo.DisplayNameDefault)); return mergedMessage.ToString(); }
private void SendLetter( SmtpSettings smtpSettings, LetterInfo letterInfo, Letter letter, LetterSubscriber subscriber) { // TODO: use multi part email with both html and plain text body // instead of this either or approach? LetterSendLog mailLog = new LetterSendLog(); mailLog.EmailAddress = subscriber.EmailAddress; mailLog.LetterGuid = letter.LetterGuid; mailLog.UserGuid = subscriber.UserGuid; mailLog.SubscribeGuid = subscriber.SubscribeGuid; if (testMode) { Thread.Sleep(testSleepMilliseconds); // sleep 1 seconds per message to simulate } else { try { if (subscriber.UseHtml) { Email.Send( smtpSettings, letterInfo.FromAddress.Coalesce(notificationFromEmail), letterInfo.FromName.Coalesce(notificationFromAlias), letterInfo.ReplyToAddress.Coalesce(notificationFromAlias), subscriber.EmailAddress, string.Empty, string.Empty, letter.Subject, ReplaceHtmlTokens(letter.HtmlBody, subscriber, letterInfo), subscriber.UseHtml, "Normal"); } else { Email.Send( smtpSettings, letterInfo.FromAddress.Coalesce(notificationFromEmail), letterInfo.FromName.Coalesce(notificationFromAlias), letterInfo.ReplyToAddress.Coalesce(notificationFromEmail), subscriber.EmailAddress, string.Empty, string.Empty, letter.Subject, ReplaceTextTokens(letter.TextBody, subscriber, letterInfo), subscriber.UseHtml, "Normal"); } } catch (Exception ex) { // TODO: catch more specific exception(s) figure out what ones can be thrown here mailLog.ErrorOccurred = true; mailLog.ErrorMessage = ex.ToString(); log.Error(ex); } } mailLog.Save(); }
private void DoSubscribe(LetterInfo letter, SiteUser siteUser) { LetterSubscriber s = new LetterSubscriber(); s.SiteGuid = siteSettings.SiteGuid; s.EmailAddress = siteUser.Email; s.UserGuid = siteUser.UserGuid; s.LetterInfoGuid = letter.LetterInfoGuid; s.UseHtml = rbHtmlFormat.Checked; s.IsVerified = (!siteSettings.UseSecureRegistration); s.IpAddress = SiteUtils.GetIP4Address(); subscriptions.Save(s); LetterInfo.UpdateSubscriberCount(s.LetterInfoGuid); }
public bool Delete(LetterSubscriber subscription) { return(Delete(subscription, true)); }
private void RunTask() { // this is where the work gets done // Get a data table of up to 1000 users // who have not opted in but also have not previously // opted out and have valid email accounts and account is not locked DataTable dataTable = GetData(); double completeRatio = .5; if (dataTable.Rows.Count == 0) { completeRatio = 1; //complete ReportStatus(completeRatio); return; } SubscriberRepository repository = new SubscriberRepository(); int count = 0; foreach (DataRow row in dataTable.Rows) { Guid userGuid = new Guid(row["UserGuid"].ToString()); string email = row["email"].ToString(); LetterSubscriber s = new LetterSubscriber(); s.SiteGuid = SiteGuid; s.UserGuid = userGuid; s.EmailAddress = email; s.LetterInfoGuid = LetterInfoGuid; s.UseHtml = true; s.IsVerified = true; repository.Save(s); count += 1; if (count > 20) { ReportStatus(completeRatio); count = 0; } } LetterInfo.UpdateSubscriberCount(LetterInfoGuid); ReportStatus(completeRatio); // repeat until the table comes back with 0 rows RunTask(); }
public LetterSubscriber Fetch(Guid siteGuid, Guid letterInfoGuid, string email) { using (IDataReader reader = DBLetterSubscription.GetByEmail(siteGuid, letterInfoGuid, email.ToLower())) { if (reader.Read()) { LetterSubscriber letterSubscriber = new LetterSubscriber(); letterSubscriber.SubscribeGuid = new Guid(reader["Guid"].ToString()); letterSubscriber.SiteGuid = new Guid(reader["SiteGuid"].ToString()); letterSubscriber.LetterInfoGuid = new Guid(reader["LetterInfoGuid"].ToString()); letterSubscriber.VerifyGuid = new Guid(reader["VerifyGuid"].ToString()); letterSubscriber.UserGuid = new Guid(reader["UserGuid"].ToString()); letterSubscriber.UseHtml = Convert.ToBoolean(reader["UseHtml"]); letterSubscriber.BeginUtc = Convert.ToDateTime(reader["BeginUtc"]); letterSubscriber.EmailAddress = reader["Email"].ToString(); letterSubscriber.Name = reader["Name"].ToString(); letterSubscriber.IsVerified = Convert.ToBoolean(reader["IsVerified"]); letterSubscriber.IpAddress = reader["IpAddress"].ToString(); letterSubscriber.FirstName = reader["FirstName"].ToString(); letterSubscriber.LastName = reader["LastName"].ToString(); return letterSubscriber; } } return null; }