-
-Thank you!
-The Bitwarden Team
diff --git a/src/Core/MailTemplates/Razor/ChangeEmail.cshtml b/src/Core/MailTemplates/Razor/ChangeEmail.cshtml
deleted file mode 100644
index 30ee0fe3ca..0000000000
--- a/src/Core/MailTemplates/Razor/ChangeEmail.cshtml
+++ /dev/null
@@ -1,7 +0,0 @@
-@model Bit.Core.Models.Mail.EmailTokenViewModel
-@{
- Layout = "_BasicMailLayout";
-}
-
- To finalize changing your email address enter the following code in the pop-up window: @Model.Token
-
diff --git a/src/Core/MailTemplates/Razor/ChangeEmail.text.cshtml b/src/Core/MailTemplates/Razor/ChangeEmail.text.cshtml
deleted file mode 100644
index 78443a46bd..0000000000
--- a/src/Core/MailTemplates/Razor/ChangeEmail.text.cshtml
+++ /dev/null
@@ -1,5 +0,0 @@
-@model Bit.Core.Models.Mail.EmailTokenViewModel
-@{
- Layout = "_BasicMailLayout.text";
-}
-To finalize changing your email address enter the following code in the pop-up window: @Raw(Model.Token)
diff --git a/src/Core/MailTemplates/Razor/ChangeEmailAlreadyExists.cshtml b/src/Core/MailTemplates/Razor/ChangeEmailAlreadyExists.cshtml
deleted file mode 100644
index fd0ec2e08a..0000000000
--- a/src/Core/MailTemplates/Razor/ChangeEmailAlreadyExists.cshtml
+++ /dev/null
@@ -1,11 +0,0 @@
-@model Bit.Core.Models.Mail.ChangeEmailExistsViewModel
-@{
- Layout = "_BasicMailLayout";
-}
-
- A user (@Model.FromEmail) recently tried to change their account to use this
- email address (@Model.ToEmail). An account already exists with this email (@Model.ToEmail).
-
-
- If you did not try to change an email address, you can safely ignore this email.
-
\ No newline at end of file
diff --git a/src/Core/MailTemplates/Razor/ChangeEmailAlreadyExists.text.cshtml b/src/Core/MailTemplates/Razor/ChangeEmailAlreadyExists.text.cshtml
deleted file mode 100644
index 19b3c435c6..0000000000
--- a/src/Core/MailTemplates/Razor/ChangeEmailAlreadyExists.text.cshtml
+++ /dev/null
@@ -1,7 +0,0 @@
-@model Bit.Core.Models.Mail.ChangeEmailExistsViewModel
-@{
- Layout = "_BasicMailLayout.text";
-}
-A user (@Raw(Model.FromEmail)) recently tried to change their account to use this email address (@Raw(Model.ToEmail)). An account already exists with this email (@Raw(Model.ToEmail)).
-
-If you did not try to change an email address, you can safely ignore this email.
diff --git a/src/Core/MailTemplates/Razor/InvoiceUpcoming.cshtml b/src/Core/MailTemplates/Razor/InvoiceUpcoming.cshtml
deleted file mode 100644
index 7872553dea..0000000000
--- a/src/Core/MailTemplates/Razor/InvoiceUpcoming.cshtml
+++ /dev/null
@@ -1,35 +0,0 @@
-@model Bit.Core.Models.Mail.InvoiceUpcomingViewModel
-@{
- Layout = "_BasicMailLayout";
-}
-
- This is a reminder that your Bitwarden subscription is due for renewal soon.
- Your payment method on file will be charged for @Model.AmountDue.ToString("C") on
- @Model.DueDate.ToString("MMM dd, yyyy").
-
-
- Summary Of Charges
- @foreach(var item in Model.Items)
- {
- @:- @item
- }
-
-
-
- To avoid any interruption in service, please ensure that your payment method
- on file is up to date and can be charged for the above amount. You can manage your
- subscription and payment method by logging into the web vault at
- @Model.WebVaultUrl. Once logged in,
- navigate to the Billing page for your account.
-
-
-@if(Model.MentionInvoices)
-{
-
- Invoices for your payments can also be downloaded from Billing page for your account.
-
-}
-
- If you have any questions or problems, please feel free to email us at
- hello@bitwarden.com.
-
diff --git a/src/Core/MailTemplates/Razor/InvoiceUpcoming.text.cshtml b/src/Core/MailTemplates/Razor/InvoiceUpcoming.text.cshtml
deleted file mode 100644
index e092f66c11..0000000000
--- a/src/Core/MailTemplates/Razor/InvoiceUpcoming.text.cshtml
+++ /dev/null
@@ -1,27 +0,0 @@
-@model Bit.Core.Models.Mail.InvoiceUpcomingViewModel
-@{
- Layout = "_BasicMailLayout.text";
-}
-This is a reminder that your Bitwarden subscription is due for renewal soon.
-Your payment method on file will be charged for @Model.AmountDue.ToString("C") on @Model.DueDate.ToString("MMM dd, yyyy").
-
-Summary Of Charges
-------------------
-@foreach(var item in Model.Items)
-{
-@:- @item
-}
-
-To avoid any interruption in service, please ensure that your payment method
-on file is up to date and can be charged for the above amount. You can manage your
-subscription and payment method by logging into the web vault at <@Model.WebVaultUrl>.
-Once logged in, navigate to the Billing page for your account.
-@if(Model.MentionInvoices)
-{
-@:
-@: Invoices for your payments can also be downloaded from Billing page for your
-@: account.
-}
-
-If you have any questions or problems, please feel free to email us at
-hello@bitwarden.com.
diff --git a/src/Core/MailTemplates/Razor/MasterPasswordHint.cshtml b/src/Core/MailTemplates/Razor/MasterPasswordHint.cshtml
deleted file mode 100644
index f7a6c041b7..0000000000
--- a/src/Core/MailTemplates/Razor/MasterPasswordHint.cshtml
+++ /dev/null
@@ -1,8 +0,0 @@
-@model Bit.Core.Models.Mail.MasterPasswordHintViewModel
-@{
- Layout = "_BasicMailLayout";
-}
-You (or someone) recently requested your master password hint.
-Your hint is: "@Model.Hint"
-Login: @Model.WebVaultUrl
-If you did not request your master password hint you can safely ignore this email.
diff --git a/src/Core/MailTemplates/Razor/MasterPasswordHint.text.cshtml b/src/Core/MailTemplates/Razor/MasterPasswordHint.text.cshtml
deleted file mode 100644
index 54b8698ec1..0000000000
--- a/src/Core/MailTemplates/Razor/MasterPasswordHint.text.cshtml
+++ /dev/null
@@ -1,10 +0,0 @@
-@model Bit.Core.Models.Mail.MasterPasswordHintViewModel
-@{
- Layout = "_BasicMailLayout.text";
-}
-You (or someone) recently requested your master password hint.
-
-Your hint is: "@Raw(Model.Hint)"
-Login: @Raw(@Model.WebVaultUrl)
-
-If you did not request your master password hint you can safely ignore this email.
diff --git a/src/Core/MailTemplates/Razor/NoMasterPasswordHint.cshtml b/src/Core/MailTemplates/Razor/NoMasterPasswordHint.cshtml
deleted file mode 100644
index 965d3ae7ec..0000000000
--- a/src/Core/MailTemplates/Razor/NoMasterPasswordHint.cshtml
+++ /dev/null
@@ -1,9 +0,0 @@
-@model Bit.Core.Models.Mail.BaseMailModel
-@{
- Layout = "_BasicMailLayout";
-}
-
- 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/Razor/NoMasterPasswordHint.text.cshtml b/src/Core/MailTemplates/Razor/NoMasterPasswordHint.text.cshtml
deleted file mode 100644
index e548b44235..0000000000
--- a/src/Core/MailTemplates/Razor/NoMasterPasswordHint.text.cshtml
+++ /dev/null
@@ -1,7 +0,0 @@
-@model Bit.Core.Models.Mail.BaseMailModel
-@{
- Layout = "_BasicMailLayout.text";
-}
-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/Razor/OrganizationUserAccepted.cshtml b/src/Core/MailTemplates/Razor/OrganizationUserAccepted.cshtml
deleted file mode 100644
index fe0ec97c55..0000000000
--- a/src/Core/MailTemplates/Razor/OrganizationUserAccepted.cshtml
+++ /dev/null
@@ -1,7 +0,0 @@
-@model Bit.Core.Models.Mail.OrganizationUserAcceptedViewModel
-@{
- Layout = "_BasicMailLayout";
-}
-This email is to notify you that @Model.UserEmail has accepted your invitation to join @Model.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/Razor/OrganizationUserAccepted.text.cshtml b/src/Core/MailTemplates/Razor/OrganizationUserAccepted.text.cshtml
deleted file mode 100644
index a8953309bb..0000000000
--- a/src/Core/MailTemplates/Razor/OrganizationUserAccepted.text.cshtml
+++ /dev/null
@@ -1,9 +0,0 @@
-@model Bit.Core.Models.Mail.OrganizationUserAcceptedViewModel
-@{
- Layout = "_BasicMailLayout.text";
-}
-This email is to notify you that @Raw(Model.UserEmail) has accepted your invitation to join @Raw(Model.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/Razor/OrganizationUserConfirmed.cshtml b/src/Core/MailTemplates/Razor/OrganizationUserConfirmed.cshtml
deleted file mode 100644
index c07c910c01..0000000000
--- a/src/Core/MailTemplates/Razor/OrganizationUserConfirmed.cshtml
+++ /dev/null
@@ -1,6 +0,0 @@
-@model Bit.Core.Models.Mail.OrganizationUserConfirmedViewModel
-@{
- Layout = "_BasicMailLayout";
-}
-This email is to notify you that you have been confirmed as a user of @(Model.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/Razor/OrganizationUserConfirmed.text.cshtml b/src/Core/MailTemplates/Razor/OrganizationUserConfirmed.text.cshtml
deleted file mode 100644
index 8d40563db3..0000000000
--- a/src/Core/MailTemplates/Razor/OrganizationUserConfirmed.text.cshtml
+++ /dev/null
@@ -1,7 +0,0 @@
-@model Bit.Core.Models.Mail.OrganizationUserConfirmedViewModel
-@{
- Layout = "_BasicMailLayout.text";
-}
-This email is to notify you that you have been confirmed as a user of @Raw(Model.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/Razor/OrganizationUserInvited.cshtml b/src/Core/MailTemplates/Razor/OrganizationUserInvited.cshtml
deleted file mode 100644
index d9a6d7336a..0000000000
--- a/src/Core/MailTemplates/Razor/OrganizationUserInvited.cshtml
+++ /dev/null
@@ -1,13 +0,0 @@
-@model Bit.Core.Models.Mail.OrganizationUserInvitedViewModel
-@{
- Layout = "_BasicMailLayout";
-}
-
- You have been invited to join the @Model.OrganizationName organization.
- To accept this invite, click the following link:
-
-@Model.Url
-
- If you do not wish to join this organization, you can safely ignore
- this email.
-
\ No newline at end of file
diff --git a/src/Core/MailTemplates/Razor/OrganizationUserInvited.text.cshtml b/src/Core/MailTemplates/Razor/OrganizationUserInvited.text.cshtml
deleted file mode 100644
index 16592b00f4..0000000000
--- a/src/Core/MailTemplates/Razor/OrganizationUserInvited.text.cshtml
+++ /dev/null
@@ -1,9 +0,0 @@
-@model Bit.Core.Models.Mail.OrganizationUserInvitedViewModel
-@{
- Layout = "_BasicMailLayout.text";
-}
-You have been invited to join the @Raw(Model.OrganizationName) organization. To accept this invite, click the following link:
-
-@Raw(Model.Url)
-
-If you do not wish to join this organization, you can safely ignore this email.
diff --git a/src/Core/MailTemplates/Razor/PasswordlessSignIn.cshtml b/src/Core/MailTemplates/Razor/PasswordlessSignIn.cshtml
deleted file mode 100644
index 0675fbc0f4..0000000000
--- a/src/Core/MailTemplates/Razor/PasswordlessSignIn.cshtml
+++ /dev/null
@@ -1,11 +0,0 @@
-@model Bit.Core.Models.Mail.PasswordlessSignInModel
-@{
- Layout = "_BasicMailLayout";
-}
-
- Click the following link to log in:
-
-@Model.Url
-
- If you did not request to log in, you can safely ignore this email.
-
\ No newline at end of file
diff --git a/src/Core/MailTemplates/Razor/PasswordlessSignIn.text.cshtml b/src/Core/MailTemplates/Razor/PasswordlessSignIn.text.cshtml
deleted file mode 100644
index b68df45d46..0000000000
--- a/src/Core/MailTemplates/Razor/PasswordlessSignIn.text.cshtml
+++ /dev/null
@@ -1,9 +0,0 @@
-@model Bit.Core.Models.Mail.PasswordlessSignInModel
-@{
- Layout = "_BasicMailLayout.text";
-}
-Click the following link to log in:
-
-@Raw(Model.Url)
-
-If you did not request to log in, you can safely ignore this email.
diff --git a/src/Core/MailTemplates/Razor/TwoFactorEmail.cshtml b/src/Core/MailTemplates/Razor/TwoFactorEmail.cshtml
deleted file mode 100644
index 63ad08e1d6..0000000000
--- a/src/Core/MailTemplates/Razor/TwoFactorEmail.cshtml
+++ /dev/null
@@ -1,10 +0,0 @@
-@model Bit.Core.Models.Mail.EmailTokenViewModel
-@{
- Layout = "_BasicMailLayout";
-}
-
- Your two-step verification code is: @Model.Token
-
-
- Use this code to complete logging in with Bitwarden.
-
\ No newline at end of file
diff --git a/src/Core/MailTemplates/Razor/TwoFactorEmail.text.cshtml b/src/Core/MailTemplates/Razor/TwoFactorEmail.text.cshtml
deleted file mode 100644
index 87d6348225..0000000000
--- a/src/Core/MailTemplates/Razor/TwoFactorEmail.text.cshtml
+++ /dev/null
@@ -1,7 +0,0 @@
-@model Bit.Core.Models.Mail.EmailTokenViewModel
-@{
- Layout = "_BasicMailLayout.text";
-}
-Your two-step verification code is: @Raw(Model.Token)
-
-Use this code to complete logging in with Bitwarden.
diff --git a/src/Core/MailTemplates/Razor/VerifyDelete.cshtml b/src/Core/MailTemplates/Razor/VerifyDelete.cshtml
deleted file mode 100644
index df3ef320c0..0000000000
--- a/src/Core/MailTemplates/Razor/VerifyDelete.cshtml
+++ /dev/null
@@ -1,9 +0,0 @@
-@model Bit.Core.Models.Mail.VerifyDeleteModel
-@{
- Layout = "_BasicMailLayout";
-}
-
- Click the link below to delete your Bitwarden account (@Model.Email).
- If you did not request this email to delete your Bitwarden account, you can safely ignore it.
-
-@Model.Url
diff --git a/src/Core/MailTemplates/Razor/VerifyDelete.text.cshtml b/src/Core/MailTemplates/Razor/VerifyDelete.text.cshtml
deleted file mode 100644
index 0661516a19..0000000000
--- a/src/Core/MailTemplates/Razor/VerifyDelete.text.cshtml
+++ /dev/null
@@ -1,7 +0,0 @@
-@model Bit.Core.Models.Mail.VerifyDeleteModel
-@{
- Layout = "_BasicMailLayout.text";
-}
-Click the link below to delete your Bitwarden account (@Raw(Model.Email)). If you did not request this email to delete your Bitwarden account, you can safely ignore it.
-
-@Raw(Model.Url)
diff --git a/src/Core/MailTemplates/Razor/VerifyEmail.cshtml b/src/Core/MailTemplates/Razor/VerifyEmail.cshtml
deleted file mode 100644
index 6d317ff4d3..0000000000
--- a/src/Core/MailTemplates/Razor/VerifyEmail.cshtml
+++ /dev/null
@@ -1,9 +0,0 @@
-@model Bit.Core.Models.Mail.VerifyEmailModel
-@{
- Layout = "_BasicMailLayout";
-}
-
- 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.
-
-@Model.Url
diff --git a/src/Core/MailTemplates/Razor/VerifyEmail.text.cshtml b/src/Core/MailTemplates/Razor/VerifyEmail.text.cshtml
deleted file mode 100644
index 1d5784e74b..0000000000
--- a/src/Core/MailTemplates/Razor/VerifyEmail.text.cshtml
+++ /dev/null
@@ -1,7 +0,0 @@
-@model Bit.Core.Models.Mail.VerifyEmailModel
-@{
- Layout = "_BasicMailLayout.text";
-}
-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.
-
-@Raw(Model.Url)
diff --git a/src/Core/MailTemplates/Razor/Welcome.cshtml b/src/Core/MailTemplates/Razor/Welcome.cshtml
deleted file mode 100644
index 0320898544..0000000000
--- a/src/Core/MailTemplates/Razor/Welcome.cshtml
+++ /dev/null
@@ -1,101 +0,0 @@
-@model Bit.Core.Models.Mail.BaseMailModel
-@{
- Layout = "_MailLayout";
-}
-
-
-
-
-
-
- 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:
- |
-
-
-
- Desktop
- |
-
-
-
- Access Bitwarden on Windows, macOS, and Linux desktops with our native desktop application.
- |
-
-
-
-
-
-
- |
-
-
-
- Web Browser
- |
-
-
-
- Integrate Bitwarden directly into your favorite browser. Use our browser extensions for a seamless browsing experience.
- |
-
-
-
-
-
-
- |
-
-
-
- Mobile
- |
-
-
-
- Take Bitwarden on the go with our mobile apps for your phone or tablet device.
- |
-
-
-
-
-
-
- |
-
-
-
- Web
- |
-
-
-
- Stuck without any of your devices? Using a friend's computer? You can access your Bitwarden vault from any web enabled device by using the web vault.
- |
-
-
-
- @Raw(Model.WebVaultUrlHostname)
-
-
- |
-
-
-
- If you have any questions or problems you can email us from our website at https://bitwarden.com/contact.
- |
-
-
-
- Thank you!
- The Bitwarden Team
- |
-
-
- |
-
-
diff --git a/src/Core/MailTemplates/Razor/Welcome.text.cshtml b/src/Core/MailTemplates/Razor/Welcome.text.cshtml
deleted file mode 100644
index 63779377f3..0000000000
--- a/src/Core/MailTemplates/Razor/Welcome.text.cshtml
+++ /dev/null
@@ -1,37 +0,0 @@
-@model Bit.Core.Models.Mail.BaseMailModel
-@{
- Layout = "_MailLayout.text";
-}
-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:
-
-Desktop
-============
-
-Access Bitwarden on Windows, macOS, and Linux desktops with our native desktop application.
-https://bitwarden.com/#download
-
-Web Browser
-============
-
-Integrate Bitwarden directly into your favorite browser. Use our browser extensions for a seamless browsing experience.
-https://bitwarden.com/#download-browser
-
-Mobile
-============
-
-Take Bitwarden on the go with our mobile apps for your phone or tablet device.
-https://bitwarden.com/#download-mobile
-
-Web
-============
-
-Stuck without any of your devices? Using a friend's computer? You can access your Bitwarden vault from any web enabled device by using the web vault.
-@Raw(Model.WebVaultUrl)/?utm_source=welcome_email&utm_medium=email
-
-
-If you have any questions or problems you can email us from our website at: https://bitwarden.com/contact/?utm_source=welcome_email&utm_medium=email
-
-Thank you!
-The Bitwarden Team
diff --git a/src/Core/MailTemplates/Razor/_BasicMailLayout.cshtml b/src/Core/MailTemplates/Razor/_BasicMailLayout.cshtml
deleted file mode 100644
index 13ba3a5ebd..0000000000
--- a/src/Core/MailTemplates/Razor/_BasicMailLayout.cshtml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
- @RenderBody()
-
-
diff --git a/src/Core/MailTemplates/Razor/_BasicMailLayout.text.cshtml b/src/Core/MailTemplates/Razor/_BasicMailLayout.text.cshtml
deleted file mode 100644
index d2f231de2f..0000000000
--- a/src/Core/MailTemplates/Razor/_BasicMailLayout.text.cshtml
+++ /dev/null
@@ -1 +0,0 @@
-@RenderBody()
\ No newline at end of file
diff --git a/src/Core/MailTemplates/Razor/_MailLayout.cshtml b/src/Core/MailTemplates/Razor/_MailLayout.cshtml
deleted file mode 100644
index e01aa79bc7..0000000000
--- a/src/Core/MailTemplates/Razor/_MailLayout.cshtml
+++ /dev/null
@@ -1,136 +0,0 @@
-
-
-
-
-
- Bitwarden
-
-
-
-
-
-
-
-
- |
-
-
-
-
-
-
-
- @RenderBody()
-
-
- |
-
-
- |
-
-
-
-
diff --git a/src/Core/MailTemplates/Razor/_MailLayout.text.cshtml b/src/Core/MailTemplates/Razor/_MailLayout.text.cshtml
deleted file mode 100644
index fd4be1dbfa..0000000000
--- a/src/Core/MailTemplates/Razor/_MailLayout.text.cshtml
+++ /dev/null
@@ -1,9 +0,0 @@
-@RenderBody()
-----------------------------
-
-8bit Solutions LLC
-
-- Twitter: https://twitter.com/bitwarden_app
-- Facebook: https://www.facebook.com/bitwarden/
-- Google+: https://plus.google.com/+bitwarden
-- GitHub: https://github.com/bitwarden
\ No newline at end of file
diff --git a/src/Core/Services/Implementations/BackupMailService.cs b/src/Core/Services/Implementations/BackupMailService.cs
deleted file mode 100644
index b5c86ab090..0000000000
--- a/src/Core/Services/Implementations/BackupMailService.cs
+++ /dev/null
@@ -1,201 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Bit.Core.Models.Table;
-using Microsoft.Extensions.Logging;
-
-namespace Bit.Core.Services
-{
- public class BackupMailService : IMailService
- {
- private readonly IMailService _primaryMailService;
- private readonly IMailService _backupMailService;
- private readonly ILogger _logger;
-
- public BackupMailService(
- GlobalSettings globalSettings,
- IMailDeliveryService mailDeliveryService,
- ILogger logger)
- {
- _primaryMailService = new RazorMailService(globalSettings, mailDeliveryService);
- _backupMailService = new MarkdownMailService(globalSettings, mailDeliveryService);
- _logger = logger;
- }
-
- public async Task SendVerifyEmailEmailAsync(string email, Guid userId, string token)
- {
- try
- {
- await _primaryMailService.SendVerifyEmailEmailAsync(email, userId, token);
- }
- catch(Exception e)
- {
- LogError(e);
- await _backupMailService.SendVerifyEmailEmailAsync(email, userId, token);
- }
- }
-
- public async Task SendVerifyDeleteEmailAsync(string email, Guid userId, string token)
- {
- try
- {
- await _primaryMailService.SendVerifyDeleteEmailAsync(email, userId, token);
- }
- catch(Exception e)
- {
- LogError(e);
- await _backupMailService.SendVerifyDeleteEmailAsync(email, userId, token);
- }
- }
-
- public async Task SendChangeEmailAlreadyExistsEmailAsync(string fromEmail, string toEmail)
- {
- try
- {
- await _primaryMailService.SendChangeEmailAlreadyExistsEmailAsync(fromEmail, toEmail);
- }
- catch(Exception e)
- {
- LogError(e);
- await _backupMailService.SendChangeEmailAlreadyExistsEmailAsync(fromEmail, toEmail);
- }
- }
-
- public async Task SendChangeEmailEmailAsync(string newEmailAddress, string token)
- {
- try
- {
- await _primaryMailService.SendChangeEmailEmailAsync(newEmailAddress, token);
- }
- catch(Exception e)
- {
- LogError(e);
- await _backupMailService.SendChangeEmailEmailAsync(newEmailAddress, token);
- }
- }
-
- public async Task SendTwoFactorEmailAsync(string email, string token)
- {
- try
- {
- await _primaryMailService.SendTwoFactorEmailAsync(email, token);
- }
- catch(Exception e)
- {
- LogError(e);
- await _backupMailService.SendTwoFactorEmailAsync(email, token);
- }
- }
-
- public async Task SendMasterPasswordHintEmailAsync(string email, string hint)
- {
- try
- {
- await _primaryMailService.SendMasterPasswordHintEmailAsync(email, hint);
- }
- catch(Exception e)
- {
- LogError(e);
- await _backupMailService.SendMasterPasswordHintEmailAsync(email, hint);
- }
- }
-
- public async Task SendNoMasterPasswordHintEmailAsync(string email)
- {
- try
- {
- await _primaryMailService.SendNoMasterPasswordHintEmailAsync(email);
- }
- catch(Exception e)
- {
- LogError(e);
- await _backupMailService.SendNoMasterPasswordHintEmailAsync(email);
- }
- }
-
- public async Task SendOrganizationAcceptedEmailAsync(string organizationName, string userEmail,
- IEnumerable adminEmails)
- {
- try
- {
- await _primaryMailService.SendOrganizationAcceptedEmailAsync(organizationName, userEmail, adminEmails);
- }
- catch(Exception e)
- {
- LogError(e);
- await _backupMailService.SendOrganizationAcceptedEmailAsync(organizationName, userEmail, adminEmails);
- }
- }
-
- public async Task SendOrganizationConfirmedEmailAsync(string organizationName, string email)
- {
- try
- {
- await _primaryMailService.SendOrganizationConfirmedEmailAsync(organizationName, email);
- }
- catch(Exception e)
- {
- LogError(e);
- await _backupMailService.SendOrganizationConfirmedEmailAsync(organizationName, email);
- }
- }
-
- public async Task SendOrganizationInviteEmailAsync(string organizationName, OrganizationUser orgUser, string token)
- {
- try
- {
- await _primaryMailService.SendOrganizationInviteEmailAsync(organizationName, orgUser, token);
- }
- catch(Exception e)
- {
- LogError(e);
- await _backupMailService.SendOrganizationInviteEmailAsync(organizationName, orgUser, token);
- }
- }
-
- public async Task SendPasswordlessSignInAsync(string returnUrl, string token, string email)
- {
- try
- {
- await _primaryMailService.SendPasswordlessSignInAsync(returnUrl, token, email);
- }
- catch(Exception e)
- {
- LogError(e);
- await _backupMailService.SendPasswordlessSignInAsync(returnUrl, token, email);
- }
- }
-
- public async Task SendWelcomeEmailAsync(User user)
- {
- try
- {
- await _primaryMailService.SendWelcomeEmailAsync(user);
- }
- catch(Exception e)
- {
- LogError(e);
- await _backupMailService.SendWelcomeEmailAsync(user);
- }
- }
-
- public async Task SendInvoiceUpcomingAsync(string email, decimal amount, DateTime dueDate,
- List items, bool mentionInvoices)
- {
- try
- {
- await _primaryMailService.SendInvoiceUpcomingAsync(email, amount, dueDate, items, mentionInvoices);
- }
- catch(Exception e)
- {
- LogError(e);
- await _backupMailService.SendInvoiceUpcomingAsync(email, amount, dueDate, items, mentionInvoices);
- }
- }
-
- private void LogError(Exception e)
- {
- _logger.LogError(e, "Error sending mail with primary service, using backup.");
- }
- }
-}
diff --git a/src/Core/Services/Implementations/MarkdownMailService.cs b/src/Core/Services/Implementations/MarkdownMailService.cs
deleted file mode 100644
index 587b41deb3..0000000000
--- a/src/Core/Services/Implementations/MarkdownMailService.cs
+++ /dev/null
@@ -1,245 +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;
-using Bit.Core.Utilities;
-
-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);
- }
-
- public async Task SendPasswordlessSignInAsync(string returnUrl, string token, string email)
- {
- var url = CoreHelpers.ExtendQuery(new Uri($"{_globalSettings.BaseServiceUri.Admin}/login/confirm"),
- new Dictionary
- {
- ["returnUrl"] = returnUrl,
- ["email"] = email,
- ["token"] = token,
- });
- var model = new Dictionary
- {
- ["url"] = url.ToString()
- };
-
- var message = await CreateMessageAsync("[Admin] Continue Logging In", email, "PasswordlessSignIn", model);
- message.MetaData.Add("SendGridBypassListManagement", true);
- await _mailDeliveryService.SendEmailAsync(message);
- }
-
- public async Task SendInvoiceUpcomingAsync(string email, decimal amount, DateTime dueDate,
- List items, bool mentionInvoices)
- {
- var model = new Dictionary
- {
- ["vaultUrl"] = _globalSettings.BaseServiceUri.VaultWithHash,
- ["dueDate"] = dueDate.ToString("MMM dd, yyyy"),
- ["amountDue"] = amount.ToString("C")
- };
-
- var message = await CreateMessageAsync("Your Subscription Will Renew Soon", email,
- "InvoiceUpcoming", 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/RazorMailService.cs b/src/Core/Services/Implementations/RazorMailService.cs
deleted file mode 100644
index 20fa2d55fb..0000000000
--- a/src/Core/Services/Implementations/RazorMailService.cs
+++ /dev/null
@@ -1,300 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Bit.Core.Models.Table;
-using RazorLight;
-using Bit.Core.Models.Mail;
-using System.IO;
-using System.Net;
-using Bit.Core.Utilities;
-using RazorLight.Razor;
-using System.Linq;
-using System.Reflection;
-
-namespace Bit.Core.Services
-{
- public class RazorMailService : IMailService
- {
- private readonly GlobalSettings _globalSettings;
- private readonly IRazorLightEngine _engine;
- private readonly IMailDeliveryService _mailDeliveryService;
-
- public RazorMailService(
- GlobalSettings globalSettings,
- IMailDeliveryService mailDeliveryService)
- {
- _globalSettings = globalSettings;
- _mailDeliveryService = mailDeliveryService;
-
-
- var factory = new EngineFactory();
- _engine = factory.Create(new CustomEmbeddedRazorProject());
- }
-
- public async Task SendVerifyEmailEmailAsync(string email, Guid userId, string token)
- {
- var message = CreateDefaultMessage("Verify Your Email", email);
- var model = new VerifyEmailModel
- {
- Token = WebUtility.UrlEncode(token),
- UserId = userId,
- WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
- SiteName = _globalSettings.SiteName
- };
- message.HtmlContent = await _engine.CompileRenderAsync("VerifyEmail", model);
- message.TextContent = await _engine.CompileRenderAsync("VerifyEmail.text", model);
- 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);
- var model = new VerifyDeleteModel
- {
- Token = WebUtility.UrlEncode(token),
- UserId = userId,
- WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
- SiteName = _globalSettings.SiteName,
- Email = email,
- EmailEncoded = WebUtility.UrlEncode(email)
- };
- message.HtmlContent = await _engine.CompileRenderAsync("VerifyDelete", model);
- message.TextContent = await _engine.CompileRenderAsync("VerifyDelete.text", model);
- message.MetaData.Add("SendGridBypassListManagement", true);
-
- await _mailDeliveryService.SendEmailAsync(message);
- }
-
- public async Task SendChangeEmailAlreadyExistsEmailAsync(string fromEmail, string toEmail)
- {
- var message = CreateDefaultMessage("Your Email Change", toEmail);
- var model = new ChangeEmailExistsViewModel
- {
- FromEmail = fromEmail,
- ToEmail = toEmail,
- WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
- SiteName = _globalSettings.SiteName
- };
- message.HtmlContent = await _engine.CompileRenderAsync("ChangeEmailAlreadyExists", model);
- message.TextContent = await _engine.CompileRenderAsync("ChangeEmailAlreadyExists.text", model);
- await _mailDeliveryService.SendEmailAsync(message);
- }
-
- public async Task SendChangeEmailEmailAsync(string newEmailAddress, string token)
- {
- var message = CreateDefaultMessage("Your Email Change", newEmailAddress);
- var model = new EmailTokenViewModel
- {
- Token = token,
- WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
- SiteName = _globalSettings.SiteName
- };
- message.HtmlContent = await _engine.CompileRenderAsync("ChangeEmail", model);
- message.TextContent = await _engine.CompileRenderAsync("ChangeEmail.text", model);
- 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);
- var model = new EmailTokenViewModel
- {
- Token = token,
- WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
- SiteName = _globalSettings.SiteName
- };
- message.HtmlContent = await _engine.CompileRenderAsync("TwoFactorEmail", model);
- message.TextContent = await _engine.CompileRenderAsync("TwoFactorEmail.text", model);
- message.MetaData.Add("SendGridBypassListManagement", true);
-
- await _mailDeliveryService.SendEmailAsync(message);
- }
-
- public async Task SendMasterPasswordHintEmailAsync(string email, string hint)
- {
- var message = CreateDefaultMessage("Your Master Password Hint", email);
- var model = new MasterPasswordHintViewModel
- {
- Hint = CoreHelpers.SanitizeForEmail(hint),
- WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
- SiteName = _globalSettings.SiteName
- };
- message.HtmlContent = await _engine.CompileRenderAsync("MasterPasswordHint", model);
- message.TextContent = await _engine.CompileRenderAsync("MasterPasswordHint.text", model);
- await _mailDeliveryService.SendEmailAsync(message);
- }
-
- public async Task SendNoMasterPasswordHintEmailAsync(string email)
- {
- var message = CreateDefaultMessage("Your Master Password Hint", email);
- var model = new BaseMailModel
- {
- WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
- SiteName = _globalSettings.SiteName
- };
- message.HtmlContent = await _engine.CompileRenderAsync("NoMasterPasswordHint", model);
- message.TextContent = await _engine.CompileRenderAsync("NoMasterPasswordHint.text", model);
- await _mailDeliveryService.SendEmailAsync(message);
- }
-
- public async Task SendOrganizationAcceptedEmailAsync(string organizationName, string userEmail,
- IEnumerable adminEmails)
- {
- var message = CreateDefaultMessage($"User {userEmail} Has Accepted Invite", adminEmails);
- var model = new OrganizationUserAcceptedViewModel
- {
- OrganizationName = CoreHelpers.SanitizeForEmail(organizationName),
- UserEmail = userEmail,
- WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
- SiteName = _globalSettings.SiteName
- };
- message.HtmlContent = await _engine.CompileRenderAsync("OrganizationUserAccepted", model);
- message.TextContent = await _engine.CompileRenderAsync("OrganizationUserAccepted.text", model);
- await _mailDeliveryService.SendEmailAsync(message);
- }
-
- public async Task SendOrganizationConfirmedEmailAsync(string organizationName, string email)
- {
- var message = CreateDefaultMessage($"You Have Been Confirmed To {organizationName}", email);
- var model = new OrganizationUserConfirmedViewModel
- {
- OrganizationName = CoreHelpers.SanitizeForEmail(organizationName),
- WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
- SiteName = _globalSettings.SiteName
- };
- message.HtmlContent = await _engine.CompileRenderAsync("OrganizationUserConfirmed", model);
- message.TextContent = await _engine.CompileRenderAsync("OrganizationUserConfirmed.text", model);
- await _mailDeliveryService.SendEmailAsync(message);
- }
-
- public async Task SendOrganizationInviteEmailAsync(string organizationName, OrganizationUser orgUser, string token)
- {
- var message = CreateDefaultMessage($"Join {organizationName}", orgUser.Email);
- var model = new OrganizationUserInvitedViewModel
- {
- OrganizationName = CoreHelpers.SanitizeForEmail(organizationName),
- Email = WebUtility.UrlEncode(orgUser.Email),
- OrganizationId = orgUser.OrganizationId.ToString(),
- OrganizationUserId = orgUser.Id.ToString(),
- Token = WebUtility.UrlEncode(token),
- OrganizationNameUrlEncoded = WebUtility.UrlEncode(organizationName),
- WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
- SiteName = _globalSettings.SiteName
- };
- message.HtmlContent = await _engine.CompileRenderAsync("OrganizationUserInvited", model);
- message.TextContent = await _engine.CompileRenderAsync("OrganizationUserInvited.text", model);
- await _mailDeliveryService.SendEmailAsync(message);
- }
-
- public async Task SendWelcomeEmailAsync(User user)
- {
- var message = CreateDefaultMessage("Welcome", user.Email);
- var model = new BaseMailModel
- {
- WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
- SiteName = _globalSettings.SiteName
- };
- message.HtmlContent = await _engine.CompileRenderAsync("Welcome", model);
- message.TextContent = await _engine.CompileRenderAsync("Welcome.text", model);
- await _mailDeliveryService.SendEmailAsync(message);
- }
-
- public async Task SendPasswordlessSignInAsync(string returnUrl, string token, string email)
- {
- var message = CreateDefaultMessage("[Admin] Continue Logging In", email);
-
- var url = CoreHelpers.ExtendQuery(new Uri($"{_globalSettings.BaseServiceUri.Admin}/login/confirm"),
- new Dictionary
- {
- ["returnUrl"] = returnUrl,
- ["email"] = email,
- ["token"] = token,
- });
- var model = new PasswordlessSignInModel
- {
- Url = url.ToString()
- };
- message.HtmlContent = await _engine.CompileRenderAsync("PasswordlessSignIn", model);
- message.TextContent = await _engine.CompileRenderAsync("PasswordlessSignIn.text", model);
- await _mailDeliveryService.SendEmailAsync(message);
- }
-
- public async Task SendInvoiceUpcomingAsync(string email, decimal amount, DateTime dueDate,
- List items, bool mentionInvoices)
- {
- var message = CreateDefaultMessage("Your Subscription Will Renew Soon", email);
- var model = new InvoiceUpcomingViewModel
- {
- WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
- SiteName = _globalSettings.SiteName,
- AmountDue = amount,
- DueDate = dueDate,
- Items = items,
- MentionInvoices = mentionInvoices
- };
- message.HtmlContent = await _engine.CompileRenderAsync("InvoiceUpcoming", model);
- message.TextContent = await _engine.CompileRenderAsync("InvoiceUpcoming.text", model);
- await _mailDeliveryService.SendEmailAsync(message);
- }
-
- private MailMessage CreateDefaultMessage(string subject, string toEmail)
- {
- return CreateDefaultMessage(subject, new List { toEmail });
- }
-
- private MailMessage CreateDefaultMessage(string subject, IEnumerable toEmails)
- {
- return new MailMessage
- {
- ToEmails = toEmails,
- Subject = subject,
- MetaData = new Dictionary()
- };
- }
-
- public class CustomEmbeddedRazorProject : RazorLightProject
- {
- public override Task GetItemAsync(string templateKey)
- {
- if(string.IsNullOrWhiteSpace(templateKey))
- {
- throw new ArgumentNullException(nameof(templateKey));
- }
-
- var item = new CustomEmbeddedRazorProjectItem(templateKey);
- return Task.FromResult(item as RazorLightProjectItem);
- }
-
- public override Task> GetImportsAsync(string templateKey)
- {
- return Task.FromResult(Enumerable.Empty());
- }
- }
-
- public class CustomEmbeddedRazorProjectItem : RazorLightProjectItem
- {
- private readonly string _fullTemplateKey;
- private readonly Assembly _assembly;
-
- public CustomEmbeddedRazorProjectItem(string key)
- {
- if(string.IsNullOrWhiteSpace(key))
- {
- throw new ArgumentNullException(nameof(key));
- }
-
- Key = key;
- _assembly = GetType().Assembly;
- _fullTemplateKey = $"Bit.Core.MailTemplates.Razor.{key}.cshtml";
- }
-
- public override string Key { get; set; }
- public override bool Exists => _assembly.GetManifestResourceNames().Any(f => f == _fullTemplateKey);
- public override Stream Read() => _assembly.GetManifestResourceStream(_fullTemplateKey);
- }
- }
-}