Improved mail template service, added advanced emailsender

This commit is contained in:
Mia Rose Winter 2024-02-13 21:47:24 +01:00
parent 336e18d4e1
commit 46a621cc38
Signed by: miawinter
GPG key ID: 4B6F6A83178F595E
6 changed files with 53 additions and 32 deletions

View file

@ -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> Features
@inject IOptions<Customization> Customizations
@inject NavigationManager Navigation
@inject IEmailSender EmailSender
@inject IAdvancedEmailSender EmailSender
@inject EmailTemplateService TemplateService
<PageTitle>@(TitlePrefix + Localizer["Title"])</PageTitle>
@ -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) +
$"""<p style="text-align: center"><a href="{confirmLink}">{Localizer["Submit"]}</a></p>""");
await EmailSender.SendEmailAsync(subscriber.Email, Localizer["ConfirmEmailSubject"], body);
string body = string.Format(Localizer["ConfirmEmailBody"], Customizations.Value.AppName) +
$"""<p style="text-align: center"><a href="{confirmLink}">{Localizer["Submit"]}</a></p>""";
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.");

View file

@ -122,6 +122,7 @@
if (smtpConfig.Exists()) {
builder.Services.Configure<SmtpConfiguration>(smtpConfig);
builder.Services.AddScoped<IEmailSender, SmtpEmailSender>();
builder.Services.AddScoped<IAdvancedEmailSender, SmtpEmailSender>();
builder.Services.AddScoped<IEmailSender<ApplicationUser>, SmtpEmailSender>();
} else {
builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();

View file

@ -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);
}

View file

@ -81,18 +81,12 @@ public class EmailBackgroundWorker(ILogger<EmailBackgroundWorker> 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, object?>{
{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 },

View file

@ -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, object?> {
{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, object?> {
{ 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"]);

View file

@ -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<SmtpConfiguration> config, ILogger<SmtpEmailSender> logger) : IEmailSender<ApplicationUser>, IEmailSender {
public class SmtpEmailSender(ILogger<SmtpEmailSender> logger, IOptions<SmtpConfiguration> config, IOptions<Customization> customizations, EmailTemplateService templateService) : IEmailSender<ApplicationUser>, IAdvancedEmailSender {
private ILogger<SmtpEmailSender> Logger { get; } = logger;
private SmtpConfiguration Configuration { get; } = config.Value;
private ILogger<SmtpEmailSender> 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 <a href='{confirmationLink}'>clicking here</a>.");
@ -56,11 +58,21 @@ public class SmtpEmailSender(IOptions<SmtpConfiguration> config, ILogger<SmtpEma
throw new EmailNotSendException("Failed Email send.", ex);
}
await client.DisconnectAsync(true);
Logger.LogInformation("Successfully send mail to {email} (subject: {subject}).", email, subject);
} catch (Exception ex) {
Logger.LogError(ex, "Error sending E-Mail");
throw;
}
}
public Task SendDefaultMailAsync(string receiverMail, string? receiverName, string subject, string title, string bodyHtml) {
var host = new Uri(string.IsNullOrWhiteSpace(Customizations.AppUrl) ? "" : Customizations.AppUrl);
string logo = !string.IsNullOrWhiteSpace(Customizations.LogoLink)
? Customizations.LogoLink
: new Uri(host, "/img/logo.png").AbsoluteUri;
string body = TemplateService.Default(host.AbsoluteUri, logo, title, bodyHtml);
return SendEmailAsync(receiverMail, receiverName, subject, body);
}
}
public class EmailNotSendException(string message, Exception exception) : ApplicationException(message, exception);