Encoding values
editA value written into HTML must be encoded for the place it is written to: otherwise, a name such as <b> or A & B breaks the layout of the email, and a value that comes from a user can inject HTML. HtmlEmailTemplate has one block per place:
| Place in the HTML | Block |
|---|---|
Text of an element: <p>…</p> | {{#html value}} |
Value of an attribute: alt="…", href="…" | {{#attr value}} |
| A part of a URL: a path segment, a query string value | {{#url value}} |
| HTML that you built and trust | {{# value}} |
A null value writes nothing.
Encode text
{{#html value}} encodes the characters that have a meaning in HTML:
using var template = new HtmlEmailTemplate();
template.Load("Hello {{#html \"<Meziantou>\" }}!");
var result = template.Run(out _);
Assert.Equal("Hello <Meziantou>!", result);The characters outside ASCII are written as numeric character references. Browsers and mail clients show the original characters:
using var template = new HtmlEmailTemplate();
template.Arguments.Add(new TemplateArgument("name", typeof(string)));
template.Load("<p>Hello {{#html name}}!</p>");
var result = template.Run(out _, "Zoé");
Assert.Equal("<p>Hello Zoé!</p>", result);Encode an attribute
{{#attr value}} encodes every character except the ASCII letters and digits, so the value is safe in a quoted attribute and in an unquoted one:
using var template = new HtmlEmailTemplate();
template.Load("Hello <a href=\"{{#attr \"Sample&Sample\"}}\">Meziantou</a>!");
var result = template.Run(out _);
Assert.Equal("Hello <a href=\"Sample&Sample\">Meziantou</a>!", result);Use it to write a complete URL in an href or a src attribute too: the encoded characters are decoded when the HTML is read.
Encode a part of a URL
{{#url value}} encodes a value for a part of a URL, such as a query string value:
using var template = new HtmlEmailTemplate();
template.Arguments.Add(new TemplateArgument("query", typeof(string)));
template.Load("<a href=\"https://example.com/search?q={{#url query}}\">Search</a>");
var result = template.Run(out _, "fish & chips");
Assert.Equal("<a href=\"https://example.com/search?q=fish%20%26%20chips\">Search</a>", result);It encodes :, /, ? and = too, so it is not suited to a complete URL: https://example.com/ would become https%3A%2F%2Fexample.com%2F. Write the fixed part of the URL in the template, and encode the variable parts only.
Write code in an HTML editor
An HTML editor encodes the <, > and & characters of the code blocks it shows as text. A {{html ... }} block decodes its code before compiling it, so a template edited in such an editor still compiles:
using var template = new HtmlEmailTemplate();
template.Load("{{html for(int i = 0; i < 3; i++) { }}{{#i}} {{ } }}");
var result = template.Run(out _);
Assert.Equal("0 1 2 ", result);The other blocks are not decoded: write their code with the plain characters.