Quick Start

Register the runtime, Scriban renderer, and filesystem reader:

using MailStencil;
using Microsoft.Extensions.DependencyInjection;

using var provider = new ServiceCollection()
    .AddMailStencil()
    .AddScribanRenderer()
    .AddFileSystemTemplateReader(options => options.BasePath = "templates")
    .BuildServiceProvider();

var templates = provider.GetRequiredService<IEmailTemplateService>();
var result = await templates.RenderAsync<OrderConfirmationModel>(
    "order-confirmation",
    new OrderConfirmationModel
    {
        CustomerName = "Ada & friends",
        OrderNumber = "MS-123",
        Total = 42.50m
    });

public sealed class OrderConfirmationModel
{
    public required string CustomerName { get; init; }
    public required string OrderNumber { get; init; }
    public decimal Total { get; init; }
}

MailStencil maps PascalCase model properties to Scriban snake_case names. A template can use:

Order {{ order_number }} totals {{ total }}
<p>Hello {{ customer_name | html.escape }}</p>

MailStencil does not automatically HTML-escape values. Use html.escape for untrusted values inserted into an HTML body. See validation and supported template syntax and the filesystem layout and security rules.