Implemented new mail system components

This commit is contained in:
Marcel Baumgartner
2023-07-13 20:39:02 +02:00
parent 5bd6f15203
commit 591da6de5c
2 changed files with 105 additions and 41 deletions

View File

@@ -2,6 +2,7 @@
using Moonlight.App.Database.Entities; using Moonlight.App.Database.Entities;
using Moonlight.App.Exceptions; using Moonlight.App.Exceptions;
using Moonlight.App.Helpers; using Moonlight.App.Helpers;
using Moonlight.App.Repositories;
using SmtpClient = MailKit.Net.Smtp.SmtpClient; using SmtpClient = MailKit.Net.Smtp.SmtpClient;
namespace Moonlight.App.Services.Mail; namespace Moonlight.App.Services.Mail;
@@ -14,8 +15,14 @@ public class MailService
private readonly int Port; private readonly int Port;
private readonly bool Ssl; private readonly bool Ssl;
public MailService(ConfigService configService) private readonly Repository<User> UserRepository;
public MailService(
ConfigService configService,
Repository<User> userRepository)
{ {
UserRepository = userRepository;
var mailConfig = configService var mailConfig = configService
.Get() .Get()
.Moonlight.Mail; .Moonlight.Mail;
@@ -26,29 +33,9 @@ public class MailService
Port = mailConfig.Port; Port = mailConfig.Port;
Ssl = mailConfig.Ssl; Ssl = mailConfig.Ssl;
} }
public async Task SendMail( public Task SendMailRaw(User user, string html)
User user,
string name,
Action<Dictionary<string, string>> values
)
{ {
if (!File.Exists(PathBuilder.File("storage", "resources", "mail", $"{name}.html")))
{
Logger.Warn($"Mail template '{name}' not found. Make sure to place one in the resources folder");
throw new DisplayException("Mail template not found");
}
var rawHtml = await File.ReadAllTextAsync(PathBuilder.File("storage", "resources", "mail", $"{name}.html"));
var val = new Dictionary<string, string>();
values.Invoke(val);
val.Add("FirstName", user.FirstName);
val.Add("LastName", user.LastName);
var parsed = ParseMail(rawHtml, val);
Task.Run(async () => Task.Run(async () =>
{ {
try try
@@ -62,17 +49,15 @@ public class MailService
var body = new BodyBuilder var body = new BodyBuilder
{ {
HtmlBody = parsed HtmlBody = html
}; };
mailMessage.Body = body.ToMessageBody(); mailMessage.Body = body.ToMessageBody();
using (var smtpClient = new SmtpClient()) using var smtpClient = new SmtpClient();
{ await smtpClient.ConnectAsync(Server, Port, Ssl);
await smtpClient.ConnectAsync(Server, Port, Ssl); await smtpClient.AuthenticateAsync(Email, Password);
await smtpClient.AuthenticateAsync(Email, Password); await smtpClient.SendAsync(mailMessage);
await smtpClient.SendAsync(mailMessage); await smtpClient.DisconnectAsync(true);
await smtpClient.DisconnectAsync(true);
}
} }
catch (Exception e) catch (Exception e)
{ {
@@ -80,6 +65,54 @@ public class MailService
Logger.Warn(e); Logger.Warn(e);
} }
}); });
return Task.CompletedTask;
}
public async Task SendMail(User user, string template, Action<Dictionary<string, string>> values)
{
if (!File.Exists(PathBuilder.File("storage", "resources", "mail", $"{template}.html")))
{
Logger.Warn($"Mail template '{template}' not found. Make sure to place one in the resources folder");
throw new DisplayException("Mail template not found");
}
var rawHtml = await File.ReadAllTextAsync(PathBuilder.File("storage", "resources", "mail", $"{template}.html"));
var val = new Dictionary<string, string>();
values.Invoke(val);
val.Add("FirstName", user.FirstName);
val.Add("LastName", user.LastName);
var parsed = ParseMail(rawHtml, val);
await SendMailRaw(user, parsed);
}
public async Task SendEmailToAll(string template, Action<Dictionary<string, string>> values)
{
var users = UserRepository
.Get()
.ToArray();
foreach (var user in users)
{
await SendMail(user, template, values);
}
}
public async Task SendEmailToAllAdmins(string template, Action<Dictionary<string, string>> values)
{
var users = UserRepository
.Get()
.Where(x => x.Admin)
.ToArray();
foreach (var user in users)
{
await SendMail(user, template, values);
}
} }
private string ParseMail(string html, Dictionary<string, string> values) private string ParseMail(string html, Dictionary<string, string> values)

