This is preliminary documentation and is subject to change.

Introduction

The DotNetExtras.Mail library can find, load, and transform localized email templates. For the detailed description of the library API, code samples, and usage scenarios, see the API documentation section.

Overview

The DotNetExtras.Mail library performs four tasks:

  1. Finds the most appropriate translation of a template for the given language.

  2. Loads a localized version of the template.

  3. Merges the localized version of the template with the message-specific data.

  4. Sets the email subject to the transformed text in the localized template's title element.

Notice that the library does not send emails. It only prepares the content of the email message, which can then be sent using any email-sending library or service.

Implementation

To get a localized template of a notification, the caller provides the path to the template folder, the template ID (the file name prefix), the requested language code in the format language-CULTURE (where the culture part is optional), such as en-US, es-MX, de, etc., and the template file name extension, such as .html. The library generates the name of the template file by joining the template ID, the language code, and the file name extension using the pre-defined separators (normally, the underscore character separates the template ID from the language and cultures suffix and language is separated from culture by a dash, but different characters can be configured).

For example, if the template ID is Welcome, the language code is pt-BR, and the file name extension is .html, then the library will look for a file named Welcome_pt-BR.html in the template folder. If the file with such name does not exist, the library will strip the culture part from the suffix and look for a file named Welcome_pt.html. If that file does not exist either, it will look for the default language, e.g. if the default language is en-US it will try Welcome_en-US.html.

Once the library determines the correct template file version for the requested language, it will keep the template in memory for faster access.

To merge a localized template with the message-specific data, DotNextExtras.Mail uses RazorLight, so the template must be formatted using the Razor syntax. The merge process will replace the placeholders in the template (entities that start with @, such as @Model.RecipientName) with the values from the provided data object, which must be a Dictionary<string, object> or an object with public properties that match the placeholders in the template (such as user.RecipientName).

Example

The following example illustrates how to load and merge a localized template for the given language and culture or the best alternative language.

Localized email template
<!DOCTYPE html>
<html lang="es">
<head>
<title>¡Bienvenida @Raw(Model.Zodiac)!</title>
<meta charset="utf-8">
</head>
<body>
<p>Hola @Raw(Model.Name),</p>
<p>
Tu signo del Zodiaco es: @Raw(Model.Zodiac).
</p>
<p>
&copy; @Model.Year | <a href="#">Términos</a> | <a href="#">Privacidad</a> | <a href="#">Darse de baja</a>
</p>
</body>
</html>
Load and merge the template
using DotNetExtras.Mail;
...

// Data object to be merged with the template.
Data data = new()
{
    Zodiac = "Géminis",
    Name = "José",
    Year = 2025
};

// Use the defaults in the constructor.
MailTemplate template = new();

// Load the 'es-MX' version of the 'Zodiac' email notification template 
// from the 'Samples/Zodiac' folder and merge it with the provided data.
// If the 'es-MX' version is not available, it will fall back to the 'es' translation.
// If the 'es' translation is also not available, it will fall back to the default template
// based on whatever default language suffix was defined previously.
template.Load("Samples/Zodiac", "Zodiac", "es-MX", ".html", data);

// The template object's 'Subject' property will hold the merged value 
// of the file template 'title' element, which in this example, will be:
// ¡Bienvenida Géminis!
string subject = template.Subject;

// The template object's 'Body' property will hold the merged value 
// of the file template's 'body' element.
string body = template.Body;

// The template object's 'Language' property will hold the language code 
// actually used by the template.
string language = template.Language;

For the complete example and other samples covering additional scenarios, see the unit tests.

See Also