diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 1da13f5cd..118c8032e 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -9,17 +9,6 @@ - - - - - - - - - - - @@ -60,7 +49,7 @@ - + @@ -70,7 +59,7 @@ - + diff --git a/src/Core/MailTemplates/Markdown/ChangeEmail.md b/src/Core/MailTemplates/Markdown/ChangeEmail.md deleted file mode 100644 index a9aaaa2b2..000000000 --- a/src/Core/MailTemplates/Markdown/ChangeEmail.md +++ /dev/null @@ -1 +0,0 @@ -To finalize changing your email address enter the following code in the pop-up window: {{token}} diff --git a/src/Core/MailTemplates/Markdown/ChangeEmailAlreadyExists.md b/src/Core/MailTemplates/Markdown/ChangeEmailAlreadyExists.md deleted file mode 100644 index e46ab95e4..000000000 --- a/src/Core/MailTemplates/Markdown/ChangeEmailAlreadyExists.md +++ /dev/null @@ -1,3 +0,0 @@ -A user ({{fromEmail}}) recently tried to change their account to use this email address ({{toEmail}}). An account already exists with this email ({{toEmail}}). - -If you did not try to change an email address, you can safely ignore this email. diff --git a/src/Core/MailTemplates/Markdown/MasterPasswordHint.md b/src/Core/MailTemplates/Markdown/MasterPasswordHint.md deleted file mode 100644 index 271e1d1c3..000000000 --- a/src/Core/MailTemplates/Markdown/MasterPasswordHint.md +++ /dev/null @@ -1,7 +0,0 @@ -You (or someone) recently requested your master password hint. - -Your hint is: "{{hint}}" - -Login: <{{vaultUrl}}> - -If you did not request your master password hint you can safely ignore this email. diff --git a/src/Core/MailTemplates/Markdown/NoMasterPasswordHint.md b/src/Core/MailTemplates/Markdown/NoMasterPasswordHint.md deleted file mode 100644 index 9ae929546..000000000 --- a/src/Core/MailTemplates/Markdown/NoMasterPasswordHint.md +++ /dev/null @@ -1,3 +0,0 @@ -You (or someone) recently requested your master password hint. Unfortunately, your account does not have a master password hint. - -If you did not request your master password hint you can safely ignore this email. diff --git a/src/Core/MailTemplates/Markdown/OrganizationUserAccepted.md b/src/Core/MailTemplates/Markdown/OrganizationUserAccepted.md deleted file mode 100644 index 8c6dd1bde..000000000 --- a/src/Core/MailTemplates/Markdown/OrganizationUserAccepted.md +++ /dev/null @@ -1,5 +0,0 @@ -This email is to notify you that {{userEmail}} has accepted your invitation to join {{organizationName}}. - -To confirm this user, log into the bitwarden web vault, manage your organization "People" and confirm the user. - -If you do not wish to confirm this user, you can also remove them from the organization on the same page. diff --git a/src/Core/MailTemplates/Markdown/OrganizationUserConfirmed.md b/src/Core/MailTemplates/Markdown/OrganizationUserConfirmed.md deleted file mode 100644 index 4ef73877a..000000000 --- a/src/Core/MailTemplates/Markdown/OrganizationUserConfirmed.md +++ /dev/null @@ -1,3 +0,0 @@ -This email is to notify you that you have been confirmed as a user of {{organizationName}}. - -Any collections and logins being shared with you by this organization will now appear in your bitwarden vault. diff --git a/src/Core/MailTemplates/Markdown/OrganizationUserInvited.md b/src/Core/MailTemplates/Markdown/OrganizationUserInvited.md deleted file mode 100644 index 55400c4e3..000000000 --- a/src/Core/MailTemplates/Markdown/OrganizationUserInvited.md +++ /dev/null @@ -1,6 +0,0 @@ -You have been invited to join the {{organizationName}} organization. To accept this invite, click the -following link: - -<{{url}}> - -If you do not wish to join this organization, you can safely ignore this email. diff --git a/src/Core/MailTemplates/Markdown/TwoFactorEmail.md b/src/Core/MailTemplates/Markdown/TwoFactorEmail.md deleted file mode 100644 index 5bd8d81e8..000000000 --- a/src/Core/MailTemplates/Markdown/TwoFactorEmail.md +++ /dev/null @@ -1,3 +0,0 @@ -Your two-step verification code is: {{token}} - -Use this code to complete logging in with bitwarden. diff --git a/src/Core/MailTemplates/Markdown/VerifyDelete.md b/src/Core/MailTemplates/Markdown/VerifyDelete.md deleted file mode 100644 index b77c8a314..000000000 --- a/src/Core/MailTemplates/Markdown/VerifyDelete.md +++ /dev/null @@ -1,3 +0,0 @@ -Click the link below to delete your bitwarden account ({{email}}). If you did not request this email to delete your bitwarden account, you can safely ignore it. - -<{{url}}> diff --git a/src/Core/MailTemplates/Markdown/VerifyEmail.md b/src/Core/MailTemplates/Markdown/VerifyEmail.md deleted file mode 100644 index fa806b4c7..000000000 --- a/src/Core/MailTemplates/Markdown/VerifyEmail.md +++ /dev/null @@ -1,3 +0,0 @@ -Verify this email address for your bitwarden account by clicking the following link. If you did not request this email to verify a bitwarden account, you can safely ignore it. - -<{{url}}> diff --git a/src/Core/MailTemplates/Markdown/Welcome.md b/src/Core/MailTemplates/Markdown/Welcome.md deleted file mode 100644 index 08901e76a..000000000 --- a/src/Core/MailTemplates/Markdown/Welcome.md +++ /dev/null @@ -1,40 +0,0 @@ -Thank you for creating an account with bitwarden. You may now log in with your new account. - -Did you know that bitwarden is free to sync with all of your devices? Download bitwarden today on: - -Mobile -============ - -## iOS - - -## Android - - -Desktop -============ - -## Chrome Extension - - -## Firefox Extension - - -## Opera Extension - - -## Edge Extension - - -Web -============ - -You can also access your vault from any web-enabled device using our web vault at: <{{vaultUrl}}?utm_source=welcome_email&utm_medium=email> - ------------- - -If you have any questions or problems you can email us from our website at: - - -Thank you! -The bitwarden Team diff --git a/src/Core/Services/Implementations/MarkdownMailService.cs b/src/Core/Services/Implementations/MarkdownMailService.cs deleted file mode 100644 index d669b71ba..000000000 --- a/src/Core/Services/Implementations/MarkdownMailService.cs +++ /dev/null @@ -1,210 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Bit.Core.Models.Table; -using Bit.Core.Models.Mail; -using System.IO; -using System.Net; -using System.Reflection; - -namespace Bit.Core.Services -{ - public class MarkdownMailService : IMailService - { - private const string Namespace = "Bit.Core.MailTemplates.Markdown"; - - private readonly GlobalSettings _globalSettings; - private readonly IMailDeliveryService _mailDeliveryService; - - public MarkdownMailService( - GlobalSettings globalSettings, - IMailDeliveryService mailDeliveryService) - { - _globalSettings = globalSettings; - _mailDeliveryService = mailDeliveryService; - } - - public async Task SendVerifyEmailEmailAsync(string email, Guid userId, string token) - { - var model = new Dictionary - { - ["url"] = string.Format("{0}/verify-email?userId={1}&token={2}", - _globalSettings.BaseServiceUri.VaultWithHash, userId, WebUtility.UrlEncode(token)) - }; - - var message = await CreateMessageAsync("Verify Your Email", email, "VerifyEmail", model); - message.MetaData.Add("SendGridBypassListManagement", true); - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendVerifyDeleteEmailAsync(string email, Guid userId, string token) - { - var model = new Dictionary - { - ["url"] = string.Format("{0}/verify-recover-delete?userId={1}&token={2}&email={3}", - _globalSettings.BaseServiceUri.VaultWithHash, - userId, - WebUtility.UrlEncode(token), - WebUtility.UrlEncode(email)), - ["email"] = WebUtility.HtmlEncode(email) - }; - - var message = await CreateMessageAsync("Delete Your Account", email, "VerifyDelete", model); - message.MetaData.Add("SendGridBypassListManagement", true); - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendChangeEmailAlreadyExistsEmailAsync(string fromEmail, string toEmail) - { - var model = new Dictionary - { - ["fromEmail"] = WebUtility.HtmlEncode(fromEmail), - ["toEmail"] = WebUtility.HtmlEncode(toEmail), - }; - - var message = await CreateMessageAsync("Your Email Change", toEmail, "ChangeEmailAlreadyExists", model); - message.MetaData.Add("SendGridBypassListManagement", true); - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendChangeEmailEmailAsync(string newEmailAddress, string token) - { - var model = new Dictionary - { - ["token"] = token - }; - - var message = await CreateMessageAsync("Your Email Change", newEmailAddress, "ChangeEmail", model); - message.MetaData.Add("SendGridBypassListManagement", true); - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendTwoFactorEmailAsync(string email, string token) - { - var model = new Dictionary - { - ["token"] = token - }; - - var message = await CreateMessageAsync("Your Two-step Login Verification Code", email, "TwoFactorEmail", model); - message.MetaData.Add("SendGridBypassListManagement", true); - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendMasterPasswordHintEmailAsync(string email, string hint) - { - var model = new Dictionary - { - ["hint"] = WebUtility.HtmlEncode(hint), - ["vaultUrl"] = _globalSettings.BaseServiceUri.VaultWithHash - }; - - var message = await CreateMessageAsync("Your Master Password Hint", email, "MasterPasswordHint", model); - message.MetaData.Add("SendGridBypassListManagement", true); - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendNoMasterPasswordHintEmailAsync(string email) - { - var message = await CreateMessageAsync("Your Master Password Hint", email, "NoMasterPasswordHint", null); - message.MetaData.Add("SendGridBypassListManagement", true); - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendOrganizationAcceptedEmailAsync(string organizationName, string userEmail, - IEnumerable adminEmails) - { - var model = new Dictionary - { - ["userEmail"] = WebUtility.HtmlEncode(userEmail), - ["organizationName"] = WebUtility.HtmlEncode(organizationName) - }; - - var message = await CreateMessageAsync($"User {userEmail} Has Accepted Invite", adminEmails, - "OrganizationUserAccepted", model); - message.MetaData.Add("SendGridBypassListManagement", true); - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendOrganizationConfirmedEmailAsync(string organizationName, string email) - { - var model = new Dictionary - { - ["organizationName"] = WebUtility.HtmlEncode(organizationName) - }; - - var message = await CreateMessageAsync($"You Have Been Confirmed To {organizationName}", email, - "OrganizationUserConfirmed", model); - message.MetaData.Add("SendGridBypassListManagement", true); - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendOrganizationInviteEmailAsync(string organizationName, OrganizationUser orgUser, string token) - { - var model = new Dictionary - { - ["organizationName"] = WebUtility.HtmlEncode(organizationName), - ["url"] = string.Format("{0}/accept-organization?organizationId={1}&organizationUserId={2}" + - "&email={3}&organizationName={4}&token={5}", - _globalSettings.BaseServiceUri.VaultWithHash, - orgUser.OrganizationId, - orgUser.Id, - WebUtility.UrlEncode(orgUser.Email), - WebUtility.UrlEncode(organizationName), - WebUtility.UrlEncode(token)) - }; - - var message = await CreateMessageAsync($"Join {organizationName}", orgUser.Email, "OrganizationUserInvited", model); - message.MetaData.Add("SendGridBypassListManagement", true); - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendWelcomeEmailAsync(User user) - { - var model = new Dictionary - { - ["vaultUrl"] = _globalSettings.BaseServiceUri.VaultWithHash - }; - - var message = await CreateMessageAsync("Welcome", user.Email, "Welcome", model); - await _mailDeliveryService.SendEmailAsync(message); - } - - private async Task CreateMessageAsync(string subject, string toEmail, string fileName, - Dictionary model) - { - return await CreateMessageAsync(subject, new List { toEmail }, fileName, model); - } - - private async Task CreateMessageAsync(string subject, IEnumerable toEmails, string fileName, - Dictionary model) - { - var message = new MailMessage - { - ToEmails = toEmails, - Subject = subject, - MetaData = new Dictionary() - }; - - var assembly = typeof(MarkdownMailService).GetTypeInfo().Assembly; - using(var s = assembly.GetManifestResourceStream($"{Namespace}.{fileName}.md")) - using(var sr = new StreamReader(s)) - { - var markdown = await sr.ReadToEndAsync(); - - if(model != null) - { - foreach(var prop in model) - { - markdown = markdown.Replace($"{{{{{prop.Key}}}}}", prop.Value); - } - } - - message.HtmlContent = CommonMark.CommonMarkConverter.Convert(markdown); - message.TextContent = markdown; - } - - return message; - } - } -} diff --git a/src/Core/Services/Implementations/SendGridTemplateMailService.cs b/src/Core/Services/Implementations/SendGridTemplateMailService.cs deleted file mode 100644 index 8266d9bd0..000000000 --- a/src/Core/Services/Implementations/SendGridTemplateMailService.cs +++ /dev/null @@ -1,254 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Bit.Core.Models.Table; -using System.Net; -using Bit.Core.Models.Mail; - -namespace Bit.Core.Services -{ - public class SendGridTemplateMailService : IMailService - { - private const string WelcomeTemplateId = "045f8ad5-5547-4fa2-8d3d-6d46e401164d"; - private const string VerifyEmailTemplateId = "TODO"; - private const string VerifyDeleteTemplateId = "TODO"; - private const string ChangeEmailAlreadyExistsTemplateId = "b69d2038-6ad9-4cf6-8f7f-7880921cba43"; - private const string ChangeEmailTemplateId = "ec2c1471-8292-4f17-b6b6-8223d514f86e"; - private const string TwoFactorEmailTemplateId = "264cfe69-5258-4c89-8d90-76b4659de589"; - private const string NoMasterPasswordHintTemplateId = "136eb299-e102-495a-88bd-f96736eea159"; - private const string MasterPasswordHintTemplateId = "be77cfde-95dd-4cb9-b5e0-8286b53885f1"; - private const string OrganizationInviteTemplateId = "1eff5512-e36c-49a8-b9e2-2b215d6bbced"; - private const string OrganizationAcceptedTemplateId = "28f7f741-598e-449c-85fe-601e1cc32ba3"; - private const string OrganizationConfirmedTemplateId = "a8afe2a0-6161-4eb9-b40c-08a7f520ec50"; - - private const string AdministrativeCategoryName = "Administrative"; - private const string MarketingCategoryName = "Marketing"; - - private readonly GlobalSettings _globalSettings; - private readonly IMailDeliveryService _mailDeliveryService; - - public SendGridTemplateMailService( - GlobalSettings globalSettings, - IMailDeliveryService mailDeliveryService) - { - _globalSettings = globalSettings; - _mailDeliveryService = mailDeliveryService; - } - - public async Task SendWelcomeEmailAsync(User user) - { - var message = CreateDefaultMessage( - "Welcome", - user.Email, - WelcomeTemplateId); - - AddCategories(message, new List { AdministrativeCategoryName, "Welcome" }); - - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendVerifyEmailEmailAsync(string email, Guid userId, string token) - { - var message = CreateDefaultMessage( - "Verify Your Email", - email, - VerifyEmailTemplateId); - - AddSubstitution(message, "{{token}}", WebUtility.UrlEncode(token)); - AddSubstitution(message, "{{userId}}", userId.ToString()); - AddCategories(message, new List { AdministrativeCategoryName, "Verify Email" }); - message.MetaData.Add("SendGridBypassListManagement", true); - - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendVerifyDeleteEmailAsync(string email, Guid userId, string token) - { - var message = CreateDefaultMessage( - "Delete Your Account", - email, - VerifyDeleteTemplateId); - - AddSubstitution(message, "{{token}}", WebUtility.UrlEncode(token)); - AddSubstitution(message, "{{email}}", email); - AddSubstitution(message, "{{emailUrlEncoded}}", WebUtility.UrlEncode(email)); - AddSubstitution(message, "{{userId}}", userId.ToString()); - AddCategories(message, new List { AdministrativeCategoryName, "Verify Delete" }); - message.MetaData.Add("SendGridBypassListManagement", true); - - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendChangeEmailAlreadyExistsEmailAsync(string fromEmail, string toEmail) - { - var message = CreateDefaultMessage( - "Your Email Change", - toEmail, - ChangeEmailAlreadyExistsTemplateId); - - AddSubstitution(message, "{{fromEmail}}", fromEmail); - AddSubstitution(message, "{{toEmail}}", toEmail); - AddCategories(message, new List { AdministrativeCategoryName, "Change Email Already Exists" }); - - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendChangeEmailEmailAsync(string newEmailAddress, string token) - { - var message = CreateDefaultMessage( - "Your Email Change", - newEmailAddress, - ChangeEmailTemplateId); - - AddSubstitution(message, "{{token}}", Uri.EscapeDataString(token)); - AddCategories(message, new List { AdministrativeCategoryName, "Change Email" }); - message.MetaData.Add("SendGridBypassListManagement", true); - - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendTwoFactorEmailAsync(string email, string token) - { - var message = CreateDefaultMessage( - "Your Two-step Login Verification Code", - email, - TwoFactorEmailTemplateId); - - AddSubstitution(message, "{{token}}", Uri.EscapeDataString(token)); - AddCategories(message, new List { AdministrativeCategoryName, "Two Factor Email" }); - message.MetaData.Add("SendGridBypassListManagement", true); - - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendNoMasterPasswordHintEmailAsync(string email) - { - var message = CreateDefaultMessage( - "Your Master Password Hint", - email, - NoMasterPasswordHintTemplateId); - AddCategories(message, new List { AdministrativeCategoryName, "No Master Password Hint" }); - - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendMasterPasswordHintEmailAsync(string email, string hint) - { - var message = CreateDefaultMessage( - "Your Master Password Hint", - email, - MasterPasswordHintTemplateId); - - message.Subject = "Your Master Password Hint"; - AddSubstitution(message, "{{hint}}", hint); - AddCategories(message, new List { AdministrativeCategoryName, "Master Password Hint" }); - - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendOrganizationInviteEmailAsync(string organizationName, OrganizationUser orgUser, string token) - { - var message = CreateDefaultMessage( - $"Join {organizationName}", - orgUser.Email, - OrganizationInviteTemplateId); - - AddSubstitution(message, "{{organizationName}}", organizationName); - AddSubstitution(message, "{{organizationId}}", orgUser.OrganizationId.ToString()); - AddSubstitution(message, "{{organizationUserId}}", orgUser.Id.ToString()); - AddSubstitution(message, "{{token}}", token); - AddSubstitution(message, "{{email}}", WebUtility.UrlEncode(orgUser.Email)); - AddSubstitution(message, "{{organizationNameUrlEncoded}}", WebUtility.UrlEncode(organizationName)); - AddCategories(message, new List { AdministrativeCategoryName, "Organization User Invite" }); - - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendOrganizationAcceptedEmailAsync(string organizationName, string userEmail, - IEnumerable adminEmails) - { - var message = CreateDefaultMessage( - $"User {userEmail} Has Accepted Invite", - adminEmails, - OrganizationAcceptedTemplateId); - - AddSubstitution(message, "{{userEmail}}", userEmail); - AddSubstitution(message, "{{organizationName}}", organizationName); - AddCategories(message, new List { AdministrativeCategoryName, "Organization User Accepted" }); - - await _mailDeliveryService.SendEmailAsync(message); - } - - public async Task SendOrganizationConfirmedEmailAsync(string organizationName, string email) - { - var message = CreateDefaultMessage( - $"You Have Been Confirmed To {organizationName}", - email, - OrganizationConfirmedTemplateId); - - AddSubstitution(message, "{{organizationName}}", organizationName); - AddCategories(message, new List { AdministrativeCategoryName, "Organization User Confirmed" }); - - await _mailDeliveryService.SendEmailAsync(message); - } - - private MailMessage CreateDefaultMessage(string subject, string toEmail, string templateId) - { - return CreateDefaultMessage(subject, new List { toEmail }, templateId); - } - - private MailMessage CreateDefaultMessage(string subject, IEnumerable toEmails, string templateId) - { - var message = new MailMessage - { - HtmlContent = " ", - TextContent = " ", - MetaData = new Dictionary(), - ToEmails = toEmails, - Subject = subject - }; - - if(!string.IsNullOrWhiteSpace(templateId)) - { - message.MetaData.Add("SendGridTemplateId", templateId); - } - - AddSubstitution(message, "{{siteName}}", _globalSettings.SiteName); - AddSubstitution(message, "{{baseVaultUri}}", _globalSettings.BaseServiceUri.VaultWithHash); - - return message; - } - - private void AddSubstitution(MailMessage message, string key, string value) - { - Dictionary dict; - if(!message.MetaData.ContainsKey("SendGridSubstitutions")) - { - dict = new Dictionary(); - } - else - { - dict = message.MetaData["SendGridSubstitutions"] as Dictionary; - } - - dict.Add(key, value); - message.MetaData["SendGridSubstitutions"] = dict; - } - - private void AddCategories(MailMessage message, List categories) - { - List cats; - if(!message.MetaData.ContainsKey("SendGridCategories")) - { - cats = categories; - } - else - { - cats = message.MetaData["SendGridCategories"] as List; - cats.AddRange(categories); - } - - message.MetaData["SendGridCategories"] = cats; - } - } -} diff --git a/src/Core/Utilities/ServiceCollectionExtensions.cs b/src/Core/Utilities/ServiceCollectionExtensions.cs index e2cf4a707..55d673e14 100644 --- a/src/Core/Utilities/ServiceCollectionExtensions.cs +++ b/src/Core/Utilities/ServiceCollectionExtensions.cs @@ -56,15 +56,7 @@ namespace Bit.Core.Utilities public static void AddDefaultServices(this IServiceCollection services, GlobalSettings globalSettings) { - if(globalSettings.SelfHosted) - { - services.AddSingleton(); - } - else - { - services.AddSingleton(); - } - + services.AddSingleton(); services.AddSingleton(); if(CoreHelpers.SettingHasValue(globalSettings.Mail.SendGridApiKey))