MailForge

Templates

Templates translate an Email<TModel> into its final bodies before the pipeline validates and sends. A registry holds named templates; renderers resolve content with a model.

Inline Templates

InlineTemplateRenderer substitutes placeholders by walking the model's property graph. Arrays and `IList` indices are supported:.

var renderer = new InlineTemplateRenderer();
var html = renderer.Render("<h1>Hi , welcome back</h1>", new { Name = "Jane" });

In Email<TModel> subclasses this is what SetHtml("......") uses.

Razor Templates

RazorEmailTemplateRenderer compiles Razor templates with RazorEngineCore. Compiled templates are cached by content so each unique template compiles once.

Model visibility: Razor templates bind the model through the runtime dynamic dispatcher, so the model type must be publicly visible. A public record or class works; a private/internal nested model cannot be bound.

services.AddMailForge(builder => builder
    .RegisterTemplate("receipt", "<p>Receipt for @Model.Amount paid (ref @Model.Reference).</p>"));

A typed email then selects it by name:

public class ReceiptEmail : Email<ReceiptModel>
{
    public ReceiptEmail(ReceiptModel model) : base(model)
    {
        AddTo("customer@example.com");
        SetSubject("Your receipt");
        UseTemplate("receipt");
    }
}

Template Registry

ITemplateRegistry holds named templates:

The default TemplateRegistry is an in-memory dictionary; implement ITemplateRegistry for file- or database-backed storage and register it through RegisterTemplate or by replacing the registered service.