diff --git a/Wave/Components/Pages/EmailSignup.razor b/Wave/Components/Pages/EmailSignup.razor index 297ef28..c369e4c 100644 --- a/Wave/Components/Pages/EmailSignup.razor +++ b/Wave/Components/Pages/EmailSignup.razor @@ -5,7 +5,6 @@ @using Wave.Data @using System.ComponentModel.DataAnnotations @using System.Net -@using Microsoft.AspNetCore.Identity.UI.Services @using Microsoft.EntityFrameworkCore @using Wave.Services @@ -15,7 +14,7 @@ @inject IOptions Features @inject IOptions Customizations @inject NavigationManager Navigation -@inject IEmailSender EmailSender +@inject IAdvancedEmailSender EmailSender @inject EmailTemplateService TemplateService @(TitlePrefix + Localizer["Title"]) @@ -80,7 +79,10 @@ subscriber.Unsubscribed = false; await context.SaveChangesAsync(); + await TemplateService.ValidateTokensAsync(Id, Token, deleteToken: true); Message = Localizer["Success_Message"]; + + } catch (Exception ex) { Logger.LogError(ex, "Error trying to confirm subscriber."); Message = Localizer["Failure_Message"]; @@ -111,17 +113,10 @@ string confirmLink = Navigation.ToAbsoluteUri( $"/Email/Confirm?user={WebUtility.UrlEncode(id)}&token={WebUtility.UrlEncode(token)}").AbsoluteUri; - - var customization = Customizations.Value; - string body = TemplateService.Default( - Navigation.BaseUri, - !string.IsNullOrWhiteSpace(customization.LogoLink) ? - customization.LogoLink : - Navigation.ToAbsoluteUri("/img/logo.png").AbsoluteUri, - Localizer["ConfirmEmailTitle"], - string.Format(Localizer["ConfirmEmailBody"], customization.AppName) + - $"""

{Localizer["Submit"]}

"""); - await EmailSender.SendEmailAsync(subscriber.Email, Localizer["ConfirmEmailSubject"], body); + string body = string.Format(Localizer["ConfirmEmailBody"], Customizations.Value.AppName) + + $"""

{Localizer["Submit"]}

"""; + await EmailSender.SendDefaultMailAsync(subscriber.Email, subscriber.Name, Localizer["ConfirmEmailSubject"], + Localizer["ConfirmEmailTitle"], body); } } catch (Exception ex) { Logger.LogError(ex, "Failed to create subscriber/send confirmation mail."); diff --git a/Wave/Program.cs b/Wave/Program.cs index a56e123..fd55c1f 100644 --- a/Wave/Program.cs +++ b/Wave/Program.cs @@ -122,6 +122,7 @@ if (smtpConfig.Exists()) { builder.Services.Configure(smtpConfig); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped, SmtpEmailSender>(); } else { builder.Services.AddSingleton, IdentityNoOpEmailSender>(); diff --git a/Wave/Services/AdvancedEmailSender.cs b/Wave/Services/AdvancedEmailSender.cs new file mode 100644 index 0000000..c763dc8 --- /dev/null +++ b/Wave/Services/AdvancedEmailSender.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNetCore.Identity.UI.Services; + +namespace Wave.Services; + +public interface IAdvancedEmailSender : IEmailSender { + Task SendEmailAsync(string email, string? name, string subject, string htmlMessage); + Task SendDefaultMailAsync(string receiverMail, string? receiverName, string subject, string title, string bodyHtml); +} \ No newline at end of file diff --git a/Wave/Services/EmailBackgroundWorker.cs b/Wave/Services/EmailBackgroundWorker.cs index 4e1e7f4..e2b022c 100644 --- a/Wave/Services/EmailBackgroundWorker.cs +++ b/Wave/Services/EmailBackgroundWorker.cs @@ -81,18 +81,12 @@ public class EmailBackgroundWorker(ILogger logger, IDbCon newsletter.IsSend = true; context.SaveChanges(); - string articleLink = ArticleUtilities.GenerateArticleLink( - newsletter.Article, new Uri(Customizations.AppUrl, UriKind.Absolute)); - string template = TemplateService.Process("newsletter", new Dictionary{ - {EmailTemplateService.Constants.BrowserLink, articleLink}, - {EmailTemplateService.Constants.ContentLogo, (!string.IsNullOrWhiteSpace(Customizations.LogoLink) ? - new Uri(Customizations.LogoLink) : - new Uri(host, "/img/logo.png")) - .AbsoluteUri}, - {EmailTemplateService.Constants.ContentTitle, newsletter.Article.Title}, - {EmailTemplateService.Constants.ContentBody, newsletter.Article.BodyHtml}, - {EmailTemplateService.Constants.EmailUnsubscribeLink, "[[<__UNSUBSCRIBE__>]]"} - }); + string articleLink = ArticleUtilities.GenerateArticleLink(newsletter.Article, new Uri(Customizations.AppUrl, UriKind.Absolute)); + string template = TemplateService.Newsletter(host.AbsoluteUri, articleLink, + (!string.IsNullOrWhiteSpace(Customizations.LogoLink) ? + new Uri(Customizations.LogoLink) : + new Uri(host, "/img/logo.png")).AbsoluteUri, newsletter.Article.Title, newsletter.Article.BodyHtml, + "[[<__UNSUBSCRIBE__>]]"); var message = new MimeMessage { From = { sender }, diff --git a/Wave/Services/EmailTemplateService.cs b/Wave/Services/EmailTemplateService.cs index ce9014e..8ebed30 100644 --- a/Wave/Services/EmailTemplateService.cs +++ b/Wave/Services/EmailTemplateService.cs @@ -42,15 +42,26 @@ public enum Constants { } - public string Default(string url, string logoLink, string title, string body) { + public string Default(string home, string logoLink, string title, string body) { return Process("default", new Dictionary { - {Constants.HomeLink, url}, + {Constants.HomeLink, home}, {Constants.ContentLogo, logoLink}, {Constants.ContentTitle, title}, {Constants.ContentBody, body} }); } + public string Newsletter(string home, string browserUrl, string logoLink, string title, string body, string unsubscribe) { + return Process("newsletter", new Dictionary { + { Constants.HomeLink, home }, + { Constants.BrowserLink, browserUrl }, + { Constants.ContentLogo, logoLink }, + { Constants.ContentTitle, title }, + { Constants.ContentBody, body }, + { Constants.EmailUnsubscribeLink, unsubscribe } + }); + } + public void TryCreateDefaultTemplates() { FileSystem.GetEmailTemplate("default", DefaultTemplates["default"]); FileSystem.GetEmailTemplate("newsletter", DefaultTemplates["newsletter"]); diff --git a/Wave/Services/SmtpEmailSender.cs b/Wave/Services/SmtpEmailSender.cs index 6cdcdac..8b53662 100644 --- a/Wave/Services/SmtpEmailSender.cs +++ b/Wave/Services/SmtpEmailSender.cs @@ -1,18 +1,20 @@ using MailKit.Net.Smtp; using MailKit.Security; using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Identity.UI.Services; using Microsoft.Extensions.Options; using MimeKit; using Wave.Data; +using Uri = System.Uri; namespace Wave.Services; -public class SmtpEmailSender(IOptions config, ILogger logger) : IEmailSender, IEmailSender { +public class SmtpEmailSender(ILogger logger, IOptions config, IOptions customizations, EmailTemplateService templateService) : IEmailSender, IAdvancedEmailSender { + private ILogger Logger { get; } = logger; private SmtpConfiguration Configuration { get; } = config.Value; - private ILogger Logger { get; } = logger; - - public Task SendConfirmationLinkAsync(ApplicationUser user, string email, string confirmationLink) => + private Customization Customizations { get; } = customizations.Value; + private EmailTemplateService TemplateService { get; } = templateService; + + public Task SendConfirmationLinkAsync(ApplicationUser user, string email, string confirmationLink) => SendEmailAsync(email, "Confirm your email", $"Please confirm your account by clicking here."); @@ -56,11 +58,21 @@ public class SmtpEmailSender(IOptions config, ILogger