diff --git a/src/Core/Constants.cs b/src/Core/Constants.cs index 499254bc31..8fb213245a 100644 --- a/src/Core/Constants.cs +++ b/src/Core/Constants.cs @@ -160,7 +160,6 @@ public static class FeatureFlagKeys public const string Otp6Digits = "pm-18612-otp-6-digits"; public const string PM24579_PreventSsoOnExistingNonCompliantUsers = "pm-24579-prevent-sso-on-existing-non-compliant-users"; public const string DisableAlternateLoginMethods = "pm-22110-disable-alternate-login-methods"; - public const string MJMLBasedEmailTemplates = "mjml-based-email-templates"; public const string PM2035PasskeyUnlock = "pm-2035-passkey-unlock"; public const string MjmlWelcomeEmailTemplates = "pm-21741-mjml-welcome-email"; public const string OrganizationConfirmationEmail = "pm-28402-update-confirmed-to-org-email-template"; diff --git a/src/Core/MailTemplates/Handlebars/Auth/SendAccessEmailOtpEmail.html.hbs b/src/Core/MailTemplates/Handlebars/Auth/SendAccessEmailOtpEmail.html.hbs index 5bf1f24218..7d30fdcbe4 100644 --- a/src/Core/MailTemplates/Handlebars/Auth/SendAccessEmailOtpEmail.html.hbs +++ b/src/Core/MailTemplates/Handlebars/Auth/SendAccessEmailOtpEmail.html.hbs @@ -1,28 +1,691 @@ -{{#>FullHtmlLayout}} - - - - - - - - - - - - - -
- Verify your email to access this Bitwarden Send. -
-
- Your verification code is: {{Token}} -
-
- This code can only be used once and expires in 5 minutes. After that you'll need to verify your email again. -
-
-
- {{TheDate}} at {{TheTime}} {{TimeZone}} -
-{{/FullHtmlLayout}} \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + + + + + +
+ + + + + + + + +
+ + + + + +
+ + + + + + + +
+ + +
+ + + + + + + + + + + + + +
+ + + + + + + +
+ + + +
+ +
+ +

+ Verify your email to access this Bitwarden Send +

+ +
+ +
+ + + +
+ + + + + + + + + +
+ + + + + + + +
+ + + +
+ +
+ +
+ + +
+ +
+ + + + + +
+ + +
+ +
+ + + + + + + + + +
+ + + + + + + +
+ + + +
+ + + + + + + +
+ + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ +
Your verification code is:
+ +
+ +
{{Token}}
+ +
+ +
+ +
+ +
This code 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. +

+ +
+ +
+ +
+ + +
+ +
+ + + +
+ +
+ + + + + + + + + +
+ + + + + + + +
+ + + +
+ + + + + + + +
+ + +
+ + + + + + + + + +
+ +

+ Learn more about Bitwarden +

+ Find user guides, product documentation, and videos on the + Bitwarden Help Center.
+ +
+ +
+ + + +
+ + + + + + + + + +
+ +
+ + +
+ +
+ + + +
+ +
+ + + + + + + + + +
+ + + + + + + +
+ + +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + + + +
+ + + +
+
+ + + + + + + + + + +
+ + + + + + +
+ + + +
+
+ + + + + + + + + + +
+ + + + + + +
+ + + +
+
+ + + + + + + + + + +
+ + + + + + +
+ + + +
+
+ + + + + + + + + + +
+ + + + + + +
+ + + +
+
+ + + + + + + + + + +
+ + + + + + +
+ + + +
+
+ + + + + + + + + + +
+ + + + + + +
+ + + +
+
+ + + +
+ +

+ © 2025 Bitwarden Inc. 1 N. Calle Cesar Chavez, Suite 102, Santa + Barbara, CA, USA +

+

+ Always confirm you are on a trusted Bitwarden domain before logging + in:
+ bitwarden.com | + Learn why we include this +

+ +
+ +
+ + +
+ +
+ + + + + +
+ + + + \ No newline at end of file diff --git a/src/Core/MailTemplates/Handlebars/Auth/SendAccessEmailOtpEmail.text.hbs b/src/Core/MailTemplates/Handlebars/Auth/SendAccessEmailOtpEmail.text.hbs index f83008c30b..7c9c1db527 100644 --- a/src/Core/MailTemplates/Handlebars/Auth/SendAccessEmailOtpEmail.text.hbs +++ b/src/Core/MailTemplates/Handlebars/Auth/SendAccessEmailOtpEmail.text.hbs @@ -3,7 +3,7 @@ Verify your email to access this Bitwarden Send. Your verification code is: {{Token}} -This code can only be used once and expires in 5 minutes. After that you'll need to verify your email again. +This code can only be used once and expires in {{Expiry}} minutes. After that you'll need to verify your email again. -Date : {{TheDate}} at {{TheTime}} {{TimeZone}} -{{/BasicTextLayout}} \ No newline at end of file +Bitwarden Send transmits sensitive, temporary information to others easily and securely. Learn more about Bitwarden Send or sign up to try it today. +{{/BasicTextLayout}} diff --git a/src/Core/MailTemplates/Handlebars/Auth/SendAccessEmailOtpEmailv2.html.hbs b/src/Core/MailTemplates/Handlebars/Auth/SendAccessEmailOtpEmailv2.html.hbs deleted file mode 100644 index 7d30fdcbe4..0000000000 --- a/src/Core/MailTemplates/Handlebars/Auth/SendAccessEmailOtpEmailv2.html.hbs +++ /dev/null @@ -1,691 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - - - - - -
- - - - - - - - -
- - - - - -
- - - - - - - -
- - -
- - - - - - - - - - - - - -
- - - - - - - -
- - - -
- -
- -

- Verify your email to access this Bitwarden Send -

- -
- -
- - - -
- - - - - - - - - -
- - - - - - - -
- - - -
- -
- -
- - -
- -
- - - - - -
- - -
- -
- - - - - - - - - -
- - - - - - - -
- - - -
- - - - - - - -
- - -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- -
Your verification code is:
- -
- -
{{Token}}
- -
- -
- -
- -
This code 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. -

- -
- -
- -
- - -
- -
- - - -
- -
- - - - - - - - - -
- - - - - - - -
- - - -
- - - - - - - -
- - -
- - - - - - - - - -
- -

- Learn more about Bitwarden -

- Find user guides, product documentation, and videos on the - Bitwarden Help Center.
- -
- -
- - - -
- - - - - - - - - -
- -
- - -
- -
- - - -
- -
- - - - - - - - - -
- - - - - - - -
- - -
- - - - - - - - - - - - - -
- - - - - - - - - - - - -
- - - - - - -
- - - -
-
- - - - - - - - - - -
- - - - - - -
- - - -
-
- - - - - - - - - - -
- - - - - - -
- - - -
-
- - - - - - - - - - -
- - - - - - -
- - - -
-
- - - - - - - - - - -
- - - - - - -
- - - -
-
- - - - - - - - - - -
- - - - - - -
- - - -
-
- - - - - - - - - - -
- - - - - - -
- - - -
-
- - - -
- -

- © 2025 Bitwarden Inc. 1 N. Calle Cesar Chavez, Suite 102, Santa - Barbara, CA, USA -

-

- Always confirm you are on a trusted Bitwarden domain before logging - in:
- bitwarden.com | - Learn why we include this -

- -
- -
- - -
- -
- - - - - -
- - - - \ No newline at end of file diff --git a/src/Core/MailTemplates/Handlebars/Auth/SendAccessEmailOtpEmailv2.text.hbs b/src/Core/MailTemplates/Handlebars/Auth/SendAccessEmailOtpEmailv2.text.hbs deleted file mode 100644 index 7c9c1db527..0000000000 --- a/src/Core/MailTemplates/Handlebars/Auth/SendAccessEmailOtpEmailv2.text.hbs +++ /dev/null @@ -1,9 +0,0 @@ -{{#>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}} diff --git a/src/Core/Platform/Mail/HandlebarsMailService.cs b/src/Core/Platform/Mail/HandlebarsMailService.cs index e92fa34daa..910285244d 100644 --- a/src/Core/Platform/Mail/HandlebarsMailService.cs +++ b/src/Core/Platform/Mail/HandlebarsMailService.cs @@ -209,26 +209,6 @@ public class HandlebarsMailService : IMailService } public async Task SendSendEmailOtpEmailAsync(string email, string token, string subject) - { - var message = CreateDefaultMessage(subject, email); - var requestDateTime = DateTime.UtcNow; - var model = new DefaultEmailOtpViewModel - { - Token = token, - TheDate = requestDateTime.ToLongDateString(), - TheTime = requestDateTime.ToShortTimeString(), - TimeZone = _utcTimeZoneDisplay, - WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash, - SiteName = _globalSettings.SiteName, - }; - await AddMessageContentAsync(message, "Auth.SendAccessEmailOtpEmail", model); - message.MetaData.Add("SendGridBypassListManagement", true); - // TODO - PM-25380 change to string constant - message.Category = "SendEmailOtp"; - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendSendEmailOtpEmailv2Async(string email, string token, string subject) { var message = CreateDefaultMessage(subject, email); var requestDateTime = DateTime.UtcNow; @@ -242,7 +222,7 @@ public class HandlebarsMailService : IMailService WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash, SiteName = _globalSettings.SiteName, }; - await AddMessageContentAsync(message, "Auth.SendAccessEmailOtpEmailv2", model); + await AddMessageContentAsync(message, "Auth.SendAccessEmailOtpEmail", model); message.MetaData.Add("SendGridBypassListManagement", true); // TODO - PM-25380 change to string constant message.Category = "SendEmailOtp"; diff --git a/src/Core/Platform/Mail/IMailService.cs b/src/Core/Platform/Mail/IMailService.cs index e21e1a010f..e07e4bad29 100644 --- a/src/Core/Platform/Mail/IMailService.cs +++ b/src/Core/Platform/Mail/IMailService.cs @@ -51,17 +51,15 @@ public interface IMailService Task SendChangeEmailAlreadyExistsEmailAsync(string fromEmail, string toEmail); Task SendChangeEmailEmailAsync(string newEmailAddress, string token); Task SendTwoFactorEmailAsync(string email, string accountEmail, string token, string deviceIp, string deviceType, TwoFactorEmailPurpose purpose); - Task SendSendEmailOtpEmailAsync(string email, string token, string subject); /// - /// has a default expiry of 5 minutes so we set the expiry to that value int he view model. + /// has a default expiry of 5 minutes so we set the expiry to that value in the view model. /// Sends OTP code token to the specified email address. - /// will replace when MJML templates are fully accepted. /// /// Email address to send the OTP to /// Otp code token - /// subject line of the email + /// Subject line of the email /// Task - Task SendSendEmailOtpEmailv2Async(string email, string token, string subject); + Task SendSendEmailOtpEmailAsync(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); diff --git a/src/Core/Platform/Mail/NoopMailService.cs b/src/Core/Platform/Mail/NoopMailService.cs index 7de48e4619..0064058afb 100644 --- a/src/Core/Platform/Mail/NoopMailService.cs +++ b/src/Core/Platform/Mail/NoopMailService.cs @@ -99,11 +99,6 @@ public class NoopMailService : IMailService return Task.FromResult(0); } - public Task SendSendEmailOtpEmailv2Async(string email, string token, string subject) - { - return Task.FromResult(0); - } - public Task SendFailedTwoFactorAttemptEmailAsync(string email, TwoFactorProviderType failedType, DateTime utcNow, string ip) { return Task.FromResult(0); diff --git a/src/Identity/IdentityServer/RequestValidators/SendAccess/SendEmailOtpRequestValidator.cs b/src/Identity/IdentityServer/RequestValidators/SendAccess/SendEmailOtpRequestValidator.cs index f20fdb6f07..bd2b4f91b4 100644 --- a/src/Identity/IdentityServer/RequestValidators/SendAccess/SendEmailOtpRequestValidator.cs +++ b/src/Identity/IdentityServer/RequestValidators/SendAccess/SendEmailOtpRequestValidator.cs @@ -1,7 +1,6 @@ using System.Security.Claims; using System.Security.Cryptography; using System.Text; -using Bit.Core; using Bit.Core.Auth.Identity; using Bit.Core.Auth.Identity.TokenProviders; using Bit.Core.Services; @@ -13,7 +12,6 @@ using Duende.IdentityServer.Validation; namespace Bit.Identity.IdentityServer.RequestValidators.SendAccess; public class SendEmailOtpRequestValidator( - IFeatureService featureService, IOtpTokenProvider otpTokenProvider, IMailService mailService) : ISendAuthenticationMethodValidator { @@ -66,20 +64,12 @@ public class SendEmailOtpRequestValidator( { return BuildErrorResult(SendAccessConstants.EmailOtpValidatorResults.OtpGenerationFailed); } - if (featureService.IsEnabled(FeatureFlagKeys.MJMLBasedEmailTemplates)) - { - await mailService.SendSendEmailOtpEmailv2Async( - email, - token, - string.Format(SendAccessConstants.OtpEmail.Subject, token)); - } - else - { - await mailService.SendSendEmailOtpEmailAsync( - email, - token, - string.Format(SendAccessConstants.OtpEmail.Subject, token)); - } + + await mailService.SendSendEmailOtpEmailAsync( + email, + token, + string.Format(SendAccessConstants.OtpEmail.Subject, token)); + return BuildErrorResult(SendAccessConstants.EmailOtpValidatorResults.EmailOtpSent); } diff --git a/test/Billing.Test/Services/SubscriptionUpdatedHandlerTests.cs b/test/Billing.Test/Services/SubscriptionUpdatedHandlerTests.cs index 2259d846b7..0e1ce8e1f0 100644 --- a/test/Billing.Test/Services/SubscriptionUpdatedHandlerTests.cs +++ b/test/Billing.Test/Services/SubscriptionUpdatedHandlerTests.cs @@ -712,15 +712,15 @@ public class SubscriptionUpdatedHandlerTests Data = [ new SubscriptionItem - { - CurrentPeriodEnd = DateTime.UtcNow.AddDays(10), - Plan = new Plan { Id = "2023-enterprise-org-seat-annually" } - }, - new SubscriptionItem - { - CurrentPeriodEnd = DateTime.UtcNow.AddDays(10), - Plan = new Plan { Id = "secrets-manager-enterprise-seat-annually" } - } + { + CurrentPeriodEnd = DateTime.UtcNow.AddDays(10), + Plan = new Plan { Id = "2023-enterprise-org-seat-annually" } + }, + new SubscriptionItem + { + CurrentPeriodEnd = DateTime.UtcNow.AddDays(10), + Plan = new Plan { Id = "secrets-manager-enterprise-seat-annually" } + } ] }, Customer = new Customer @@ -760,7 +760,7 @@ public class SubscriptionUpdatedHandlerTests Data = [ new SubscriptionItem { Plan = new Stripe.Plan { Id = "secrets-manager-teams-seat-annually" } }, - ] + ] } }) } diff --git a/test/Core.Test/Services/HandlebarsMailServiceTests.cs b/test/Core.Test/Services/HandlebarsMailServiceTests.cs index b98c4580f5..4ff0868c7e 100644 --- a/test/Core.Test/Services/HandlebarsMailServiceTests.cs +++ b/test/Core.Test/Services/HandlebarsMailServiceTests.cs @@ -254,21 +254,6 @@ public class HandlebarsMailServiceTests } } - [Fact] - public async Task SendSendEmailOtpEmailAsync_SendsEmail() - { - // Arrange - var email = "test@example.com"; - var token = "aToken"; - var subject = string.Format("Your Bitwarden Send verification code is {0}", token); - - // Act - await _sut.SendSendEmailOtpEmailAsync(email, token, subject); - - // Assert - await _mailDeliveryService.Received(1).SendEmailAsync(Arg.Any()); - } - [Fact] public async Task SendIndividualUserWelcomeEmailAsync_SendsCorrectEmail() { diff --git a/test/Identity.Test/IdentityServer/SendAccess/SendEmailOtpRequestValidatorTests.cs b/test/Identity.Test/IdentityServer/SendAccess/SendEmailOtpRequestValidatorTests.cs index 1815b9207d..d2c7051f69 100644 --- a/test/Identity.Test/IdentityServer/SendAccess/SendEmailOtpRequestValidatorTests.cs +++ b/test/Identity.Test/IdentityServer/SendAccess/SendEmailOtpRequestValidatorTests.cs @@ -270,10 +270,8 @@ public class SendEmailOtpRequestValidatorTests // Arrange var otpTokenProvider = Substitute.For>(); var mailService = Substitute.For(); - var featureService = Substitute.For(); - // Act - var validator = new SendEmailOtpRequestValidator(featureService, otpTokenProvider, mailService); + var validator = new SendEmailOtpRequestValidator(otpTokenProvider, mailService); // Assert Assert.NotNull(validator);