diff --git a/src/Core/MailTemplates/Handlebars/RecoverTwoFactor.html.hbs b/src/Core/MailTemplates/Handlebars/RecoverTwoFactor.html.hbs
new file mode 100644
index 0000000000..b2bff8d579
--- /dev/null
+++ b/src/Core/MailTemplates/Handlebars/RecoverTwoFactor.html.hbs
@@ -0,0 +1,20 @@
+{{#>FullHtmlLayout}}
+
+
+
+ Your Bitwarden account Two Factor was just reset.
+ |
+
+
+
+ Date: {{TheDate}} at {{TheTime}} {{TimeZone}}
+ IP Address: {{IpAddress}}
+ |
+
+
+
+ If this was not you, you should immediately log in and secure your account.
+ |
+
+
+{{/FullHtmlLayout}}
diff --git a/src/Core/MailTemplates/Handlebars/RecoverTwoFactor.text.hbs b/src/Core/MailTemplates/Handlebars/RecoverTwoFactor.text.hbs
new file mode 100644
index 0000000000..8e6e75400c
--- /dev/null
+++ b/src/Core/MailTemplates/Handlebars/RecoverTwoFactor.text.hbs
@@ -0,0 +1,8 @@
+{{#>BasicTextLayout}}
+Your Bitwarden account Two Factor was just reset.
+
+Date: {{TheDate}} at {{TheTime}} {{TimeZone}}
+IP Address: {{IpAddress}}
+
+If this was not you, you should immediately log in and secure your account.
+{{/BasicTextLayout}}
\ No newline at end of file
diff --git a/src/Core/Models/Mail/RecoverTwoFactorModel.cs b/src/Core/Models/Mail/RecoverTwoFactorModel.cs
new file mode 100644
index 0000000000..f9b8cb5d45
--- /dev/null
+++ b/src/Core/Models/Mail/RecoverTwoFactorModel.cs
@@ -0,0 +1,10 @@
+namespace Bit.Core.Models.Mail
+{
+ public class RecoverTwoFactorModel : BaseMailModel
+ {
+ public string TheDate { get; set; }
+ public string TheTime { get; set; }
+ public string TimeZone { get; set; }
+ public string IpAddress { get; set; }
+ }
+}
diff --git a/src/Core/Services/IMailService.cs b/src/Core/Services/IMailService.cs
index 42196a0c72..c44d86855e 100644
--- a/src/Core/Services/IMailService.cs
+++ b/src/Core/Services/IMailService.cs
@@ -25,5 +25,6 @@ namespace Bit.Core.Services
Task SendPaymentFailedAsync(string email, decimal amount, bool mentionInvoices);
Task SendAddedCreditAsync(string email, decimal amount);
Task SendNewDeviceLoggedInEmail(string email, string deviceType, DateTime timestamp, string ip);
+ Task SendRecoverTwoFactorEmail(string email, DateTime timestamp, string ip);
}
}
diff --git a/src/Core/Services/Implementations/HandlebarsMailService.cs b/src/Core/Services/Implementations/HandlebarsMailService.cs
index 7dc7555296..8c7a223aed 100644
--- a/src/Core/Services/Implementations/HandlebarsMailService.cs
+++ b/src/Core/Services/Implementations/HandlebarsMailService.cs
@@ -283,6 +283,23 @@ namespace Bit.Core.Services
await _mailDeliveryService.SendEmailAsync(message);
}
+ public async Task SendRecoverTwoFactorEmail(string email, DateTime timestamp, string ip)
+ {
+ var message = CreateDefaultMessage($"Recover 2FA From {ip}", email);
+ var model = new RecoverTwoFactorModel
+ {
+ WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
+ SiteName = _globalSettings.SiteName,
+ TheDate = timestamp.ToLongDateString(),
+ TheTime = timestamp.ToShortTimeString(),
+ TimeZone = "UTC",
+ IpAddress = ip
+ };
+ await AddMessageContentAsync(message, "RecoverTwoFactor", model);
+ message.Category = "RecoverTwoFactor";
+ await _mailDeliveryService.SendEmailAsync(message);
+ }
+
private MailMessage CreateDefaultMessage(string subject, string toEmail)
{
return CreateDefaultMessage(subject, new List { toEmail });
diff --git a/src/Core/Services/Implementations/UserService.cs b/src/Core/Services/Implementations/UserService.cs
index 96bb17d966..5e0885a20a 100644
--- a/src/Core/Services/Implementations/UserService.cs
+++ b/src/Core/Services/Implementations/UserService.cs
@@ -674,6 +674,7 @@ namespace Bit.Core.Services
user.TwoFactorProviders = null;
user.TwoFactorRecoveryCode = CoreHelpers.SecureRandomString(32, upper: false, special: false);
await SaveUserAsync(user);
+ await _mailService.SendRecoverTwoFactorEmail(user.Email, DateTime.UtcNow, _currentContext.IpAddress);
await _eventService.LogUserEventAsync(user.Id, EventType.User_Recovered2fa);
return true;
diff --git a/src/Core/Services/NoopImplementations/NoopMailService.cs b/src/Core/Services/NoopImplementations/NoopMailService.cs
index b20379c1de..5fb3f0c118 100644
--- a/src/Core/Services/NoopImplementations/NoopMailService.cs
+++ b/src/Core/Services/NoopImplementations/NoopMailService.cs
@@ -87,5 +87,10 @@ namespace Bit.Core.Services
{
return Task.FromResult(0);
}
+
+ public Task SendRecoverTwoFactorEmail(string email, DateTime timestamp, string ip)
+ {
+ return Task.FromResult(0);
+ }
}
}