mirror of
https://github.com/bitwarden/server.git
synced 2025-07-02 00:22:50 -05:00
mail templates for RazorViewMailService
This commit is contained in:
@ -1,132 +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 RazorLight.Templating;
|
||||
using System.IO;
|
||||
|
||||
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 manager = new CustomEmbeddedResourceTemplateManager("Bit.Core.MailTemplates");
|
||||
var core = new EngineCore(manager, EngineConfiguration.Default);
|
||||
var pageFactory = new DefaultPageFactory(core.KeyCompile);
|
||||
var lookup = new DefaultPageLookup(pageFactory);
|
||||
_engine = new RazorLightEngine(core, lookup);
|
||||
}
|
||||
|
||||
public Task SendChangeEmailAlreadyExistsEmailAsync(string fromEmail, string toEmail)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SendChangeEmailEmailAsync(string newEmailAddress, string token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task SendMasterPasswordHintEmailAsync(string email, string hint)
|
||||
{
|
||||
var message = CreateDefaultMessage("Your Master Password Hint", email);
|
||||
var model = new MasterPasswordHintViewModel
|
||||
{
|
||||
Hint = hint
|
||||
};
|
||||
message.HtmlContent = _engine.Parse("MasterPasswordHint", model);
|
||||
message.TextContent = _engine.Parse("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();
|
||||
message.HtmlContent = _engine.Parse("NoMasterPasswordHint", model);
|
||||
message.TextContent = _engine.Parse("NoMasterPasswordHint.text", model);
|
||||
await _mailDeliveryService.SendEmailAsync(message);
|
||||
}
|
||||
|
||||
public Task SendOrganizationAcceptedEmailAsync(string organizationName, string userEmail, IEnumerable<string> adminEmails)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SendOrganizationConfirmedEmailAsync(string organizationName, string email)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SendOrganizationInviteEmailAsync(string organizationName, OrganizationUser orgUser, string token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SendWelcomeEmailAsync(User user)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MailMessage CreateDefaultMessage(string subject, string toEmail)
|
||||
{
|
||||
return CreateDefaultMessage(subject, new List<string> { toEmail });
|
||||
}
|
||||
|
||||
private MailMessage CreateDefaultMessage(string subject, IEnumerable<string> toEmails)
|
||||
{
|
||||
var message = new MailMessage
|
||||
{
|
||||
MetaData = new Dictionary<string, object>(),
|
||||
ToEmails = toEmails,
|
||||
Subject = subject
|
||||
};
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
public class CustomEmbeddedResourceTemplateManager : ITemplateManager
|
||||
{
|
||||
public CustomEmbeddedResourceTemplateManager(string rootNamespace)
|
||||
{
|
||||
if(rootNamespace == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(rootNamespace));
|
||||
}
|
||||
|
||||
Namespace = rootNamespace;
|
||||
}
|
||||
|
||||
public string Namespace { get; }
|
||||
|
||||
public ITemplateSource Resolve(string key)
|
||||
{
|
||||
var assembly = GetType().Assembly;
|
||||
using(var stream = assembly.GetManifestResourceStream(Namespace + "." + key + ".cshtml"))
|
||||
{
|
||||
if(stream == null)
|
||||
{
|
||||
throw new RazorLightException(string.Format("Couldn't load resource '{0}.{1}.cshtml'.", Namespace, key));
|
||||
}
|
||||
|
||||
using(var reader = new StreamReader(stream))
|
||||
{
|
||||
return new LoadedTemplateSource(reader.ReadToEnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
186
src/Core/Services/Implementations/RazorViewMailService.cs
Normal file
186
src/Core/Services/Implementations/RazorViewMailService.cs
Normal file
@ -0,0 +1,186 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Models.Table;
|
||||
using RazorLight;
|
||||
using Bit.Core.Models.Mail;
|
||||
using RazorLight.Templating;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
|
||||
namespace Bit.Core.Services
|
||||
{
|
||||
public class RazorViewMailService : IMailService
|
||||
{
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
private readonly IRazorLightEngine _engine;
|
||||
private readonly IMailDeliveryService _mailDeliveryService;
|
||||
|
||||
public RazorViewMailService(
|
||||
GlobalSettings globalSettings,
|
||||
IMailDeliveryService mailDeliveryService)
|
||||
{
|
||||
_globalSettings = globalSettings;
|
||||
_mailDeliveryService = mailDeliveryService;
|
||||
|
||||
var manager = new CustomEmbeddedResourceTemplateManager("Bit.Core.MailTemplates");
|
||||
var core = new EngineCore(manager, EngineConfiguration.Default);
|
||||
var pageFactory = new DefaultPageFactory(core.KeyCompile);
|
||||
var lookup = new DefaultPageLookup(pageFactory);
|
||||
_engine = new RazorLightEngine(core, lookup);
|
||||
}
|
||||
|
||||
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.BaseVaultUri,
|
||||
SiteName = _globalSettings.SiteName
|
||||
};
|
||||
message.HtmlContent = _engine.Parse("ChangeEmailAlreadyExists", model);
|
||||
message.TextContent = _engine.Parse("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 ChangeEmailViewModel
|
||||
{
|
||||
Token = token,
|
||||
WebVaultUrl = _globalSettings.BaseVaultUri,
|
||||
SiteName = _globalSettings.SiteName
|
||||
};
|
||||
message.HtmlContent = _engine.Parse("ChangeEmail", model);
|
||||
message.TextContent = _engine.Parse("ChangeEmail.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 = hint,
|
||||
WebVaultUrl = _globalSettings.BaseVaultUri,
|
||||
SiteName = _globalSettings.SiteName
|
||||
};
|
||||
message.HtmlContent = _engine.Parse("MasterPasswordHint", model);
|
||||
message.TextContent = _engine.Parse("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.BaseVaultUri,
|
||||
SiteName = _globalSettings.SiteName
|
||||
};
|
||||
message.HtmlContent = _engine.Parse("NoMasterPasswordHint", model);
|
||||
message.TextContent = _engine.Parse("NoMasterPasswordHint.text", model);
|
||||
await _mailDeliveryService.SendEmailAsync(message);
|
||||
}
|
||||
|
||||
public async Task SendOrganizationAcceptedEmailAsync(string organizationName, string userEmail,
|
||||
IEnumerable<string> adminEmails)
|
||||
{
|
||||
var message = CreateDefaultMessage($"User {userEmail} Has Accepted Invite", adminEmails);
|
||||
var model = new OrganizationUserAcceptedViewModel
|
||||
{
|
||||
OrganizationName = organizationName,
|
||||
UserEmail = userEmail,
|
||||
WebVaultUrl = _globalSettings.BaseVaultUri,
|
||||
SiteName = _globalSettings.SiteName
|
||||
};
|
||||
message.HtmlContent = _engine.Parse("OrganizationUserInvited", model);
|
||||
message.TextContent = _engine.Parse("OrganizationUserInvited.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 = organizationName,
|
||||
WebVaultUrl = _globalSettings.BaseVaultUri,
|
||||
SiteName = _globalSettings.SiteName
|
||||
};
|
||||
message.HtmlContent = _engine.Parse("OrganizationUserConfirmed", model);
|
||||
message.TextContent = _engine.Parse("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 = organizationName,
|
||||
Email = WebUtility.UrlEncode(orgUser.Email),
|
||||
OrganizationId = orgUser.OrganizationId.ToString(),
|
||||
OrganizationUserId = orgUser.UserId.ToString(),
|
||||
Token = token,
|
||||
OrganizationNameUrlEncoded = WebUtility.UrlEncode(organizationName),
|
||||
WebVaultUrl = _globalSettings.BaseVaultUri,
|
||||
SiteName = _globalSettings.SiteName
|
||||
};
|
||||
message.HtmlContent = _engine.Parse("OrganizationUserInvited", model);
|
||||
message.TextContent = _engine.Parse("OrganizationUserInvited.text", model);
|
||||
await _mailDeliveryService.SendEmailAsync(message);
|
||||
}
|
||||
|
||||
public async Task SendWelcomeEmailAsync(User user)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MailMessage CreateDefaultMessage(string subject, string toEmail)
|
||||
{
|
||||
return CreateDefaultMessage(subject, new List<string> { toEmail });
|
||||
}
|
||||
|
||||
private MailMessage CreateDefaultMessage(string subject, IEnumerable<string> toEmails)
|
||||
{
|
||||
return new MailMessage
|
||||
{
|
||||
ToEmails = toEmails,
|
||||
Subject = subject
|
||||
};
|
||||
}
|
||||
|
||||
public class CustomEmbeddedResourceTemplateManager : ITemplateManager
|
||||
{
|
||||
public CustomEmbeddedResourceTemplateManager(string rootNamespace)
|
||||
{
|
||||
Namespace = rootNamespace ?? throw new ArgumentNullException(nameof(rootNamespace));
|
||||
}
|
||||
|
||||
public string Namespace { get; }
|
||||
|
||||
public ITemplateSource Resolve(string key)
|
||||
{
|
||||
var assembly = GetType().Assembly;
|
||||
using(var stream = assembly.GetManifestResourceStream(Namespace + "." + key + ".cshtml"))
|
||||
{
|
||||
if(stream == null)
|
||||
{
|
||||
throw new RazorLightException(string.Format("Couldn't load resource '{0}.{1}.cshtml'.", Namespace, key));
|
||||
}
|
||||
|
||||
using(var reader = new StreamReader(stream))
|
||||
{
|
||||
return new LoadedTemplateSource(reader.ReadToEnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -36,26 +36,26 @@ namespace Bit.Core.Services
|
||||
|
||||
sendGridMessage.AddTos(message.ToEmails.Select(e => new EmailAddress(e)).ToList());
|
||||
|
||||
if(message.MetaData.ContainsKey("SendGridTemplateId"))
|
||||
if(message.MetaData?.ContainsKey("SendGridTemplateId") ?? false)
|
||||
{
|
||||
sendGridMessage.HtmlContent = " ";
|
||||
sendGridMessage.PlainTextContent = " ";
|
||||
sendGridMessage.TemplateId = message.MetaData["SendGridTemplateId"].ToString();
|
||||
}
|
||||
|
||||
if(message.MetaData.ContainsKey("SendGridSubstitutions"))
|
||||
if(message.MetaData?.ContainsKey("SendGridSubstitutions") ?? false)
|
||||
{
|
||||
var subs = message.MetaData["SendGridSubstitutions"] as Dictionary<string, string>;
|
||||
sendGridMessage.AddSubstitutions(subs);
|
||||
}
|
||||
|
||||
if(message.MetaData.ContainsKey("SendGridCategories"))
|
||||
if(message.MetaData?.ContainsKey("SendGridCategories") ?? false)
|
||||
{
|
||||
var cats = message.MetaData["SendGridCategories"] as List<string>;
|
||||
sendGridMessage.AddCategories(cats);
|
||||
}
|
||||
|
||||
if(message.MetaData.ContainsKey("SendGridBypassListManagement"))
|
||||
if(message.MetaData?.ContainsKey("SendGridBypassListManagement") ?? false)
|
||||
{
|
||||
var bypass = message.MetaData["SendGridBypassListManagement"] as bool?;
|
||||
sendGridMessage.SetBypassListManagement(bypass.GetValueOrDefault(false));
|
||||
|
Reference in New Issue
Block a user