You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Razor(.cshtml)模板的.NET Core 2.0邮件发送类库问询

我太懂你这种需求了——找了好久都没找到清晰的方案,想用Razor视图当邮件模板,还想打包成类库让别的Web应用直接引用实现发邮件,对吧?我之前折腾过这个,给你分享一套落地的步骤:

1. 先搭好Razor类库的基础结构

别用普通的类库,直接创建Razor类库(Razor Class Library),选“支持页面和视图”的模板——这种项目天生就支持Razor视图的编译与嵌入,完美适配你的需求。

2. 定义邮件模型与模板
  • 新建Models文件夹,放对应模板的模型类,比如PasswordResetEmailModel,把邮件需要的字段都塞进去:用户名、重置链接、过期时间这些。
  • 新建Views/Emails文件夹,把你的Razor模板放进去,比如PasswordReset.cshtml。顶部记得指定模型:
    @model YourLibraryName.Models.PasswordResetEmailModel
    <!DOCTYPE html>
    <html>
    <head>
        <title>密码重置</title>
        <style>
            /* 邮件里尽量用内联样式,避免客户端不识别外部CSS */
            .container { padding: 20px; background-color: #f5f5f5; }
            .content { background-color: white; padding: 30px; border-radius: 8px; }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="content">
                <h3>您好,@Model.UserName</h3>
                <p>请点击下方链接重置您的密码:</p>
                <a href="@Model.ResetLink">重置密码</a>
                <p>链接将在@Model.ExpireTime 后失效</p>
            </div>
        </div>
    </body>
    </html>
    
3. 实现EmailSender服务

在类库新建Services文件夹,先搞个接口IEmailSender,再写实现类EmailSender:

  • 核心是把Razor视图渲染成HTML字符串,需要注入IRazorViewEngine、ITempDataProvider、IHttpContextAccessor这些服务(如果类库没有这些依赖,要先引用Microsoft.AspNetCore.Mvc.ViewFeatures包)。
  • 写一个RenderViewToStringAsync方法,负责视图渲染:
    private async Task<string> RenderViewToStringAsync(string viewPath, object model)
    {
        var actionContext = new ActionContext(
            _httpContextAccessor.HttpContext ?? new DefaultHttpContext(),
            new RouteData(),
            new ActionDescriptor()
        );
    
        using var sw = new StringWriter();
        var viewResult = _razorViewEngine.FindView(actionContext, viewPath, false);
    
        if (!viewResult.Success)
        {
            throw new InvalidOperationException($"找不到视图:{viewPath}");
        }
    
        var viewDictionary = new ViewDataDictionary(
            new EmptyModelMetadataProvider(),
            new ModelStateDictionary()
        ) { Model = model };
    
        var viewContext = new ViewContext(
            actionContext,
            viewResult.View,
            viewDictionary,
            new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),
            sw,
            new HtmlHelperOptions()
        );
    
        await viewResult.View.RenderAsync(viewContext);
        return sw.ToString();
    }
    
  • 然后在SendEmailAsync方法里,先渲染HTML,再用邮件客户端发送(推荐用MailKit,比.NET自带的SmtpClient靠谱):
    public async Task SendEmailAsync(string toEmail, string subject, object model, string viewPath)
    {
        var htmlContent = await RenderViewToStringAsync(viewPath, model);
    
        // 这里用MailKit实现发送逻辑,需要先引用MailKit和MimeKit包
        var message = new MimeMessage();
        message.From.Add(new MailboxAddress("你的发件人名称", "sender@example.com"));
        message.To.Add(new MailboxAddress("", toEmail));
        message.Subject = subject;
    
        message.Body = new TextPart("html") { Text = htmlContent };
    
        using var client = new SmtpClient();
        await client.ConnectAsync("smtp.example.com", 587, SecureSocketOptions.StartTls);
        await client.AuthenticateAsync("your-username", "your-password");
        await client.SendAsync(message);
        await client.DisconnectAsync(true);
    }
    
4. 确保视图被正确嵌入到类库

打开类库的.csproj文件,确认有这段配置(没有的话手动加上),这样所有.cshtml文件都会被嵌入到DLL里,引用类库的Web应用不需要复制视图文件:

<ItemGroup>
  <EmbeddedResource Include="Views/**/*.cshtml" />
</ItemGroup>
5. Web应用引用与使用
  • 把类库作为项目引用或者NuGet包添加到你的Web应用。
  • 在Web应用的Program.cs里注册服务:
    builder.Services.AddScoped<IEmailSender, YourLibraryName.Services.EmailSender>();
    // 别忘了注册IHttpContextAccessor,因为渲染视图需要它
    builder.Services.AddHttpContextAccessor();
    
  • 然后在需要发邮件的地方(比如控制器、服务)注入IEmailSender,调用方法就行:
    var model = new PasswordResetEmailModel
    {
        UserName = "张三",
        ResetLink = "https://yourapp.com/reset-password?token=xxx",
        ExpireTime = DateTime.Now.AddHours(1).ToString("yyyy-MM-dd HH:mm:ss")
    };
    await _emailSender.SendEmailAsync("user@example.com", "密码重置通知", model, "/Views/Emails/PasswordReset.cshtml");
    
几个关键提醒
  • 邮件里的样式尽量用内联CSS,大部分邮件客户端不支持外部样式表。
  • 邮件服务器的配置(SMTP地址、账号、密码)可以让Web应用通过appsettings.json配置,在EmailSender里注入IConfiguration读取,不要硬编码在类库中。
  • 测试的时候,可以先把渲染后的HTML保存到本地文件,确认格式没问题再实际发送,避免频繁发测试邮件。

内容的提问来源于stack exchange,提问作者akd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:13:59