View File

@@ -5,17 +5,35 @@
@using Moonlight.App.Helpers.Files @using Moonlight.App.Helpers.Files
@using Moonlight.App.Helpers @using Moonlight.App.Helpers
@using BlazorTable @using BlazorTable
@using Moonlight.App.Database.Entities
@using Moonlight.App.Models.Misc @using Moonlight.App.Models.Misc
@using Moonlight.App.Services @using Moonlight.App.Services
@using Moonlight.App.Services.Interop @using Moonlight.App.Services.Interop
@using Moonlight.App.Services.Mail
@inject SmartTranslateService SmartTranslateService @inject SmartTranslateService SmartTranslateService
@inject ToastService ToastService @inject ToastService ToastService
@inject AlertService AlertService @inject AlertService AlertService
@inject MailService MailService
<OnlyAdmin> <OnlyAdmin>
<AdminSystemNavigation Index="9"/> <AdminSystemNavigation Index="9"/>
<div class="card mb-3">
<div class="card-header">
<span class="card-title">
<TL>Actions</TL>
</span>
</div>
<div class="card-body">
<WButton Text="@(SmartTranslateService.Translate("Test mail configuration"))"
WorkingText="@(SmartTranslateService.Translate("Sending test mail"))"
CssClasses="btn-primary"
OnClick="SendTestMail">
</WButton>
</div>
</div>
<LazyLoader @ref="LazyLoader" Load="Load"> <LazyLoader @ref="LazyLoader" Load="Load">
@if (CurrentMailTemplate == null) @if (CurrentMailTemplate == null)
{ {
@@ -63,9 +81,9 @@
} }
else else
{ {
<FileEditor Language="html" <FileEditor Language="html"
HideControls="false" HideControls="false"
InitialData="@(CurrentMailTemplateContent)" InitialData="@(CurrentMailTemplateContent)"
OnCancel="OnCancelTemplateEdit" OnCancel="OnCancelTemplateEdit"
OnSubmit="OnSubmitTemplateEdit"/> OnSubmit="OnSubmitTemplateEdit"/>
} }
@@ -74,12 +92,17 @@
@code @code
{ {
[CascadingParameter]
public User User { get; set; }
private MailTemplate[] MailTemplateFiles; private MailTemplate[] MailTemplateFiles;
private FileAccess FileAccess; private FileAccess FileAccess;
private LazyLoader LazyLoader; private LazyLoader LazyLoader;
#region Template Editor
private MailTemplate? CurrentMailTemplate; private MailTemplate? CurrentMailTemplate;
private string CurrentMailTemplateContent; private string CurrentMailTemplateContent = "";
private async Task Load(LazyLoader arg) private async Task Load(LazyLoader arg)
{ {
@@ -101,10 +124,10 @@
private async Task EditTemplate(MailTemplate mailTemplate) private async Task EditTemplate(MailTemplate mailTemplate)
{ {
CurrentMailTemplate = mailTemplate; CurrentMailTemplate = mailTemplate;
CurrentMailTemplateContent = await FileAccess CurrentMailTemplateContent = await FileAccess
.Read(CurrentMailTemplate.File); .Read(CurrentMailTemplate.File);
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
} }
@@ -135,15 +158,23 @@
SmartTranslateService.Translate("Enter the name of the new template"), SmartTranslateService.Translate("Enter the name of the new template"),
"" ""
); );
if(string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
return; return;
await FileAccess.Write(new() await FileAccess.Write(new()
{ {
Name = name + ".html" Name = name + ".html"
}, ""); }, "");
await LazyLoader.Reload(); await LazyLoader.Reload();
} }
#endregion
private async Task SendTestMail()
{
await MailService.SendMailRaw(User, "<html><body>If you see this mail, your moonlight mail configuration is ready to use</body></html>");
await AlertService.Info(SmartTranslateService.Translate("A test mail has been sent to the email address of your account"));
}
} }