From bcb8b413110331de70fea47a4149936ec42a5bf9 Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 5 Jun 2025 09:44:57 +0200 Subject: [PATCH] Implement handlebar logic --- .../Registration/VerifyEmail/VerifyEmail.cs | 21 ++++++-- src/Core/Core.csproj | 6 ++- src/Core/Platform/Services/IMailer.cs | 2 +- src/Core/Platform/Services/Mailer.cs | 52 +++++++++++++++++-- test/Core.Test/Platform/MailerTest.cs | 23 ++++++++ 5 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 test/Core.Test/Platform/MailerTest.cs diff --git a/src/Core/Auth/UserFeatures/Registration/VerifyEmail/VerifyEmail.cs b/src/Core/Auth/UserFeatures/Registration/VerifyEmail/VerifyEmail.cs index 81e5e69aeb..8f9417df43 100644 --- a/src/Core/Auth/UserFeatures/Registration/VerifyEmail/VerifyEmail.cs +++ b/src/Core/Auth/UserFeatures/Registration/VerifyEmail/VerifyEmail.cs @@ -1,9 +1,24 @@ -using Bit.Core.Platform.Services; +using System.Net; +using Bit.Core.Platform.Services; namespace Bit.Core.Auth.UserFeatures.Registration.VerifyEmail; -public class VerifyEmail(string url) : BaseMailModel2 +public class VerifyEmail() : BaseMailModel2 { public override string Subject { get; set; } = "Verify Your Email"; - public string Url { get; } = url; + + public required string Token { get; init; } + public required string Email { get; init; } + public required string WebVaultUrl { get; init; } + + public string Url + { + get => string.Format( + "{0}/redirect-connector.html#finish-signup?token={1}&email={2}&fromEmail=true", + WebVaultUrl, + WebUtility.UrlEncode(Token), + WebUtility.UrlEncode(Email) + ); + } + } diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 88ecaf8cef..7dcf3a2d88 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -16,7 +16,9 @@ - + + + @@ -70,7 +72,7 @@ - + diff --git a/src/Core/Platform/Services/IMailer.cs b/src/Core/Platform/Services/IMailer.cs index c14d9d6f56..acb410871d 100644 --- a/src/Core/Platform/Services/IMailer.cs +++ b/src/Core/Platform/Services/IMailer.cs @@ -12,7 +12,7 @@ public interface IMailer /// /// /// Recipient email - public void SendEmail(BaseMailModel2 message, string recipient); + public Task SendEmail(BaseMailModel2 message, string recipient); /// /// Sends multiple emails message to the specified recipients. diff --git a/src/Core/Platform/Services/Mailer.cs b/src/Core/Platform/Services/Mailer.cs index 8167fc1fe6..c1e5a49baa 100644 --- a/src/Core/Platform/Services/Mailer.cs +++ b/src/Core/Platform/Services/Mailer.cs @@ -1,11 +1,57 @@ -namespace Bit.Core.Platform.Services; +using System.Reflection; +using HandlebarsDotNet; + +namespace Bit.Core.Platform.Services; #nullable enable - public class Mailer : IMailer { - public void SendEmail(BaseMailModel2 message, string recipient) => throw new NotImplementedException(); + public IHandlebars H { get; set; } + + public Mailer() + { + H = Handlebars.Create(); + } + + + public async Task SendEmail(BaseMailModel2 message, string recipient) + { + var htmlTemplate = await ReadTemplateAsync(message, "html"); + var textTemplate = await ReadTemplateAsync(message, "txt"); + + + var assembly = typeof(Mailer).Assembly; + var basicHtmlLayoutSource = await ReadSourceAsync(assembly, "Bit.Core.MailTemplates.Handlebars.Layouts.Full.html.hbs"); + H.RegisterTemplate("FullHtmlLayout", basicHtmlLayoutSource); + + var t = H.Compile(htmlTemplate); + var tmp = t(message); + + Console.WriteLine(tmp); + } public void SendEmails(BaseMailModel2 message, string[] recipients) => throw new NotImplementedException(); + + + private static async Task ReadTemplateAsync(BaseMailModel2 message, string suffix) + { + var assembly = message.GetType().Assembly; + var qualifiedName = message.GetType().FullName; + var template = $"{qualifiedName}.{suffix}.hbs"; + + return await ReadSourceAsync(assembly, template); + } + + private static async Task ReadSourceAsync(Assembly assembly, string template) + { + if (assembly.GetManifestResourceNames().All(f => f != template)) + { + return null; + } + + await using var s = assembly.GetManifestResourceStream(template)!; + using var sr = new StreamReader(s); + return await sr.ReadToEndAsync(); + } } diff --git a/test/Core.Test/Platform/MailerTest.cs b/test/Core.Test/Platform/MailerTest.cs new file mode 100644 index 0000000000..732e858931 --- /dev/null +++ b/test/Core.Test/Platform/MailerTest.cs @@ -0,0 +1,23 @@ +using Bit.Core.Auth.UserFeatures.Registration.VerifyEmail; +using Bit.Core.Platform.Services; +using Xunit; + +namespace Bit.Core.Test.Platform; + +public class MailerTest +{ + [Fact] + public async Task SendEmailAsync() + { + var mailer = new Mailer(); + + var mail = new VerifyEmail + { + Token = "test-token", + Email = "test@bitwarden.com", + WebVaultUrl = "https://vault.bitwarden.com" + }; + + await mailer.SendEmail(mail, "test@bitwarden.com"); + } +}