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

Asp.Net Core 2.0中MimeKit BodyBuilder的{}占位符与CSS冲突解决

解决MimeKit邮件模板中CSS大括号与占位符冲突的问题

这个问题我之前也碰到过,确实挺头疼的——CSS里的大括号和{0}这类格式化占位符撞车了,.NET的string.Format(或类似格式化方法)会把所有{}都当成占位符来解析,直接使用就会触发格式异常。给你几个实用的解决办法:

方法一:转义模板中的CSS大括号

最简单的方式是修改邮件模板,把CSS里的单个{替换成{{,单个}替换成}}。这样string.Format会把{{}}解析成普通的大括号,而{0}、{1}仍然作为占位符正常工作。

比如原模板中的CSS:

.discount-banner {
    background-color: #ff4444;
    padding: 10px;
}

修改后:

.discount-banner {{
    background-color: #ff4444;
    padding: 10px;
}}

然后在代码中正常使用string.Format填充数据:

var pathToFile = _enviorment.WebRootPath + Path.DirectorySeparatorChar + "Templates" + Path.DirectorySeparatorChar + "EmailTemplate" + Path.DirectorySeparatorChar + "Discount.html";
var builder = new BodyBuilder();
using (StreamReader reader = new StreamReader(pathToFile))
{
    var templateContent = reader.ReadToEnd();
    // 假设需要填充折扣描述和优惠码
    var formattedContent = string.Format(templateContent, "专属8折优惠", "DISCOUNT80");
    builder.HtmlBody = formattedContent;
}
// 后续发送邮件逻辑...

方法二:使用自定义语义化占位符

如果不想修改模板里的CSS代码,可以把{0}、{1}这类占位符换成自定义的标记(比如{{DISCOUNT_DESC}}、{{COUPON_CODE}}),然后用字符串替换的方式填充数据,完全避开大括号冲突。

模板中的占位符示例:

<p>您好,您获得了{{DISCOUNT_DESC}},优惠码是{{COUPON_CODE}}</p>

代码中替换逻辑:

var pathToFile = _enviorment.WebRootPath + Path.DirectorySeparatorChar + "Templates" + Path.DirectorySeparatorChar + "EmailTemplate" + Path.DirectorySeparatorChar + "Discount.html";
var builder = new BodyBuilder();
using (StreamReader reader = new StreamReader(pathToFile))
{
    var templateContent = reader.ReadToEnd();
    var formattedContent = templateContent
        .Replace("{{DISCOUNT_DESC}}", "专属8折优惠")
        .Replace("{{COUPON_CODE}}", "DISCOUNT80");
    builder.HtmlBody = formattedContent;
}

这种方法的优势是占位符有语义,可读性更强,也不用担心CSS大括号的干扰。

方法三:使用专业模板引擎(推荐复杂场景)

如果你的项目是ASP.NET Core,更推荐用Razor视图作为邮件模板。Razor支持用@Model语法绑定数据,完全不会和CSS大括号冲突,还能支持循环、条件判断等复杂逻辑,维护起来更方便。

  1. 创建一个Razor视图(比如EmailTemplates/Discount.cshtml):
@model DiscountEmailModel
<style>
.discount-banner {
    background-color: #ff4444;
    padding: 10px;
}
</style>
<div class="discount-banner">
    <p>您好,您获得了@Model.DiscountDesc,优惠码是@Model.CouponCode</p>
</div>
  1. 创建对应的模型类:
public class DiscountEmailModel
{
    public string DiscountDesc { get; set; }
    public string CouponCode { get; set; }
}
  1. 使用Razor引擎渲染视图为字符串:
// 注入IRazorViewEngine和ITempDataProvider
private readonly IRazorViewEngine _razorViewEngine;
private readonly ITempDataProvider _tempDataProvider;

public async Task<string> RenderEmailTemplateAsync(DiscountEmailModel model)
{
    var viewResult = _razorViewEngine.FindView(ControllerContext, "EmailTemplates/Discount", false);
    if (!viewResult.Success)
    {
        throw new InvalidOperationException("找不到邮件模板");
    }

    using var sw = new StringWriter();
    var viewContext = new ViewContext(
        ControllerContext,
        viewResult.View,
        new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
        {
            Model = model
        },
        new TempDataDictionary(ControllerContext.HttpContext, _tempDataProvider),
        sw,
        new HtmlHelperOptions()
    );

    await viewResult.View.RenderAsync(viewContext);
    return sw.ToString();
}
  1. 把渲染后的字符串赋值给BodyBuilder:
var model = new DiscountEmailModel { DiscountDesc = "专属8折优惠", CouponCode = "DISCOUNT80" };
var htmlContent = await RenderEmailTemplateAsync(model);
builder.HtmlBody = htmlContent;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:22:51