public async Task SendCommentNotificationEmailAsync( IProjectSettings project, IPost post, IComment comment, string postUrl, string approveUrl, string deleteUrl ) { var sender = await _emailSenderResolver.GetEmailSender(project.Id); if (sender == null) { var logMessage = $"failed to send comment notification email because email settings are not populated for site {project.Title}"; _log.LogError(logMessage); return; } if (string.IsNullOrWhiteSpace(project.CommentNotificationEmail)) { var logMessage = $"failed to send comment notification email because CommentNotificationEmail is not populated for project {project.Id}"; _log.LogError(logMessage); return; } var model = new CommentNotificationModel(project, post, comment, postUrl); var subject = "Blog comment: " + post.Title; string plainTextMessage = null; string htmlMessage = null; try { try { htmlMessage = await _viewRenderer.RenderViewAsString <CommentNotificationModel>("CommentEmail", model); } catch (Exception ex) { _log.LogError("error generating html email from razor template", ex); return; } await sender.SendEmailAsync( project.CommentNotificationEmail, //to null, //from subject, plainTextMessage, htmlMessage, comment.Email, //replyto configLookupKey : project.Id ).ConfigureAwait(false); } catch (Exception ex) { _log.LogError($"error sending comment notification email {ex.Message} : {ex.StackTrace}"); } }
public async Task SendAccountConfirmationEmailAsync( ISiteContext siteSettings, string toAddress, string subject, string confirmationUrl, string confirmCode) { var sender = await _emailSenderResolver.GetEmailSender(siteSettings.Id.ToString()); if (sender == null) { var logMessage = $"failed to send account confirmation email because email settings are not populated for site {siteSettings.SiteName}"; _log.LogError(logMessage); return; } var model = new ConfirmEmailAddessViewModel { ConfirmationUrl = confirmationUrl, ConfirmationCode = confirmCode, Tenant = siteSettings }; try { var plainTextMessage = await _viewRenderer.RenderViewAsString <ConfirmEmailAddessViewModel>("EmailTemplates/ConfirmAccountTextEmail", model).ConfigureAwait(false); var htmlMessage = await _viewRenderer.RenderViewAsString <ConfirmEmailAddessViewModel>("EmailTemplates/ConfirmAccountHtmlEmail", model).ConfigureAwait(false); await sender.SendEmailAsync( toAddress, siteSettings.DefaultEmailFromAddress, subject, plainTextMessage, htmlMessage, configLookupKey : siteSettings.Id.ToString() ).ConfigureAwait(false); } catch (Exception ex) { _log.LogError($"error sending account confirmation email: {ex.Message} stacktrace: {ex.StackTrace}"); } }
public async Task SendAccountConfirmationEmailAsync( ISiteContext siteSettings, string toAddress, string subject, string confirmationUrl) { var smtpOptions = await GetSmptOptions().ConfigureAwait(false); if (smtpOptions == null) { var logMessage = $"failed to send account confirmation email because smtp settings are not populated for site {siteSettings.SiteName}"; log.LogError(logMessage); return; } var sender = new EmailSender(); try { var plainTextMessage = await viewRenderer.RenderViewAsString <string>("EmailTemplates/ConfirmAccountTextEmail", confirmationUrl).ConfigureAwait(false); var htmlMessage = await viewRenderer.RenderViewAsString <string>("EmailTemplates/ConfirmAccountHtmlEmail", confirmationUrl).ConfigureAwait(false); await sender.SendEmailAsync( smtpOptions, toAddress, smtpOptions.DefaultEmailFromAddress, subject, plainTextMessage, htmlMessage).ConfigureAwait(false); } catch (Exception ex) { log.LogError("error sending account confirmation email", ex); } }
public async Task <CommandResult <IPost> > Handle(InitTemplatedPostRequest request, CancellationToken cancellationToken = default(CancellationToken)) { // initialize an unpublished post based on the template var errors = new List <string>(); try { var serializer = GetSerializer(request.Template.SerializerName); var type = Type.GetType(request.Template.ModelType); var model = Activator.CreateInstance(type); var post = new Post { BlogId = request.ProjectId, CreatedByUser = request.CreatedByUserName, DraftAuthor = request.Author, LastModifiedByUser = request.CreatedByUserName, TemplateKey = request.Template.Key, Title = request.ViewModel.Title, Serializer = serializer.Name, DraftSerializedModel = serializer.Serialize(request.Template.ModelType, model), Content = await _viewRenderer.RenderViewAsString(request.Template.RenderView, model).ConfigureAwait(false), IsPublished = false }; await _blogService.Create(post); var result = new CommandResult <IPost>(post, true, errors); return(result); } catch (Exception ex) { _log.LogError($"{ex.Message}:{ex.StackTrace}"); errors.Add(_localizer["Initializing a new post from a content template failed. An error has been logged."]); return(new CommandResult <IPost>(null, false, errors)); } }
public async Task <MessageResult> Process(ContactFormMessage message) { var form = await contactFormResolver.GetCurrentContactForm().ConfigureAwait(false); var smtpOptions = await smtpOptionsProvider.GetSmtpOptions().ConfigureAwait(false); var errorList = new List <MessageError>(); if (string.IsNullOrEmpty(smtpOptions.Server)) { throw new InvalidOperationException("smtp settings are not configured"); } EmailSender sender = new EmailSender(); try { var plainTextMessage = await viewRenderer.RenderViewAsString <ContactFormMessage>(messageProcessorOptions.NotificationTextViewName, message); var htmlMessage = await viewRenderer.RenderViewAsString <ContactFormMessage>(messageProcessorOptions.NotificationHtmlViewName, message); var replyTo = message.Email; await sender.SendMultipleEmailAsync( smtpOptions, form.NotificationEmailCsv, smtpOptions.DefaultEmailFromAddress, message.Subject, plainTextMessage, htmlMessage, replyTo ).ConfigureAwait(false); if (form.CopySubmitterEmailOnSubmission) { try { plainTextMessage = await viewRenderer.RenderViewAsString <ContactFormMessage>( messageProcessorOptions.SubmitterNotificationTextViewName, message); htmlMessage = await viewRenderer.RenderViewAsString <ContactFormMessage>( messageProcessorOptions.SubmitterNotificationHtmlViewName, message); await sender.SendEmailAsync( smtpOptions, message.Email, smtpOptions.DefaultEmailFromAddress, message.Subject, plainTextMessage, htmlMessage ).ConfigureAwait(false); } catch (Exception ex) { log.LogError("error sending contact form submitter notification email", ex); var m = new MessageError(); m.Code = "SubmitterNotificationError"; m.Description = ex.Message; errorList.Add(m); } } } catch (Exception ex) { log.LogError("error sending contact form notification email: " + ex.Message, ex); var m = new MessageError(); m.Code = "NotificationError"; m.Description = ex.Message; errorList.Add(m); } if (errorList.Count > 0) { return(MessageResult.Failed(errorList.ToArray())); } return(MessageResult.Success); }
public async Task <CommandResult <IPage> > Handle(UpdateTemplatedPageRequest request, CancellationToken cancellationToken = default(CancellationToken)) { var errors = new List <string>(); var customModelIsValid = true; try { var page = request.Page; var history = page.CreateHistory(request.UserName); var project = await _projectService.GetProjectSettings(request.ProjectId); var serializer = GetSerializer(request.Template.SerializerName); var parser = GetFormParser(request.Template.FormParserName); var validator = GetValidator(request.Template.ValidatorName); var type = Type.GetType(request.Template.ModelType); var model = parser.ParseModel(request.Template.ModelType, request.Form); if (model == null) { errors.Add(_localizer["Failed to parse custom template model from form."]); customModelIsValid = false; //failed to parse model from form // at least return the original model before changes string pageModelString; if (!string.IsNullOrWhiteSpace(page.DraftSerializedModel)) { pageModelString = page.DraftSerializedModel; } else { pageModelString = page.SerializedModel; } if (!string.IsNullOrWhiteSpace(pageModelString)) { request.ViewModel.TemplateModel = serializer.Deserialize(request.Template.ModelType, pageModelString); } } if (customModelIsValid) { // we are going to return the parsed model either way request.ViewModel.TemplateModel = model; var validationContext = new ValidationContext(model, serviceProvider: null, items: null); var validationResults = new List <ValidationResult>(); customModelIsValid = validator.IsValid(model, validationContext, validationResults); if (!customModelIsValid) { foreach (var item in validationResults) { foreach (var memberName in item.MemberNames) { request.ModelState.AddModelError(memberName, item.ErrorMessage); } } } } if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { // remove any bad characters request.ViewModel.Slug = ContentUtils.CreateSlug(request.ViewModel.Slug); if (request.ViewModel.Slug != page.Slug) { var slugIsAvailable = await _pageService.SlugIsAvailable(request.ViewModel.Slug); if (!slugIsAvailable) { errors.Add(_localizer["The page slug was not changed because the requested slug is already in use."]); request.ModelState.AddModelError("Slug", _localizer["The page slug was not changed because the requested slug is already in use."]); } } } if (request.ModelState.IsValid) { var modelString = serializer.Serialize(request.Template.ModelType, model); var renderedModel = await _viewRenderer.RenderViewAsString(request.Template.RenderView, model).ConfigureAwait(false); page.Title = request.ViewModel.Title; page.CorrelationKey = request.ViewModel.CorrelationKey; page.LastModified = DateTime.UtcNow; page.LastModifiedByUser = request.UserName; page.MenuFilters = request.ViewModel.MenuFilters; page.MetaDescription = request.ViewModel.MetaDescription; page.PageOrder = request.ViewModel.PageOrder; page.ShowHeading = request.ViewModel.ShowHeading; page.ShowMenu = request.ViewModel.ShowMenu; page.ShowComments = request.ViewModel.ShowComments; page.MenuFilters = request.ViewModel.MenuFilters; page.ViewRoles = request.ViewModel.ViewRoles; if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { page.Slug = request.ViewModel.Slug; } page.ViewRoles = request.ViewModel.ViewRoles; if (!string.IsNullOrEmpty(request.ViewModel.ParentSlug)) { var parentPage = await _pageService.GetPageBySlug(request.ViewModel.ParentSlug); if (parentPage != null) { if (parentPage.Id != page.ParentId) { page.ParentId = parentPage.Id; page.ParentSlug = parentPage.Slug; } } } else { // empty means root level page.ParentSlug = string.Empty; page.ParentId = "0"; } if (page.ParentSlug == project.DefaultPageSlug) { _log.LogWarning($"{request.UserName} tried to explicitely set the default page slug as the parent slug which is not allowed since all root pages are already children of the default page"); page.ParentSlug = string.Empty; page.ParentId = "0"; } var shouldFirePublishEvent = false; switch (request.ViewModel.SaveMode) { case SaveMode.SaveDraft: page.DraftSerializedModel = modelString; page.DraftContent = renderedModel; page.DraftAuthor = request.ViewModel.Author; if (!page.PubDate.HasValue) { page.IsPublished = false; } break; case SaveMode.PublishLater: page.DraftSerializedModel = modelString; page.DraftContent = renderedModel; page.DraftAuthor = request.ViewModel.Author; if (request.ViewModel.NewPubDate.HasValue) { var tzId = await _timeZoneIdResolver.GetUserTimeZoneId(CancellationToken.None); page.DraftPubDate = _timeZoneHelper.ConvertToUtc(request.ViewModel.NewPubDate.Value, tzId); } if (!page.PubDate.HasValue) { page.IsPublished = false; } break; case SaveMode.PublishNow: page.Author = request.ViewModel.Author; page.Content = renderedModel; page.SerializedModel = modelString; page.PubDate = DateTime.UtcNow; page.IsPublished = true; shouldFirePublishEvent = true; page.DraftAuthor = null; page.DraftContent = null; page.DraftPubDate = null; page.DraftSerializedModel = null; break; } await _historyCommands.Create(request.ProjectId, history).ConfigureAwait(false); await _pageService.Update(page); if (shouldFirePublishEvent) { await _pageService.FirePublishEvent(page).ConfigureAwait(false); await _historyCommands.DeleteDraftHistory(project.Id, page.Id).ConfigureAwait(false); } await _navigationCache.ClearTreeCache(); } return(new CommandResult <IPage>(page, customModelIsValid && request.ModelState.IsValid, errors)); } catch (Exception ex) { _log.LogError($"{ex.Message}:{ex.StackTrace}"); errors.Add(_localizer["Updating a page from a content template failed. An error has been logged."]); return(new CommandResult <IPage>(null, false, errors)); } }
public async Task <IActionResult> TestEmail(TestSendEmailViewModel model) { var sender = await _emailSenderResolver.GetEmailSender(model.ConfigLookupKey); var messageModel = new TestEmailMessageViewModel { Tenant = _currentSite, Greeting = "Hey there from " + sender.Name, Message = model.Message }; var htmlMessage = await _viewRenderer.RenderViewAsString <TestEmailMessageViewModel>("TestEmailMessage", messageModel).ConfigureAwait(false); if (model.AttachmentFilePathsCsv == "joetest") { model.AttachmentFilePathsCsv = @"C:\_c\cloudscribe\src\sourceDev.WebApp\wwwroot\testfiles\PowerShell_Examples_v4.pdf,C:\_c\cloudscribe\src\sourceDev.WebApp\wwwroot\testfiles\Shortcut-Keys-For-Windows-10.docx"; } List <EmailAttachment> attachments = null; string[] attachmentPaths = null; if (!string.IsNullOrWhiteSpace(model.AttachmentFilePathsCsv)) { attachments = new List <EmailAttachment>(); attachmentPaths = model.AttachmentFilePathsCsv.Split(','); foreach (var path in attachmentPaths) { var stream = System.IO.File.OpenRead(path); var attachment = new EmailAttachment(stream, Path.GetFileName(path)); attachments.Add(attachment); } } var result = await sender.SendEmailAsync( model.ToEmailCsv, model.FromEmail, model.Subject, null, htmlMessage, replyToEmail : model.ReplyToEmail, replyToName : model.ReplyToName, fromName : model.FromName, toAliasCsv : model.ToAliasCsv, ccEmailCsv : model.CcEmailCsv, ccAliasCsv : model.CcAliasCsv, bccEmailCsv : model.BccEmailCsv, bccAliasCsv : model.BccAliasCsv, attachments : attachments, configLookupKey : model.ConfigLookupKey ).ConfigureAwait(false); if (result.Succeeded) { this.AlertSuccess("message sent", true); } else { this.AlertDanger(result.ErrorMessage, true); } return(RedirectToAction("TestEmail")); }
public async Task <CommandResult <IPost> > Handle(UpdateTemplatedPostRequest request, CancellationToken cancellationToken = default(CancellationToken)) { var errors = new List <string>(); var customModelIsValid = true; try { var post = request.Post; var history = post.CreateHistory(request.UserName); var project = await _projectService.GetCurrentProjectSettings(); var serializer = GetSerializer(request.Template.SerializerName); var parser = GetFormParser(request.Template.FormParserName); var validator = GetValidator(request.Template.ValidatorName); var type = Type.GetType(request.Template.ModelType); var model = parser.ParseModel(request.Template.ModelType, request.Form); if (model == null) { errors.Add(_localizer["Failed to parse custom template model from form."]); customModelIsValid = false; //failed to parse model from form // at least return the original model before changes string pageModelString; if (!string.IsNullOrWhiteSpace(post.DraftSerializedModel)) { pageModelString = post.DraftSerializedModel; } else { pageModelString = post.SerializedModel; } if (!string.IsNullOrWhiteSpace(pageModelString)) { request.ViewModel.TemplateModel = serializer.Deserialize(request.Template.ModelType, pageModelString); } } if (customModelIsValid) { // we are going to return the parsed model either way request.ViewModel.TemplateModel = model; var validationContext = new ValidationContext(model, serviceProvider: null, items: null); var validationResults = new List <ValidationResult>(); customModelIsValid = validator.IsValid(model, validationContext, validationResults); if (!customModelIsValid) { foreach (var item in validationResults) { foreach (var memberName in item.MemberNames) { request.ModelState.AddModelError(memberName, item.ErrorMessage); } } } } if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { // remove any bad characters request.ViewModel.Slug = ContentUtils.CreateSlug(request.ViewModel.Slug); if (request.ViewModel.Slug != post.Slug) { var slug = request.ViewModel.Slug; var slugIsAvailable = await _blogService.SlugIsAvailable(slug); while (!slugIsAvailable) { slug += "-"; slugIsAvailable = await _blogService.SlugIsAvailable(slug); } if (slugIsAvailable) { post.Slug = slug; } } } if (request.ModelState.IsValid) { var modelString = serializer.Serialize(request.Template.ModelType, model); var renderedModel = await _viewRenderer.RenderViewAsString(request.Template.RenderView, model).ConfigureAwait(false); post.Title = request.ViewModel.Title; post.CorrelationKey = request.ViewModel.CorrelationKey; post.ImageUrl = request.ViewModel.ImageUrl; post.ThumbnailUrl = request.ViewModel.ThumbnailUrl; post.IsFeatured = request.ViewModel.IsFeatured; post.TeaserOverride = request.ViewModel.TeaserOverride; post.SuppressTeaser = request.ViewModel.SuppressTeaser; post.ShowComments = request.ViewModel.ShowComments; post.LastModified = DateTime.UtcNow; post.LastModifiedByUser = request.UserName; post.MetaDescription = request.ViewModel.MetaDescription; var categories = new List <string>(); if (!string.IsNullOrEmpty(request.ViewModel.Categories)) { if (_editOptions.ForceLowerCaseCategories) { categories = request.ViewModel.Categories.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim().ToLower()) .Where(x => !string.IsNullOrWhiteSpace(x) && x != "," ) .Distinct() .ToList(); } else { categories = request.ViewModel.Categories.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()) .Where(x => !string.IsNullOrWhiteSpace(x) && x != "," ) .Distinct() .ToList(); } } post.Categories = categories; var tzId = await _timeZoneIdResolver.GetUserTimeZoneId(CancellationToken.None); var shouldFirePublishEvent = false; var saveMode = request.ViewModel.SaveMode; if (saveMode == SaveMode.PublishLater) { if (request.ViewModel.NewPubDate.HasValue) { var newPubDate = _timeZoneHelper.ConvertToUtc(request.ViewModel.NewPubDate.Value, tzId); if (newPubDate < DateTime.UtcNow) { saveMode = SaveMode.PublishNow; post.PubDate = newPubDate; } } } switch (saveMode) { case SaveMode.SaveDraft: post.DraftSerializedModel = modelString; post.DraftContent = renderedModel; post.DraftAuthor = request.ViewModel.Author; if (!post.PubDate.HasValue) { post.IsPublished = false; } break; case SaveMode.PublishLater: post.DraftSerializedModel = modelString; post.DraftContent = renderedModel; post.DraftAuthor = request.ViewModel.Author; if (request.ViewModel.NewPubDate.HasValue) { post.DraftPubDate = _timeZoneHelper.ConvertToUtc(request.ViewModel.NewPubDate.Value, tzId); } if (!post.PubDate.HasValue) { post.IsPublished = false; } break; case SaveMode.PublishNow: post.Author = request.ViewModel.Author; post.Content = renderedModel; post.SerializedModel = modelString; if (!post.PubDate.HasValue) { post.PubDate = DateTime.UtcNow; } post.IsPublished = true; shouldFirePublishEvent = true; post.DraftAuthor = null; post.DraftContent = null; post.DraftPubDate = null; post.DraftSerializedModel = null; break; } if (project.TeaserMode != TeaserMode.Off) { // need to generate the teaser on save var teaserResult = _teaserService.GenerateTeaser( project.TeaserTruncationMode, project.TeaserTruncationLength, post.Content, Guid.NewGuid().ToString(),//cache key post.Slug, project.LanguageCode, false //logWarnings ); post.AutoTeaser = teaserResult.Content; } await _historyCommands.Create(request.ProjectId, history).ConfigureAwait(false); await _blogService.Update(post); if (shouldFirePublishEvent) { await _blogService.FirePublishEvent(post).ConfigureAwait(false); await _historyCommands.DeleteDraftHistory(project.Id, post.Id).ConfigureAwait(false); } } return(new CommandResult <IPost>(post, customModelIsValid && request.ModelState.IsValid, errors)); } catch (Exception ex) { _log.LogError($"{ex.Message}:{ex.StackTrace}"); errors.Add(_localizer["Updating a post from a content template failed. An error has been logged."]); return(new CommandResult <IPost>(null, false, errors)); } }
public async Task <CommandResult <IPage> > Handle(InitTemplatedPageRequest request, CancellationToken cancellationToken = default(CancellationToken)) { // initialize an unpublished page based on the template var errors = new List <string>(); try { var serializer = GetSerializer(request.Template.SerializerName); var type = Type.GetType(request.Template.ModelType); var model = Activator.CreateInstance(type); var page = new Page { ProjectId = request.ProjectId, CreatedByUser = request.CreatedByUserName, DraftAuthor = request.Author, LastModifiedByUser = request.CreatedByUserName, TemplateKey = request.Template.Key, Title = request.ViewModel.Title, Serializer = serializer.Name, DraftSerializedModel = serializer.Serialize(request.Template.ModelType, model), ParentSlug = request.ViewModel.ParentSlug, PageOrder = request.ViewModel.PageOrder, Content = await _viewRenderer.RenderViewAsString(request.Template.RenderView, model).ConfigureAwait(false), IsPublished = false }; if (!string.IsNullOrEmpty(request.ViewModel.ParentSlug)) { var parentPage = await _pageService.GetPageBySlug(request.ViewModel.ParentSlug); if (parentPage != null) { if (parentPage.Id != page.ParentId) { page.ParentId = parentPage.Id; page.ParentSlug = parentPage.Slug; } } } else { // empty means root level page.ParentSlug = string.Empty; page.ParentId = "0"; } await _pageService.Create(page); await _navigationCache.ClearTreeCache(); var result = new CommandResult <IPage>(page, true, errors); return(result); } catch (Exception ex) { _log.LogError($"{ex.Message}:{ex.StackTrace}"); errors.Add(_localizer["Initializing a new page from a content template failed. An error has been logged."]); return(new CommandResult <IPage>(null, false, errors)); } }
public async Task SendCommentNotificationEmailAsync( IProjectSettings project, IPost post, IComment comment, string postUrl, string approveUrl, string deleteUrl ) { var smtpOptions = GetSmptOptions(project); if (smtpOptions == null) { var logMessage = $"failed to send comment notification email because smtp settings are not populated for project {project.Id}"; log.LogError(logMessage); return; } if (string.IsNullOrWhiteSpace(project.CommentNotificationEmail)) { var logMessage = $"failed to send comment notification email because CommentNotificationEmail is not populated for project {project.Id}"; log.LogError(logMessage); return; } if (string.IsNullOrWhiteSpace(project.EmailFromAddress)) { var logMessage = $"failed to send comment notification email because EmailFromAddress is not populated for project {project.Id}"; log.LogError(logMessage); return; } var model = new CommentNotificationModel(project, post, comment, postUrl); var subject = "Blog comment: " + post.Title; string plainTextMessage = null; string htmlMessage = null; var sender = new EmailSender(); try { try { htmlMessage = await viewRenderer.RenderViewAsString <CommentNotificationModel>("CommentEmail", model); } catch (Exception ex) { log.LogError("error generating html email from razor template", ex); return; } await sender.SendEmailAsync( smtpOptions, project.CommentNotificationEmail, //to project.EmailFromAddress, //from subject, plainTextMessage, htmlMessage, comment.Email //replyto ).ConfigureAwait(false); } catch (Exception ex) { log.LogError("error sending comment notification email", ex); } }
public async Task <MessageResult> Process(ContactFormMessage message) { var errorList = new List <MessageError>(); var sender = await _emailSenderResolver.GetEmailSender(); if (sender == null) { var logMessage = $"failed to send account confirmation email because email settings are not populated"; _log.LogError(logMessage); var m = new MessageError { Code = "NoSenderError", Description = logMessage }; errorList.Add(m); return(MessageResult.Failed(errorList.ToArray())); } var form = await _contactFormResolver.GetCurrentContactForm().ConfigureAwait(false); message.Tenant = await _tenantResolver.ResolveTenant(); try { var plainTextMessage = await _viewRenderer.RenderViewAsString <ContactFormMessage>(_messageProcessorOptions.NotificationTextViewName, message); var htmlMessage = await _viewRenderer.RenderViewAsString <ContactFormMessage>(_messageProcessorOptions.NotificationHtmlViewName, message); var replyTo = message.Email; await sender.SendEmailAsync( form.NotificationEmailCsv, null, message.Subject, plainTextMessage, htmlMessage, replyTo ).ConfigureAwait(false); if (form.CopySubmitterEmailOnSubmission) { try { plainTextMessage = await _viewRenderer.RenderViewAsString <ContactFormMessage>( _messageProcessorOptions.SubmitterNotificationTextViewName, message); htmlMessage = await _viewRenderer.RenderViewAsString <ContactFormMessage>( _messageProcessorOptions.SubmitterNotificationHtmlViewName, message); await sender.SendEmailAsync( message.Email, null, message.Subject, plainTextMessage, htmlMessage ).ConfigureAwait(false); } catch (Exception ex) { _log.LogError($"error sending contact form submitter notification email {ex.Message} : {ex.StackTrace}"); var m = new MessageError { Code = "SubmitterNotificationError", Description = ex.Message }; errorList.Add(m); } } } catch (Exception ex) { _log.LogError($"error sending contact form notification email: {ex.Message} : {ex.StackTrace}"); var m = new MessageError { Code = "NotificationError", Description = ex.Message }; errorList.Add(m); } if (errorList.Count > 0) { return(MessageResult.Failed(errorList.ToArray())); } return(MessageResult.Success); }