Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Core/Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<EmbeddedResource Include="licensing.cer" />
<EmbeddedResource Include="licensing_dev.cer" />
<EmbeddedResource Include="MailTemplates\Handlebars\**\*.hbs" />
<EmbeddedResource Include="MailTemplates\Mjml\Handlebars\**\*.hbs" />
</ItemGroup>

<ItemGroup>
Expand Down Expand Up @@ -72,7 +73,7 @@
<PackageReference Include="System.Text.Json" Version="8.0.5" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
</ItemGroup>

<ItemGroup>
<Folder Include="Resources\" />
<Folder Include="Properties\" />
Expand Down
675 changes: 675 additions & 0 deletions src/Core/MailTemplates/Mjml/Handlebars/Auth/send-email-otp.html.hbs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
๏ปฟ{{#>BasicTextLayout}}
Verify your email to access this Bitwarden Send.

Your verification code is: {{Token}}

This code can only be used once and expires in {{Expiry}} minutes. After that you'll need to verify your email again.

Bitwarden Send transmits sensitive, temporary information to others easily and securely. Learn more about Bitwarden Send or sign up to try it today.
{{/BasicTextLayout}}
405 changes: 405 additions & 0 deletions src/Core/MailTemplates/Mjml/Handlebars/Auth/two-factor.html.hbs

Large diffs are not rendered by default.

571 changes: 571 additions & 0 deletions src/Core/MailTemplates/Mjml/Handlebars/invite.html.hbs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/Core/MailTemplates/Mjml/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const flags = {
// Use __dirname to get absolute paths relative to the script location
const config = {
inputDir: path.join(__dirname, "emails"),
outputDir: path.join(__dirname, "out"),
outputDir: flags.hbs ? path.join(__dirname, "Handlebars") : path.join(__dirname, "out"),
minify: flags.minify,
validationLevel: "strict",
hbsOutput: flags.hbs,
Expand Down
1 change: 1 addition & 0 deletions src/Core/MailTemplates/Mjml/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"build:hbs": "node ./build.js --hbs",
"build:minify": "node ./build.js --hbs --minify",
"build:watch": "nodemon ./build.js --watch emails --watch components --ext mjml,js",
"build:watch:hbs": "nodemon ./build.js --hbs --watch emails --watch components --ext mjml,js",
"prettier": "prettier --cache --write ."
},
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Services/IMailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Task SendTrialInitiationSignupEmailAsync(
/// <param name="token">Otp code token</param>
/// <param name="subject">subject line of the email</param>
/// <returns>Task</returns>
Task SendSendEmailOtpEmailv2Async(string email, string token, string subject);
Task SendMJMLSendEmailOtpEmailAsync(string email, string token, string subject);
Task SendFailedTwoFactorAttemptEmailAsync(string email, TwoFactorProviderType type, DateTime utcNow, string ip);
Task SendNoMasterPasswordHintEmailAsync(string email);
Task SendMasterPasswordHintEmailAsync(string email, string hint);
Expand Down
16 changes: 12 additions & 4 deletions src/Core/Services/Implementations/HandlebarsMailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ namespace Bit.Core.Services;

public class HandlebarsMailService : IMailService
{
private const string Namespace = "Bit.Core.MailTemplates.Handlebars";
// This namespace is the legacy name space when we only utilized handlebars processes to render email templates.
private const string _handlebarsTemplateNamespace = "Bit.Core.MailTemplates.Handlebars";
// This namespace is for mjml compiled emails, allowing for better email client rendering while still able to use handlebars for content.
private const string _mjmlTemplateNamespace = "Bit.Core.MailTemplates.Mjml.Handlebars";
private const string _utcTimeZoneDisplay = "UTC";
private const string FailedTwoFactorAttemptCacheKeyFormat = "FailedTwoFactorAttemptEmail_{0}";

Expand Down Expand Up @@ -224,7 +227,7 @@ public async Task SendSendEmailOtpEmailAsync(string email, string token, string
await _mailDeliveryService.SendEmailAsync(message);
}

public async Task SendSendEmailOtpEmailv2Async(string email, string token, string subject)
public async Task SendMJMLSendEmailOtpEmailAsync(string email, string token, string subject)
{
var message = CreateDefaultMessage(subject, email);
var requestDateTime = DateTime.UtcNow;
Expand All @@ -238,7 +241,7 @@ public async Task SendSendEmailOtpEmailv2Async(string email, string token, strin
WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
SiteName = _globalSettings.SiteName,
};
await AddMessageContentAsync(message, "Auth.SendAccessEmailOtpEmailv2", model);
await AddMessageContentAsync(message, $"{_mjmlTemplateNamespace}.Auth.send-email-otp", model);
message.MetaData.Add("SendGridBypassListManagement", true);
// TODO - PM-25380 change to string constant
message.Category = "SendEmailOtp";
Expand Down Expand Up @@ -740,7 +743,12 @@ private async Task AddMessageContentAsync<T>(MailMessage message, string templat
}

var assembly = typeof(HandlebarsMailService).GetTypeInfo().Assembly;
var fullTemplateName = $"{Namespace}.{templateName}.hbs";

var mjmlTemplate = templateName.StartsWith(_mjmlTemplateNamespace);

// MJML templateName already includes the full namespace path
var fullTemplateName = mjmlTemplate ? $"{templateName}.hbs" : $"{_handlebarsTemplateNamespace}.{templateName}.hbs";

if (!assembly.GetManifestResourceNames().Any(f => f == fullTemplateName))
{
return null;
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Services/NoopImplementations/NoopMailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public Task SendSendEmailOtpEmailAsync(string email, string token, string subjec
return Task.FromResult(0);
}

public Task SendSendEmailOtpEmailv2Async(string email, string token, string subject)
public Task SendMJMLSendEmailOtpEmailAsync(string email, string token, string subject)
{
return Task.FromResult(0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public async Task<GrantValidationResult> ValidateRequestAsync(ExtensionGrantVali
}
if (featureService.IsEnabled(FeatureFlagKeys.MJMLBasedEmailTemplates))
{
await mailService.SendSendEmailOtpEmailv2Async(
await mailService.SendMJMLSendEmailOtpEmailAsync(
email,
token,
string.Format(SendAccessConstants.OtpEmail.Subject, token));
Expand Down
Loading