I would like to generate emails using the Razor view engine.
From what I've read, I can use these OS projects to do that from my website:
- Postal
- ActionMailer.Net
- MvcMailer
However, all these use example where the user submits a form and an email is sent from the contoller. When creating the email a ControllerContext seems to be required. I am hoping to do the generating within my "Service" layer at periodic intervals, so I doubt I have access to the ControllerContext.
Is this doable?
Check this out. I'm using it with templates as embedded resources like this (but can be modified to locate templates anywhere):
public static class MailSender
{
static MailSender()
{
CompilerServiceFactory = new DefaultCompilerServiceFactory();
TemplateService = new TemplateService(CompilerServiceFactory.CreateCompilerService(), typeof(MailTemplate<>));
}
private static ICompilerServiceFactory CompilerServiceFactory { get; set; }
private static TemplateService TemplateService { get; set; }
private static ITemplate<T> GetTemplate<T>(T model)
{
string path = typeof(T).FullName;
var assembly = Assembly.GetExecutingAssembly();
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(path))
{
if (stream == null)
throw new FileNotFoundException("Mail template not found");
using (var reader = new StreamReader(stream))
{
string source = reader.ReadToEnd();
return TemplateService.GetTemplate<T>(source, model);
}
}
}
public static void Send<T>(string to, T model)
{
Send(new string[] { to }, new string[] { }, new string[] { }, model);
}
public static void Send<T>(string to, string cc, string bcc, T model)
{
Send(new string[] { to }, new string[] { cc }, new string[] { bcc }, model);
}
public static void Send<T>(string[] to, string[] cc, string[] bcc, T model)
{
var template = (MailTemplate<T>)GetTemplate<T>(model);
template.Execute();
Trace.WriteLine(string.Format("To: {0} Subject: {1}{3}Body: {2}", string.Join(",", to), template.Subject, template.Result, Environment.NewLine), "Mail");
#if !LOCAL
using (var message = new MailMessage())
using (var client = new SmtpClient())
{
if (!string.IsNullOrWhiteSpace(template.From))
message.From = new MailAddress(template.From);
message.To.Add(string.Join(",", to));
if (cc != null && cc.Length > 0)
message.CC.Add(string.Join(",", cc));
if (bcc != null && bcc.Length > 0)
message.Bcc.Add(string.Join(",", bcc));
message.Subject = template.Subject;
message.Body = template.Result;
message.IsBodyHtml = true;
client.Send(message);
}
#endif
}
}
public abstract class MailTemplate<TModel> : TemplateBase<TModel>
{
public string From { get; set; }
public string Subject { get; set; }
}
model:
public class Contact
{
public string Name { get; set; }
public string Email { get; set; }
public string Text { get; set; }
}
template:
@inherits Feedback.Lib.Mail.MailTemplate<Feedback.Lib.Mail.Templates.Contact>
@{
From = string.Format("{0} <{1}>", Model.Name, Model.Email);
Subject = "Contact request - " + From;
}
@Model.Text
I have for each template it's own model, so its easy to locate them via class name. Also I was unable to make intellisense work.
so what i use to get razor outside asp.net is the razor engine found on codeplex:
RazorEngine