I am using the Razor engine https://github.com/Antaris/RazorEngine to parse the body of my email templates. Is it possible to define a layout and include other .cshtml files
Fully custom solution of implementing Mail functionality.
Add nuget packet of RazorEngine
Create _Layout Template(.cshtml) :
Send Mail Logo
{{BODY}}
Create ConfirmEmail Template (.cshtml) :
@using yourProjectnamespace.LanguageResources.Mail
@model ConfirmEmail
@MailTemplateResource.YouHaveLoggedIn
@MailTemplateResource.ClickHere
Create CustomTemplateBase class :
public class CustomTemplateBase : TemplateBase
{
public string Url(string url)
{
return MailConfiguration.BaseUrl + url.TrimStart('/');
}
}
Create EmbeddedTemplateManager class :
internal class EmbeddedTemplateManager : ITemplateManager { private readonly string ns;
public EmbeddedTemplateManager(string @namespace)
{
ns = @namespace;
}
public ITemplateSource Resolve(ITemplateKey key)
{
var resourceName = $"{ns}.{key.Name}.cshtml";
string content;
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
using (var streamReader = new StreamReader(stream))
{
content = streamReader.ReadToEnd();
}
return new LoadedTemplateSource(content);
}
public ITemplateKey GetKey(string name, ResolveType resolveType, ITemplateKey context)
{
return new NameOnlyTemplateKey(name, resolveType, context);
}
public void AddDynamic(ITemplateKey key, ITemplateSource source)
{
throw new NotImplementedException("");
}
}
Create Mail Class :
public class Mail
{
private static readonly IRazorEngineService RazorEngine;
static Mail()
{
var config = new TemplateServiceConfiguration
{
BaseTemplateType = typeof(CustomTemplateBase<>),
TemplateManager = new EmbeddedTemplateManager(typeof(Mail).Namespace + ".Templates"),
Namespaces = { "Add CurrentProjectName", "Add CurrentProjectName .Models" },
CachingProvider = new DefaultCachingProvider()
};
RazorEngine = RazorEngineService.Create(config);
}
public Mail(string templateName)
{
TemplateName = templateName;
ViewBag = new DynamicViewBag();
}
public string TemplateName { get; set; }
public object Model { get; set; }
public DynamicViewBag ViewBag { get; set; }
public string GenerateBody()
{
var layout = RazorEngine.RunCompile("_Layout", model: null);
var body = RazorEngine.RunCompile(TemplateName, Model.GetType(), Model);
return layout.Replace("{{BODY}}", body);
}
public MailMessage Send(Guid key, string to, string subject, string cc = null)
{
var email = new MailMessage()
{
From = MailConfiguration.From,
Body = GenerateBody(),
IsBodyHtml = true,
Subject = subject,
BodyEncoding = Encoding.UTF8
};
email.Headers.Add("X-MC-Metadata", "{ \"key\": \"" + key.ToString("N") + "\" }");
foreach (var sendTo in to.Split(' ', ',', ';'))
{
email.To.Add(sendTo);
}
if (cc != null)
{
foreach (var sendCC in cc.Split(' ', ',', ';'))
{
email.CC.Add(sendCC);
}
}
var smtp = new MailClient().SmtpClient;
smtp.EnableSsl = true;
smtp.Send(email);
return email;
}
}
public class Mail : Mail where TModel : class
{
public Mail(string templateName, TModel mailModel) : base(templateName)
{
Model = mailModel;
}
}
Create MailClient Class :
public class MailClient
{
public MailClient()
{
SmtpClient = new SmtpClient(MailConfiguration.Host)
{
Port = MailConfiguration.Port,
Credentials = new NetworkCredential
{
UserName = MailConfiguration.UserName,
Password = MailConfiguration.Password
}
};
}
public SmtpClient SmtpClient { get; }
}
Create MailConfiguration Class :
public class MailConfiguration
{
private static string GetAppSetting(string key)
{
var element = ConfigurationManager.AppSettings["Mail:" + key];
return element ?? string.Empty;
}
public static string BaseUrl => GetAppSetting("BaseUrl");
public static string Host => GetAppSetting("Host");
public static int Port => Int32.Parse(GetAppSetting("Port"));
public static string UserName => GetAppSetting("Username");
public static string Password => GetAppSetting("Password");
public static MailAddress From => new MailAddress(GetAppSetting("From"));
}
MailSender Class :
Implement your method in MailSerder class and call MailSerder method in your repository or Controller.
Create public class MailSender : IMailSender
{
public MailSender()
{
}
public void SendConfirmEmail(string emailId, Guid userId)
{
var confirmEmail = new ConfirmEmail
{
UserId = userId
};
ConfirmEmail(emailId, MailResource.YourRegistration, confirmEmail);
}
private void ConfirmEmail(string recipient,string subject,ConfirmEmail model)
{
var key = Guid.NewGuid();
var mail = new Mail("ConfirmEmail", model);
mail.ViewBag.AddValue("Recipient", recipient);
var sentMail = mail.Send(key, recipient, subject);
}
}