diff --git a/Wave/Services/EmailFactory.cs b/Wave/Services/EmailFactory.cs index ffd2072..772751e 100644 --- a/Wave/Services/EmailFactory.cs +++ b/Wave/Services/EmailFactory.cs @@ -82,6 +82,14 @@ public class EmailFactory(IOptions customizations, EmailTemplateS }.ToFrozenDictionary()); } + public async ValueTask CreateAuthorCard(ApplicationUser user, Uri host) { + var profileLink = new Uri(host, "/profile/" + user.Id); + var pfpLink = new Uri(host, "api/user/pfp/" + user.Id + "?size=100"); + + string partial = await TemplateService.GetPartialAsync("email-author"); + return string.Format(partial, pfpLink, user.FullName, user.AboutTheAuthor, profileLink.AbsoluteUri); + } + public async ValueTask IsTokenValid(string id, string token) { return await TemplateService.ValidateTokensAsync(id, token, deleteToken: false); } diff --git a/Wave/Services/EmailTemplateService.cs b/Wave/Services/EmailTemplateService.cs index 32ce245..4f76eaa 100644 --- a/Wave/Services/EmailTemplateService.cs +++ b/Wave/Services/EmailTemplateService.cs @@ -98,6 +98,7 @@ public enum Constants { FileSystem.GetEmailTemplate("welcome", DefaultTemplates["welcome"]); FileSystem.GetPartialTemplate("email-article", DefaultPartials["email-article"]); FileSystem.GetPartialTemplate("email-plain-footer", DefaultPartials["email-plain-footer"]); + FileSystem.GetPartialTemplate("email-author", DefaultPartials["email-author"]); } public string ApplyTokens(string template, Func replacer) { @@ -312,6 +313,20 @@ public enum Constants { { "email-plain-footer", $"Unsubscribe: [[{Constants.EmailUnsubscribeLink}]]" + }, + { + "email-author", + """ +
+ + +

{1}

+

{2}

+ Profile +
+
+ """ } }; } \ No newline at end of file diff --git a/Wave/Services/NewsletterBackgroundService.cs b/Wave/Services/NewsletterBackgroundService.cs index 1ceb34c..cba707c 100644 --- a/Wave/Services/NewsletterBackgroundService.cs +++ b/Wave/Services/NewsletterBackgroundService.cs @@ -18,9 +18,10 @@ public class NewsletterBackgroundService(ILogger lo await using var context = await ContextFactory.CreateDbContextAsync(cancellationToken); var now = DateTimeOffset.UtcNow; var newsletters = context.Set() + .IgnoreQueryFilters() .Include(n => n.Article.Author) .Include(n => n.Article.Categories) - .Where(n => !n.IsSend && n.DistributionDateTime <= now) + .Where(n => !n.Article.IsDeleted && !n.IsSend && n.DistributionDateTime <= now) .ToList(); if (newsletters.Count < 1) return; @@ -38,6 +39,9 @@ public class NewsletterBackgroundService(ILogger lo string replyTo = ""; if (!string.IsNullOrWhiteSpace(newsletter.Article.Author.ContactEmail)) replyTo = $"{newsletter.Article.Author.Name} <{newsletter.Article.Author.ContactEmail}>"; + string aboutTheAuthor = await factory.CreateAuthorCard( + newsletter.Article.Author, + new Uri(Customizations.AppUrl, UriKind.Absolute)); Logger.LogInformation("Processing '{title}'.", newsletter.Article.Title); // set newsletter to send first, so we don't spam people @@ -55,10 +59,11 @@ public class NewsletterBackgroundService(ILogger lo last = subscribers.Last(); foreach (var subscriber in subscribers) { - var email = await factory.CreateSubscribedEmail(subscriber, articleLink, + var email = await factory.CreateSubscribedEmail( + subscriber, articleLink, newsletter.Article.Title, - newsletter.Article.Title, - newsletter.Article.BodyHtml, + newsletter.Article.Title, + newsletter.Article.BodyHtml + aboutTheAuthor, newsletter.Article.BodyPlain, "newsletter-" + newsletter.Id, replyTo); await client.SendEmailAsync(email);