Email Templating with .NET
- uses mjml.net for email template formatting
uses mustache-sharp for variable substitution within the template- uses dotliquid for variable substitution
Required Packages
dotnet add package Mjml.Net
dotnet add package dotliquid
Template.mjml
<mjml>
<mj-head>
<mj-font name="Quicksand" href="https://fonts.googleapis.com/css?family=Quicksand" />
<mj-title>{{AppTypeName}} Contact</mj-title>
<mj-attributes>
<mj-all font-family="Quicksand,helvetica" />
</mj-attributes>
</mj-head>
<mj-body background-color="#ffffff">
<mj-section background-color="#ffffff">
<mj-column>
<mj-image width="150px" align="center" src="https://cdn.example.com/logo@2x.png" container-background-color="#ffffff" />
</mj-column>
</mj-section>
<mj-section background-color="#ffffff">
<mj-column>
<mj-text font-size="24px" color="#454FD0">{{AppTypeName}} Contact</mj-text>
<mj-divider border-color="#454FD0"></mj-divider>
<mj-text font-size="18px" color="#38428B">From: {{FromName}}</mj-text>
<mj-text font-size="18px" color="#38428B">Email Address: {{FromEmail}}</mj-text>
<mj-text font-size="18px" color="#38428B">Organisation: {{FromOrganization}}</mj-text>
<mj-text font-size="18px" color="#38428B">Message: {{Message | prettyprint | paragraph}}</mj-text>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff">
<mj-column>
<mj-divider border-color="#454FD0"></mj-divider>
<mj-text font-size="18px" color="#38428B">At: {{SentAt | date:"dd-MM-yyyy"}}</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
Program.cs
using Bogus;
using DotLiquid;
using Mjml.Net;
var user = new Faker<User>()
.CustomInstantiator(o => new User(o.Random.Guid(), o.Name.FirstName(), o.Internet.Email(), o.Company.CompanyName()))
.Generate();
var message = new Faker<Message>()
.CustomInstantiator(o => new Message(o.Random.Guid(), o.Date.Recent(), o.Commerce.ProductDescription()))
.Generate();
var rawMjml = File.ReadAllText("Template.mjml");
var mjmlRenderer = new MjmlRenderer();
var mjmlOptions = new MjmlOptions
{
Beautify = false,
Minify = true,
KeepComments = false
};
var renderedMjml = mjmlRenderer.Render(rawMjml, mjmlOptions);
if (renderedMjml.Errors.Any())
Console.WriteLine($"Error rendering MJML: {renderedMjml.Errors}");
Console.WriteLine($"Rendered Mjml: {renderedMjml}");
var renderedMjmlHtml = renderedMjml.Html;
var template = Template.Parse(renderedMjmlHtml);
var renderedHtml = template.Render(Hash.FromAnonymousObject(new
{
FromId = user,
FromName = user.FirstName,
FromEmail = user.EmailAddress,
FromOrganization = user.OrganizationName,
Message = message.Content,
SentAt = message.CreatedAt
}));
Console.WriteLine($"Rendered Html: {renderedHtml}");
DemoPlumbing.cs
public record User(Guid Id, string FirstName, string EmailAddress, string OrganizationName);
public record Message(Guid Id, DateTimeOffset CreatedAt, string Content);
Output Non Rendered
...
<div style="font-family:Quicksand,helvetica;font-size:18px;line-height:1;text-align:left;color:#38428B;">
Message: {{Message | prettyprint | paragraph}}
</div>
...
<div style="font-family:Quicksand,helvetica;font-size:18px;line-height:1;text-align:left;color:#38428B;">
At: {{SentAt}}
</div>
...
Output Rendered
...
<div style="font-family:Quicksand,helvetica;font-size:18px;line-height:1;text-align:left;color:#38428B;">
Message: The slim & simple Maple Gaming Keyboard from Dev Byte comes with a sleek body and 7- Color RGB LED Back-lighting for smart functionality
</div>
...
<div style="font-family:Quicksand,helvetica;font-size:18px;line-height:1;text-align:left;color:#38428B;">
At: 04-11-2023
</div>
...