剃刀视图页面作为电子邮件模板

本文关键字:电子邮件 视图 剃刀 | 更新日期: 2023-09-27 18:17:43

我用Razor语法设计了一个电子邮件模板。 当我使用 C# 代码和 SMTP 协议将此模板作为电子邮件发送时,我得到裸露的 Razor 和 HTML 标记作为电子邮件正文。 我这种方法错了吗? 允许将剃刀页面作为电子邮件模板吗?

这是我的页面

@inherits ViewPage
@{
Layout = "_Layout";
ViewBag.Title = "";
}
<div class="container w-420 p-15 bg-white mt-40">
<div style="border-top:3px solid #22BCE5">&nbsp;</div>
<span style="font-family:Arial;font-size:10pt">
    Hello <b>{UserName}</b>,<br /><br />
    Thanks for Registering to XYZ Portal<br /><br />
    <a style="color:#22BCE5" href="{Url}">Click to Confirm Email</a><br />
    <br /><br />
    Thanks<br />
    Admin (XYZ)
</span>

更新。。

 using (StreamReader reader = new StreamReader(HttpContext.Current.Server.MapPath("~/ContentPages/EmailConfTemplate.cshtml")))
  {
     body = reader.ReadToEnd();
     //Replace UserName and Other variables available in body Stream
     body = body.Replace("{UserName}", FirstName);
  }

稍后我将SMTP代码替换为..

  MailMessage message = new MailMessage(
    ApplicationWideData.fromEmailId, // From field
    ToEmailId, // Recipient field
    "Click On HyperLink To Verify Email Id", // Subject of the email message
    body
   );

剃刀视图页面作为电子邮件模板

不需要任何特殊库即可将 Razor 视图呈现为 ASP.NET MVC 应用程序中的字符串。

以下是您在MVC Core 3中的操作方法

public static class ViewToStringRenderer
{
    public static async Task<string> RenderViewToStringAsync<TModel>(IServiceProvider requestServices, string viewName, TModel model)
    {
        var viewEngine = requestServices.GetRequiredService(typeof(IRazorViewEngine)) as IRazorViewEngine;
        ViewEngineResult viewEngineResult = viewEngine.GetView(null, viewName, false);
        if (viewEngineResult.View == null)
        {
            throw new Exception("Could not find the View file. Searched locations:'r'n" + string.Join("'r'n", viewEngineResult.SearchedLocations));
        }
        else
        {
            IView view = viewEngineResult.View;
            var httpContextAccessor = (IHttpContextAccessor)requestServices.GetRequiredService(typeof(IHttpContextAccessor));
            var actionContext = new ActionContext(httpContextAccessor.HttpContext, new RouteData(), new ActionDescriptor());
            var tempDataProvider = requestServices.GetRequiredService(typeof(ITempDataProvider)) as ITempDataProvider;
            using var outputStringWriter = new StringWriter();
            var viewContext = new ViewContext(
                actionContext,
                view,
                new ViewDataDictionary<TModel>(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = model },
                new TempDataDictionary(actionContext.HttpContext, tempDataProvider),
                outputStringWriter,
                new HtmlHelperOptions());
            await view.RenderAsync(viewContext);
            return outputStringWriter.ToString();
        }
    }
}

在控制器中

string str = await ViewToStringRenderer.RenderViewToStringAsync(HttpContext.RequestServices, $"~/Views/Emails/MyEmailTemplate.cshtml", new MyEmailModel { Prop1 = "Hello", Prop2 = 23 });

在创业ConfigureServices().cs

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

以下是您在 MVC 5 中的操作方法

public static class ViewToStringRenderer
{
    public static string RenderViewToString<TModel>(ControllerContext controllerContext, string viewName, TModel model)
    {
        ViewEngineResult viewEngineResult = ViewEngines.Engines.FindView(controllerContext, viewName, null);
        if (viewEngineResult.View == null)
        {
            throw new Exception("Could not find the View file. Searched locations:'r'n" + viewEngineResult.SearchedLocations);
        }
        else
        {
            IView view = viewEngineResult.View;
            using (var stringWriter = new StringWriter())
            {
                var viewContext = new ViewContext(controllerContext, view, new ViewDataDictionary<TModel>(model), new TempDataDictionary(), stringWriter);
                view.Render(viewContext, stringWriter);
                return stringWriter.ToString();
            }
        }
    }
}

然后,从控制器

ViewToStringRenderer.RenderViewToString(this.ControllerContext, "~/Views/Emails/MyEmailTemplate.cshtml", model);

拥有电子邮件内容后,可以使用MailMessageSmtpClient轻松发送电子邮件。

电子邮件仅支持两种格式:纯文本和 HTML。由于 Razor 两者都不是,因此它需要由某个引擎处理,以便它返回生成的 HTML。

这正是你在幕后 ASP.NET MVC中使用Razor时发生的事情。Razor 文件被编译为一个内部 C# 类,该类被执行,执行的结果是发送到客户端的 HTML 的字符串内容。

您的问题是您希望并且需要该处理来运行,只是为了将 HTML 作为字符串返回,而不是发送到浏览器。之后,您可以对HTML字符串执行任何操作,包括将其作为电子邮件发送。

有几个软件包包含这种功能,我已经成功地使用了Westwind.RazorHosting,但你也可以使用RazorEngine获得类似的结果。我更喜欢RazorHosting用于独立的非Web应用程序,以及RazorEngine用于Web应用程序。

这是我的一些代码的(净化(版本 - 我正在使用Westwind.RazorHosting从Windows服务发送剃刀格式的电子邮件,使用强类型视图。

RazorFolderHostContainer host = = new RazorFolderHostContainer();
host.ReferencedAssemblies.Add("NotificationsManagement.dll");
host.TemplatePath = templatePath;
host.Start();
string output = host.RenderTemplate(template.Filename, model);
MailMessage mm = new MailMessage { Subject = subject, IsBodyHtml = true };
mm.Body = output;
mm.To.Add(email);
var smtpClient = new SmtpClient();
await smtpClient.SendMailAsync(mm);

你看过MVC Mailer吗?

这是一个免费的软件包,可从GitHub(https://github.com/smsohan/MvcMailer

(

也有分步指南 https://github.com/smsohan/MvcMailer/wiki/MvcMailer-Step-by-Step-Guide

它也在Nuget上。 https://www.nuget.org/packages/MvcMailer

从本质上讲,它会将您的剃刀视图解析为 html。

查看NuGet上可用的RazorEngine(https://razorengine.codeplex.com/(等剃刀处理器。 它处理 razor 以创建输出,然后您将该输出用作电子邮件的正文。

Mailzory项目是发送具有Razor模板的电子邮件的一个有价值且方便的选择。

// template path
var viewPath = Path.Combine("Views/Emails", "hello.cshtml");
// read the content of template and pass it to the Email constructor
var template = File.ReadAllText(viewPath);
var email = new Email(template);
// set ViewBag properties
email.ViewBag.Name = "Johnny";
email.ViewBag.Content = "Mailzory Is Funny";
// send email
var task = email.SendAsync("mailzory@outlook.com", "subject");
task.Wait()

该项目托管在Github。还有一个可用于Mailzory的nuget包。