public MailingScheduledViewModel(Translator translator, IDatabase db, Session session, Mailing mailing) : this(translator, session) { Id = mailing.Id.Value.ToString(); Title = mailing.Title.Value.EscapeHtml(); Recipients = mailing.RecipientFeed.Value.Name.Value[translator.Language]; if (mailing.RecipientTag.Value != null) { Recipients = " / " + mailing.RecipientTag.Value.Name.Value[translator.Language]; } if (mailing.RecipientLanguage.Value.HasValue) { Recipients = " / " + mailing.RecipientLanguage.Value.Value.Translate(translator); } var number = db .Query <Contact>() .Count(p => p.ActiveSubscriptions.Any(m => m.Feed == mailing.RecipientFeed.Value) && (mailing.RecipientTag.Value == null || p.TagAssignments.Any(t => t.Tag == mailing.RecipientTag.Value))); Recipients += " / " + translator.Get("Mailing.Scheduled.Fields.Recipients.Contacts", "Contacts in the recipients field on the scheduled mailing page", "circa {0} contacts", number); Subject = mailing.Subject.Value.EscapeHtml(); var sendingDate = mailing.SendingDate.Value.HasValue ? mailing.SendingDate.Value.Value.ToLocalTime().ToString("dd.MM.yyyy HH:mm") : string.Empty; var sentDate = mailing.SentDate.Value.HasValue ? mailing.SentDate.Value.Value.ToLocalTime().ToString("dd.MM.yyyy HH:mm") : string.Empty; switch (mailing.Status.Value) { case MailingStatus.Scheduled: Status = translator.Get("Mailing.Scheduled.Field.Status.Scheduled", "Scheduled status in the status field the scheduled mailing page", "Scheduled for {0}", sendingDate).EscapeHtml(); break; case MailingStatus.Sending: Status = translator.Get("Mailing.Scheduled.Field.Status.Sending", "Sending status in the status field the scheduled mailing page", "Sending since {0}", sendingDate).EscapeHtml(); break; case MailingStatus.Sent: Status = translator.Get("Mailing.Scheduled.Field.Status.Sent", "Sent status in the status field the scheduled mailing page", "Sent at {0}", sentDate).EscapeHtml(); break; case MailingStatus.Canceled: Status = translator.Get("Mailing.Scheduled.Field.Status.Canceled", "Canceled status in the status field the scheduled mailing page", "Canceled").EscapeHtml(); break; default: throw new NotSupportedException(); } Sendings = new List <MailingSendingViewModel>(db .Query <Sending>(DC.Equal("mailingid", mailing.Id.Value)) .Select(s => new MailingSendingViewModel(translator, s))); Cancelable = mailing.Status.Value == MailingStatus.Scheduled || mailing.Status.Value == MailingStatus.Sending; }
public MailingModule() { this.RequiresAuthentication(); Get["/mailing"] = parameters => { return(View["View/mailing.sshtml", new MailingViewModel(Translator, CurrentSession)]); }; Get["/mailing/list"] = parameters => { return(View["View/mailinglist.sshtml", new MailingListViewModel(Translator, Database, CurrentSession)]); }; Get["/mailing/add"] = parameters => { return(View["View/mailingedit.sshtml", new MailingEditViewModel(Translator, Database, CurrentSession)]); }; Post["/mailing/add/{id}"] = parameters => { string idString = parameters.id; var model = JsonConvert.DeserializeObject <MailingEditViewModel>(ReadBody()); var status = CreateStatus(); if (Guid.TryParse(idString, out Guid id)) { var mailing = new Mailing(id); status.AssignStringRequired("Title", mailing.Title, model.Title); status.AssignObjectIdString("RecipientFeed", mailing.RecipientFeed, model.RecipientFeed); status.AssignObjectIdString("RecipientTag", mailing.RecipientTag, model.RecipientTag); status.AssignEnumIntString("RecipientLanguage", mailing.RecipientLanguage, model.RecipientLanguage); status.AssignObjectIdString("SenderGroup", mailing.Sender, model.SenderGroup); status.AssignObjectIdString("Header", mailing.Header, model.Header); status.AssignObjectIdString("Footer", mailing.Footer, model.Footer); status.AssignStringRequired("Subject", mailing.Subject, model.Subject); var worker = new HtmlWorker(model.HtmlText); mailing.HtmlText.Value = worker.CleanHtml; mailing.PlainText.Value = worker.PlainText; mailing.Creator.Value = CurrentSession.User; if (status.IsSuccess) { if (status.HasAccess(mailing.RecipientFeed.Value, PartAccess.Mailings, AccessRight.Write) && (mailing.Sender.Value == null || status.HasAccess(mailing.Sender.Value, PartAccess.Mailings, AccessRight.Write))) { Database.Save(mailing); Notice("{0} added mailing {1}", CurrentSession.User.UserName.Value, mailing); } } } else { status.SetErrorNotFound(); } return(status.CreateJsonData()); }; Get["/mailing/edit/{id}"] = parameters => { string idString = parameters.id; var mailing = Database.Query <Mailing>(idString); if (mailing != null) { if (mailing.Status.Value == MailingStatus.New) { return(View["View/mailingedit.sshtml", new MailingEditViewModel(Translator, Database, CurrentSession, mailing)]); } else { return(View["View/mailingscheduled.sshtml", new MailingScheduledViewModel(Translator, Database, CurrentSession, mailing)]); } } return(Response.AsRedirect("/mailing")); }; Post["/mailing/edit/{id}"] = parameters => { string idString = parameters.id; var model = JsonConvert.DeserializeObject <MailingEditViewModel>(ReadBody()); var mailing = Database.Query <Mailing>(idString); var status = CreateStatus(); if (status.ObjectNotNull(mailing)) { if (mailing.Status.Value == MailingStatus.New) { status.AssignStringRequired("Title", mailing.Title, model.Title); status.AssignObjectIdString("RecipientFeed", mailing.RecipientFeed, model.RecipientFeed); status.AssignObjectIdString("RecipientTag", mailing.RecipientTag, model.RecipientTag); status.AssignEnumIntString("RecipientLanguage", mailing.RecipientLanguage, model.RecipientLanguage); status.AssignObjectIdString("SenderGroup", mailing.Sender, model.SenderGroup); status.AssignObjectIdString("Header", mailing.Header, model.Header); status.AssignObjectIdString("Footer", mailing.Footer, model.Footer); status.AssignStringRequired("Subject", mailing.Subject, model.Subject); var worker = new HtmlWorker(model.HtmlText); mailing.HtmlText.Value = worker.CleanHtml; mailing.PlainText.Value = worker.PlainText; mailing.Creator.Value = CurrentSession.User; if (status.IsSuccess) { if (status.HasAccess(mailing.RecipientFeed.Value, PartAccess.Mailings, AccessRight.Write) && (mailing.Sender.Value == null || status.HasAccess(mailing.Sender.Value, PartAccess.Mailings, AccessRight.Write))) { Database.Save(mailing); Notice("{0} changed mailing {1}", CurrentSession.User.UserName.Value, mailing); } } } else { status.SetErrorAccessDenied(); } } return(status.CreateJsonData()); }; Post["/mailing/test"] = parameters => { var model = JsonConvert.DeserializeObject <MailingEditViewModel>(ReadBody()); var worker = new HtmlWorker(model.HtmlText); var header = Database.Query <MailingElement>(model.Header); var footer = Database.Query <MailingElement>(model.Footer); var sender = Database.Query <Group>(model.SenderGroup); var htmlText = worker.CleanHtml; var plainText = worker.PlainText; if (header != null) { htmlText = HtmlWorker.ConcatHtml(header.HtmlText.Value, htmlText); plainText = header.PlainText.Value + plainText; } if (footer != null) { htmlText = HtmlWorker.ConcatHtml(htmlText, footer.HtmlText.Value); plainText = plainText + footer.PlainText.Value; } var contact = Database .Query <Contact>() .Where(p => HasAccess(p, PartAccess.Contact, AccessRight.Read)) .FirstOrDefault(); if (contact == null) { return(PostResult.Failed( Translate("Mailing.Edit.Test.Failed", "Failed message on sending test mail in mailing edit page", "E-Mail could not be sent."))); } var templator = new Templator(new ContactContentProvider(Translator, contact)); htmlText = templator.Apply(htmlText); plainText = templator.Apply(plainText); try { var language = CurrentSession.User.Language.Value; var from = new MailboxAddress( sender.MailName.Value[language], sender.MailAddress.Value[language]); var to = new MailboxAddress(model.TestAddress); var senderKey = sender.GpgKeyId.Value == null ? null : new GpgPrivateKeyInfo( sender.GpgKeyId.Value, sender.GpgKeyPassphrase.Value); var content = new Multipart("alternative"); var textPart = new TextPart("plain") { Text = plainText }; textPart.ContentTransferEncoding = ContentEncoding.QuotedPrintable; content.Add(textPart); var htmlPart = new TextPart("html") { Text = htmlText }; htmlPart.ContentTransferEncoding = ContentEncoding.QuotedPrintable; content.Add(htmlPart); Global.Mail.Send(from, to, senderKey, null, model.Subject, content); Notice("{0} tests mailing with subject {1}", CurrentSession.User.UserName.Value, model.Subject); return(PostResult.Success( Translate("Mailing.Edit.Test.Success", "Success message on sending test mail in mailing edit page", "Test E-Mail sent."))); } catch { return(PostResult.Failed( Translate("Mailing.Edit.Test.Failed", "Failed message on sending test mail in mailing edit page", "E-Mail could not be sent."))); } }; Get["/mailing/send/{id}"] = parameters => { string idString = parameters.id; var mailing = Database.Query <Mailing>(idString); if (mailing != null) { if (HasAccess(mailing.RecipientFeed.Value, PartAccess.Mailings, AccessRight.Write) && (mailing.Sender.Value == null || HasAccess(mailing.Sender.Value, PartAccess.Mailings, AccessRight.Write))) { return(View["View/mailingsend.sshtml", new MailingSendViewModel(Translator, Database, CurrentSession, mailing)]); } } return(AccessDenied()); }; Post["/mailing/send/{id}"] = parameters => { string idString = parameters.id; var model = JsonConvert.DeserializeObject <MailingSendViewModel>(ReadBody()); var mailing = Database.Query <Mailing>(idString); var status = CreateStatus(); if (status.ObjectNotNull(mailing)) { status.AssignDateString("Date", mailing.SendingDate, model.Date, true); status.AddAssignTimeString("Time", mailing.SendingDate, model.Time); if (status.IsSuccess) { if (status.HasAccess(mailing.RecipientFeed.Value, PartAccess.Mailings, AccessRight.Write) && (mailing.Sender.Value == null || status.HasAccess(mailing.Sender.Value, PartAccess.Mailings, AccessRight.Write))) { mailing.SendingDate.Value = mailing.SendingDate.Value.Value.ToUniversalTime(); mailing.Status.Value = MailingStatus.Scheduled; Database.Save(mailing); Notice("{0} sent mailing {1}", CurrentSession.User.UserName.Value, mailing); } } } return(status.CreateJsonData()); }; Get["/mailing/delete/{id}"] = parameters => { string idString = parameters.id; var mailing = Database.Query <Mailing>(idString); var status = CreateStatus(); if (status.ObjectNotNull(mailing)) { if (status.HasAccess(mailing.RecipientFeed.Value, PartAccess.Mailings, AccessRight.Write) && (mailing.Sender.Value == null || status.HasAccess(mailing.Sender.Value, PartAccess.Mailings, AccessRight.Write))) { using (var transaction = Database.BeginTransaction()) { mailing.Delete(Database); transaction.Commit(); Notice("{0} deleted mailing {1}", CurrentSession.User.UserName.Value, mailing); } } } return(status.CreateJsonData()); }; Get["/mailing/cancel/{id}"] = parameters => { string idString = parameters.id; var mailing = Database.Query <Mailing>(idString); var status = CreateStatus(); if (status.ObjectNotNull(mailing)) { if (status.HasAccess(mailing.RecipientFeed.Value, PartAccess.Mailings, AccessRight.Write) && (mailing.Sender.Value == null || status.HasAccess(mailing.Sender.Value, PartAccess.Mailings, AccessRight.Write))) { if (mailing.Status.Value == MailingStatus.Scheduled || mailing.Status.Value == MailingStatus.Sending) { using (var transaction = Database.BeginTransaction()) { mailing.Status.Value = MailingStatus.Canceled; Database.Save(mailing); transaction.Commit(); Notice("{0} canceled mailing {1}", CurrentSession.User.UserName.Value, mailing); } } else { status.SetErrorAccessDenied(); } } } return(status.CreateJsonData()); }; Get["/mailing/copy/{id}"] = parameters => { string idString = parameters.id; var mailing = Database.Query <Mailing>(idString); var status = CreateStatus(); if (status.ObjectNotNull(mailing)) { if (status.HasAccess(mailing.RecipientFeed.Value, PartAccess.Mailings, AccessRight.Write) && (mailing.Sender.Value == null || status.HasAccess(mailing.Sender.Value, PartAccess.Mailings, AccessRight.Write))) { var newMailing = new Mailing(Guid.NewGuid()); newMailing.Title.Value = mailing.Title.Value + Translate("Mailing.Copy.Postfix", "Postfix of copied mailings", " (Copy)"); newMailing.RecipientFeed.Value = mailing.RecipientFeed.Value; newMailing.RecipientTag.Value = mailing.RecipientTag.Value; newMailing.RecipientLanguage.Value = mailing.RecipientLanguage.Value; newMailing.Sender.Value = mailing.Sender.Value; newMailing.Header.Value = mailing.Header.Value; newMailing.Footer.Value = mailing.Footer.Value; newMailing.Subject.Value = mailing.Subject.Value; newMailing.HtmlText.Value = mailing.HtmlText.Value; newMailing.PlainText.Value = mailing.PlainText.Value; newMailing.Creator.Value = CurrentSession.User; newMailing.CreatedDate.Value = DateTime.UtcNow; newMailing.Status.Value = MailingStatus.New; Database.Save(newMailing); Notice("{0} copied mailing {1}", CurrentSession.User.UserName.Value, mailing); } } return(status.CreateJsonData()); }; }
public MailingSendViewModel(Translator translator, IDatabase db, Session session, Mailing mailing) : this(translator, session) { Id = mailing.Id.Value.ToString(); Title = mailing.Title.Value.EscapeHtml(); RecipientFeed = mailing.RecipientFeed.Value.Name.Value[translator.Language]; if (mailing.RecipientTag.Value != null) { RecipientTag = mailing.RecipientTag.Value.Name.Value[translator.Language]; } else { RecipientTag = translator.Get("Mailing.Edit.Field.RecipientTags.None", "No selection in the recipient tag field of the edit mailing page", "None"); } RecipientNumber = "~" + db .Query <Contact>() .Where(p => p.ActiveSubscriptions.Any(m => m.Feed == mailing.RecipientFeed.Value) && (mailing.RecipientTag.Value == null || p.TagAssignments.Any(t => t.Tag == mailing.RecipientTag.Value))) .Count().ToString(); Subject = mailing.Subject.Value.EscapeHtml(); }
public MailingEditViewModel(Translator translator, IDatabase db, Session session, Mailing mailing) : this(translator, session) { Method = "edit"; Id = mailing.Id.Value.ToString(); Title = mailing.Title.Value.EscapeHtml(); Subject = mailing.Subject.Value.EscapeHtml(); HtmlText = mailing.HtmlText.Value; RecipientFeeds = new List <NamedIdViewModel>(db .Query <Feed>() .Where(o => session.HasAccess(o, PartAccess.Mailings, AccessRight.Write)) .Select(o => new NamedIdViewModel(translator, o, mailing.RecipientFeed.Value == o)) .OrderBy(o => o.Name)); RecipientTags = new List <NamedIdViewModel>(db .Query <Tag>() .Where(t => t.Usage.Value.HasFlag(TagUsage.Mailing)) .Select(t => new NamedIdViewModel(translator, t, mailing.RecipientTag.Value == t)) .OrderBy(t => t.Name)); RecipientTags.Add(new NamedIdViewModel(translator.Get("Mailing.Edit.Field.RecipientTags.None", "No selection in the recipient tag field of the edit mailing page", "None"), false, mailing.RecipientTag.Value == null)); RecipientLanguages = new List <NamedIntViewModel>(); RecipientLanguages.Add(new NamedIntViewModel(translator, Language.English, mailing.RecipientLanguage.Value == Language.English)); RecipientLanguages.Add(new NamedIntViewModel(translator, Language.German, mailing.RecipientLanguage.Value == Language.German)); RecipientLanguages.Add(new NamedIntViewModel(translator, Language.French, mailing.RecipientLanguage.Value == Language.French)); RecipientLanguages.Add(new NamedIntViewModel(translator, Language.Italian, mailing.RecipientLanguage.Value == Language.Italian)); RecipientLanguages.Add(new NamedIntViewModel(translator.Get("Mailing.Edit.Field.RecipientLanguage.None", "No selection in the recipient language field of the edit mailing page", "None"), false, mailing.RecipientLanguage.Value == null)); SenderGroups = new List <NamedIdViewModel>(db .Query <Group>() .Where(g => session.HasAccess(g, PartAccess.Mailings, AccessRight.Write)) .Select(g => new NamedIdViewModel(translator, g, mailing.Sender.Value == g)) .OrderBy(g => g.Name)); Headers = new List <NamedIdViewModel>(db .Query <MailingElement>() .Where(e => e.Type.Value == MailingElementType.Header) .Select(e => new NamedIdViewModel(e, mailing.Header.Value == e)) .OrderBy(e => e.Name)); Headers.Add(new NamedIdViewModel(translator.Get("Mailing.Edit.Field.Headers.None", "No selection in the header field of the edit mailing page", "None"), false, mailing.Header.Value == null)); Footers = new List <NamedIdViewModel>(db .Query <MailingElement>() .Where(e => e.Type.Value == MailingElementType.Footer) .Select(e => new NamedIdViewModel(e, mailing.Footer.Value == e)) .OrderBy(e => e.Name)); Footers.Add(new NamedIdViewModel(translator.Get("Mailing.Edit.Field.Footers.None", "No selection in the footer field of the edit mailing page", "None"), false, mailing.Footer.Value == null)); }
private void RunSending(IDatabase database, Mailing mailing) { int remainingCount = 0; foreach (var sending in database.Query <Sending>(DC.Equal("mailingid", mailing.Id.Value))) { if (sending.Status.Value == SendingStatus.Created) { if (_maxMailsCount > 0) { _maxMailsCount--; var header = mailing.Header.Value; var footer = mailing.Footer.Value; var htmlText = mailing.HtmlText.Value; var plainText = mailing.PlainText.Value; if (header != null) { htmlText = HtmlWorker.ConcatHtml(header.HtmlText.Value, htmlText); plainText = header.PlainText.Value + plainText; } if (footer != null) { htmlText = HtmlWorker.ConcatHtml(htmlText, footer.HtmlText.Value); plainText = plainText + footer.PlainText.Value; } var translation = new Translation(database); var translator = new Translator(translation, sending.Address.Value.Contact.Value.Language.Value); var templator = new Templator(new ContactContentProvider(translator, sending.Address.Value.Contact.Value)); htmlText = templator.Apply(htmlText); plainText = templator.Apply(plainText); try { var language = sending.Address.Value.Contact.Value.Language.Value; var from = new MimeKit.MailboxAddress( mailing.Sender.Value.MailName.Value[language], mailing.Sender.Value.MailAddress.Value[language]); var to = new MimeKit.MailboxAddress( sending.Address.Value.Contact.Value.ShortHand, sending.Address.Value.Address.Value); var senderKey = mailing.Sender.Value.GpgKeyId.Value == null ? null : new GpgPrivateKeyInfo( mailing.Sender.Value.GpgKeyId.Value, mailing.Sender.Value.GpgKeyPassphrase.Value); var content = new Multipart("alternative"); var textPart = new TextPart("plain") { Text = plainText }; textPart.ContentTransferEncoding = ContentEncoding.QuotedPrintable; content.Add(textPart); var htmlPart = new TextPart("html") { Text = htmlText }; htmlPart.ContentTransferEncoding = ContentEncoding.QuotedPrintable; content.Add(htmlPart); Global.Mail.Send(from, to, senderKey, null, mailing.Subject.Value, content); sending.Status.Value = SendingStatus.Sent; sending.SentDate.Value = DateTime.UtcNow; database.Save(sending); Journal(database, mailing, sending.Address.Value.Contact.Value, "MailTask.Journal.Sent", "Journal entry sent mail", "Task sent mail {0}", t => mailing.Title.Value); } catch (Exception exception) { sending.Status.Value = SendingStatus.Failed; sending.FailureMessage.Value = exception.Message; sending.SentDate.Value = DateTime.UtcNow; database.Save(sending); Journal(database, mailing, sending.Address.Value.Contact.Value, "MailTask.Journal.Failed", "Journal entry sending mail failed", "Task failed sending mail {0}", t => mailing.Title.Value); } } else { remainingCount++; } } } if (remainingCount < 1) { mailing.Status.Value = MailingStatus.Sent; mailing.SentDate.Value = DateTime.UtcNow; database.Save(mailing); Global.Log.Notice("Mailing {0} has finished sending", mailing.Title); } else { Global.Log.Notice("Mailing {0} needs to send {1} more mails", mailing.Title, remainingCount); } }