Skip to content

Commit e085f03

Browse files
Add the Emailing.Templates.Razor package.
1 parent 15db20c commit e085f03

File tree

11 files changed

+374
-0
lines changed

11 files changed

+374
-0
lines changed

PosInformatique.Foundations.slnx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@
4545
<Project Path="src/Emailing.Azure/Emailing.Azure.csproj" Id="3bcc0cf7-a90d-4d85-b540-58bf6c11eeee" />
4646
<Project Path="tests/Emailing.Azure.Tests/Emailing.Azure.Tests.csproj" Id="d782c2a5-8434-4cdb-8f53-ed20cdbc546d" />
4747
</Folder>
48+
<Folder Name="/Emailing/Templates/" />
49+
<Folder Name="/Emailing/Templates/Razor/">
50+
<Project Path="src/Emailing.Templates.Razor/Emailing.Templates.Razor.csproj" Id="2d0078a9-305d-43ad-aaa9-9f35f62f0873" />
51+
<Project Path="tests/Emailing.Templates.Razor.Tests/Emailing.Templates.Razor.Tests.csproj" Id="cb6212b5-270e-4ec9-bf07-6f7b8a3b8187" />
52+
</Folder>
4853
<Folder Name="/MediaTypes/">
4954
<Project Path="src/MediaTypes/MediaTypes.csproj" Id="31039dbf-ee6f-414c-8345-b92a6bc3e60a" />
5055
<Project Path="tests/MediaTypes.Tests/MediaTypes.Tests.csproj" Id="1cee2c26-ceb5-43c8-a5c9-98ced675385c" />

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ You can install any package using the .NET CLI or NuGet Package Manager.
2929
|<img src="./src/EmailAddresses/Icon.png" alt="PosInformatique.Foundations.EmailAddresses.Json icon" width="48" height="48" />|[**PosInformatique.Foundations.EmailAddresses.Json**](./src/EmailAddresses.Json/README.md) | `System.Text.Json` converter for the `EmailAddress` value object, enabling seamless serialization and deserialization of RFC 5322 compliant email addresses. | [![NuGet](https://img.shields.io/nuget/v/PosInformatique.Foundations.EmailAddresses.Json)](https://www.nuget.org/packages/PosInformatique.Foundations.EmailAddresses.Json) |
3030
|<img src="./src/Emailing/Icon.png" alt="PosInformatique.Foundations.Emailing icon" width="48" height="48" />|[**PosInformatique.Foundations.Emailing**](./src/Emailing/README.md) | Template-based emailing infrastructure for .NET that lets you register strongly-typed email templates, create emails from models, and send them through pluggable providers. | [![NuGet](https://img.shields.io/nuget/v/PosInformatique.Foundations.Emailing)](https://www.nuget.org/packages/PosInformatique.Foundations.Emailing) |
3131
|<img src="./src/Emailing/Icon.png" alt="PosInformatique.Foundations.Emailing.Azure icon" width="48" height="48" />|[**PosInformatique.Foundations.Emailing.Azure**](./src/Emailing.Azure/README.md) | `IEmailProvider` implementation for `PosInformatique.Foundations.Emailing` using **Azure Communication Service**. | [![NuGet](https://img.shields.io/nuget/v/PosInformatique.Foundations.Emailing.Azure)](https://www.nuget.org/packages/PosInformatique.Foundations.Emailing.Azure) |
32+
|<img src="./src/Emailing/Icon.png" alt="PosInformatique.Foundations.Emailing.Templates.Razor icon" width="48" height="48" />|[**PosInformatique.Foundations.Emailing.Templates.Razor**](./src/Emailing.Templates.Razor/README.md) | Helpers to build EmailTemplate instances from Razor components for subject and HTML body, supporting strongly-typed models and reusable layouts. | [![NuGet](https://img.shields.io/nuget/v/PosInformatique.Foundations.Emailing.Templates.Razor)](https://www.nuget.org/packages/PosInformatique.Foundations.Emailing.Templates.Razor) |
3233
|<img src="./src/MediaTypes/Icon.png" alt="PosInformatique.Foundations.MediaTypes icon" width="48" height="48" />|[**PosInformatique.Foundations.MediaTypes**](./src/MediaTypes/README.md) | Immutable `MimeType` value object with well-known media types and helpers to map between media types and file extensions. | [![NuGet](https://img.shields.io/nuget/v/PosInformatique.Foundations.MediaTypes)](https://www.nuget.org/packages/PosInformatique.Foundations.MediaTypes) |
3334
|<img src="./src/MediaTypes/Icon.png" alt="PosInformatique.Foundations.MediaTypes.EntityFramework icon" width="48" height="48" />|[**PosInformatique.Foundations.MediaTypes.EntityFramework**](./src/MediaTypes.EntityFramework/README.md) | Entity Framework Core integration for the `MimeType` value object, including property configuration and value converter for seamless database persistence. | [![NuGet](https://img.shields.io/nuget/v/PosInformatique.Foundations.MediaTypes.EntityFramework)](https://www.nuget.org/packages/PosInformatique.Foundations.MediaTypes.EntityFramework) |
3435
|<img src="./src/MediaTypes/Icon.png" alt="PosInformatique.Foundations.MediaTypes.Json icon" width="48" height="48" />|[**PosInformatique.Foundations.MediaTypes.Json**](./src/MediaTypes.Json/README.md) | `System.Text.Json` converter for the `MimeType` value object, enabling seamless serialization and deserialization of MIME types within JSON documents. | [![NuGet](https://img.shields.io/nuget/v/PosInformatique.Foundations.MediaTypes.Json)](https://www.nuget.org/packages/PosInformatique.Foundations.MediaTypes.Json) |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
1.0.0
2+
- Initial release with Emailing template based on Razor view.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<IsPackable>true</IsPackable>
5+
6+
<Description>
7+
Provides helpers to create EmailTemplate instances using Razor components for subject and HTML body.
8+
Built on top of PosInformatique.Foundations.Text.Templating.Razor, it supports strongly-typed models and Razor layout features for reusable email designs.
9+
</Description>
10+
<PackageTags>email;emailing;razor;blazor;templating;component;layout;dotnet;posinformatique;emailtemplate</PackageTags>
11+
<PackageReleaseNotes>
12+
$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/CHANGELOG.md"))
13+
</PackageReleaseNotes>
14+
15+
</PropertyGroup>
16+
17+
<ItemGroup>
18+
<ProjectReference Include="..\Emailing\Emailing.csproj" />
19+
<ProjectReference Include="..\Text.Templating.Razor\Text.Templating.Razor.csproj" />
20+
</ItemGroup>
21+
22+
<ItemGroup>
23+
<Content Include="CHANGELOG.md" Pack="false" />
24+
<Content Include="..\Emailing\Icon.png" Pack="true" PackagePath="" />
25+
<Content Include="README.md" Pack="true" PackagePath="" />
26+
</ItemGroup>
27+
28+
</Project>
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# PosInformatique.Foundations.Emailing.Templates.Razor
2+
3+
[![NuGet version](https://img.shields.io/nuget/v/PosInformatique.Foundations.Emailing.Templates.Razor)](https://www.nuget.org/packages/PosInformatique.Foundations.Emailing.Templates.Razor/)
4+
[![NuGet downloads](https://img.shields.io/nuget/dt/PosInformatique.Foundations.Emailing.Templates.Razor)](https://www.nuget.org/packages/PosInformatique.Foundations.Emailing.Templates.Razor/)
5+
6+
## Introduction
7+
8+
[PosInformatique.Foundations.Emailing.Templates.Razor](https://www.nuget.org/packages/PosInformatique.Foundations.Emailing.Templates.Razor/)
9+
provides helpers to create `EmailTemplate<TModel>` instances using Razor components as text templates for the subject and HTML body.
10+
11+
It is built on top of:
12+
13+
- [PosInformatique.Foundations.Emailing](https://www.nuget.org/packages/PosInformatique.Foundations.Emailing.Templates.Razor/)
14+
- [PosInformatique.Foundations.Text.Templates.Razor](https://www.nuget.org/packages/PosInformatique.Foundations.Emailing.Templates.Razor/)
15+
16+
This allows you to design your email content with Blazor-style Razor components, benefiting from layout reuse, strongly-typed models, and familiar Razor syntax.
17+
18+
## Install
19+
20+
You can install the package from [NuGet](https://www.nuget.org/packages/PosInformatique.Foundations.Emailing.Templates.Razor/):
21+
22+
```powershell
23+
dotnet add package PosInformatique.Foundations.Emailing.Templates.Razor
24+
```
25+
26+
You also need a Blazor-compatible environment for compiling/executing Razor components.
27+
28+
## Features
29+
30+
- `RazorEmailTemplate<TModel>.Create<TSubjectComponent, TBodyComponent>()` to build `EmailTemplate<TModel>` from Razor components.
31+
- Base classes for Razor components:
32+
- `RazorEmailTemplateSubject<TModel>` for email subject.
33+
- `RazorEmailTemplateBody<TModel>` for email HTML body.
34+
- Strongly-typed model support via the `Model` parameter.
35+
- Supports Razor layout features for the email body (reuse consistent layout across multiple templates).
36+
37+
## Creating Razor components for subject and body
38+
39+
### 1. Define the email model
40+
41+
Example model used by the templates:
42+
43+
```csharp
44+
using PosInformatique.Foundations.Emailing;
45+
46+
public sealed class InvitationEmailTemplateModel : EmailModel
47+
{
48+
public string FirstName { get; set; } = string.Empty;
49+
public string InvitationLink { get; set; } = string.Empty;
50+
}
51+
```
52+
53+
### 2. Subject component
54+
55+
Create a Razor component for the subject that inherits from `RazorEmailTemplateSubject<TModel>` and uses the `Model` parameter.
56+
57+
`InvitationEmailSubject.razor`:
58+
59+
```razor
60+
@using PosInformatique.Foundations.Emailing
61+
@using PosInformatique.Foundations.Emailing.Templates.Razor
62+
@inherits RazorEmailTemplateSubject<InvitationEmailTemplateModel>
63+
64+
Invitation for @Model.FirstName
65+
```
66+
67+
This component:
68+
69+
- Renders a single line of text.
70+
- Uses the strongly-typed `Model` to build the subject.
71+
72+
### 3. Body component with layout
73+
74+
You can define a layout component that centralizes common HTML structure (header, footer, styles, etc.),
75+
then reuse it across different email bodies.
76+
77+
`EmailLayout.razor` (layout component):
78+
79+
```razor
80+
@inherits LayoutComponentBase
81+
82+
<!DOCTYPE html>
83+
<html>
84+
<head>
85+
<meta charset="utf-8" />
86+
<title>@Title</title>
87+
<style>
88+
body {
89+
font-family: Arial, sans-serif;
90+
font-size: 14px;
91+
}
92+
93+
.email-container {
94+
max-width: 600px;
95+
margin: 0 auto;
96+
}
97+
98+
.email-header {
99+
background-color: #1f2937;
100+
color: #ffffff;
101+
padding: 16px;
102+
font-size: 18px;
103+
font-weight: bold;
104+
}
105+
106+
.email-content {
107+
padding: 16px;
108+
}
109+
110+
.email-footer {
111+
padding: 16px;
112+
font-size: 12px;
113+
color: #6b7280;
114+
}
115+
</style>
116+
</head>
117+
<body>
118+
<div class="email-container">
119+
<div class="email-header">
120+
@Title
121+
</div>
122+
123+
<div class="email-content">
124+
@Body
125+
</div>
126+
127+
<div class="email-footer">
128+
This email was sent by MyApp.
129+
</div>
130+
</div>
131+
</body>
132+
</html>
133+
```
134+
135+
Now create the specific body component for your invitation email.
136+
137+
`InvitationEmailBody.razor`:
138+
139+
```razor
140+
@using PosInformatique.Foundations.Emailing
141+
@using PosInformatique.Foundations.Emailing.Templates.Razor
142+
@inherits RazorEmailTemplateBody<InvitationEmailTemplateModel>
143+
@layout EmailLayout
144+
145+
@{
146+
Title = $"Invitation for {Model.FirstName}";
147+
}
148+
149+
<p>Hello @Model.FirstName,</p>
150+
151+
<p>
152+
You have been invited to join our platform.
153+
Please click the link below to accept your invitation:
154+
</p>
155+
156+
<p>
157+
<a href="@Model.InvitationLink">@Model.InvitationLink</a>
158+
</p>
159+
160+
<p>
161+
If you did not expect this email, you can safely ignore it.
162+
</p>
163+
```
164+
165+
Key points:
166+
167+
- The body component inherits from `RazorEmailTemplateBody<InvitationEmailTemplateModel>`.
168+
- It uses `@layout EmailLayout` to reuse the common HTML structure.
169+
- It uses the `Model` property to inject data into the HTML.
170+
171+
## Creating an EmailTemplate from Razor components
172+
173+
Use the static helper `RazorEmailTemplate<TModel>.Create<TSubjectComponent, TBodyComponent>()` to build an `EmailTemplate<TModel>` instance.
174+
175+
```csharp
176+
using PosInformatique.Foundations.Emailing;
177+
using PosInformatique.Foundations.Emailing.Templates.Razor;
178+
179+
var invitationTemplate = RazorEmailTemplate<InvitationEmailTemplateModel>.Create<
180+
InvitationEmailSubject,
181+
InvitationEmailBody>();
182+
```
183+
184+
You can then register this template in `EmailingOptions`:
185+
186+
```csharp
187+
options.RegisterTemplate(EmailTemplateIdentifiers.Invitation, invitationTemplate);
188+
```
189+
190+
After that, the rest of the flow is the same as with any other `EmailTemplate<TModel>`:
191+
192+
- Use `IEmailManager.Create(EmailTemplateIdentifiers.Invitation)` to create the email.
193+
- Add recipients and models.
194+
- Call `SendAsync(...)` to send.
195+
196+
## Links
197+
198+
- [NuGet package: Emailing (core library)](https://www.nuget.org/packages/PosInformatique.Foundations.Emailing/)
199+
- [NuGet package: Emailing.Templates.Razor](https://www.nuget.org/packages/PosInformatique.Foundations.Emailing.Templates.Razor/)
200+
- [NuGet package: Text.Templating.Razor](https://www.nuget.org/packages/PosInformatique.Foundations.Text.Templating.Razor/)
201+
- [Source code](https://github.com/PosInformatique/PosInformatique.Foundations)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//-----------------------------------------------------------------------
2+
// <copyright file="RazorEmailTemplate.cs" company="P.O.S Informatique">
3+
// Copyright (c) P.O.S Informatique. All rights reserved.
4+
// </copyright>
5+
//-----------------------------------------------------------------------
6+
7+
namespace PosInformatique.Foundations.Emailing.Templates.Razor
8+
{
9+
using PosInformatique.Foundations.Text.Templating.Razor;
10+
11+
/// <summary>
12+
/// Used to create an <see cref="EmailTemplate{TModel}"/> using Razor text templating for the subject and body.
13+
/// </summary>
14+
/// <typeparam name="TModel">Type of the model used to generate the subject and body of the e-mail.</typeparam>
15+
public static class RazorEmailTemplate<TModel>
16+
where TModel : EmailModel
17+
{
18+
/// <summary>
19+
/// Creates an <see cref="EmailTemplate{TModel}"/> using the specified Razor components as text templating for the subject and body.
20+
/// </summary>
21+
/// <typeparam name="TSubjectComponent">Type of the Razor component used to generate the content of the e-mail subject.</typeparam>
22+
/// <typeparam name="TBodyComponent">Type of the Razor component used to generate the content of the e-mail body.</typeparam>
23+
/// <returns>An instance <see cref="EmailTemplate{TModel}"/> using the specified Razor components as text templating for the subject and body.</returns>
24+
public static EmailTemplate<TModel> Create<TSubjectComponent, TBodyComponent>()
25+
where TSubjectComponent : RazorEmailTemplateSubject<TModel>
26+
where TBodyComponent : RazorEmailTemplateBody<TModel>
27+
{
28+
return new EmailTemplate<TModel>(
29+
new RazorTextTemplate<TModel>(typeof(TSubjectComponent)),
30+
new RazorTextTemplate<TModel>(typeof(TBodyComponent)));
31+
}
32+
}
33+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//-----------------------------------------------------------------------
2+
// <copyright file="RazorEmailTemplateBody.cs" company="P.O.S Informatique">
3+
// Copyright (c) P.O.S Informatique. All rights reserved.
4+
// </copyright>
5+
//-----------------------------------------------------------------------
6+
7+
namespace PosInformatique.Foundations.Emailing.Templates.Razor
8+
{
9+
using Microsoft.AspNetCore.Components;
10+
11+
/// <summary>
12+
/// Base class of a Razor component which is used to generate the body of an email.
13+
/// </summary>
14+
/// <typeparam name="TModel">Type of the <see cref="Model"/> used to generate the body of the e-mail.</typeparam>
15+
public abstract class RazorEmailTemplateBody<TModel> : ComponentBase
16+
where TModel : EmailModel
17+
{
18+
/// <summary>
19+
/// Initializes a new instance of the <see cref="RazorEmailTemplateBody{TModel}"/> class.
20+
/// </summary>
21+
protected RazorEmailTemplateBody()
22+
{
23+
}
24+
25+
/// <summary>
26+
/// Gets or sets the model used to generate the body of the e-mail.
27+
/// </summary>
28+
[Parameter]
29+
public TModel Model { get; set; } = default!;
30+
}
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//-----------------------------------------------------------------------
2+
// <copyright file="RazorEmailTemplateSubject.cs" company="P.O.S Informatique">
3+
// Copyright (c) P.O.S Informatique. All rights reserved.
4+
// </copyright>
5+
//-----------------------------------------------------------------------
6+
7+
namespace PosInformatique.Foundations.Emailing.Templates.Razor
8+
{
9+
using Microsoft.AspNetCore.Components;
10+
11+
/// <summary>
12+
/// Base class of a Razor component which is used to generate the subject of an email.
13+
/// </summary>
14+
/// <typeparam name="TModel">Type of the <see cref="Model"/> used to generate the subject of the e-mail.</typeparam>
15+
public abstract class RazorEmailTemplateSubject<TModel> : ComponentBase
16+
where TModel : EmailModel
17+
{
18+
/// <summary>
19+
/// Initializes a new instance of the <see cref="RazorEmailTemplateSubject{TModel}"/> class.
20+
/// </summary>
21+
protected RazorEmailTemplateSubject()
22+
{
23+
}
24+
25+
/// <summary>
26+
/// Gets or sets the model used to generate the body of the e-mail.
27+
/// </summary>
28+
[Parameter]
29+
public TModel Model { get; set; } = default!;
30+
}
31+
}

src/Text.Templating.Razor/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ As long as `IDateTimeProvider` and `IMyFormatter` are registered in the `IServic
157157

158158
## Links
159159

160+
- [NuGet package: Emailing.Templates.Razor](https://www.nuget.org/packages/PosInformatique.Foundations.Emailing.Templates.Razor/)
160161
- [NuGet package: Text.Templating (core library)](https://www.nuget.org/packages/PosInformatique.Foundations.Text.Templating/)
161162
- [NuGet package: Text.Templating.Razor](https://www.nuget.org/packages/PosInformatique.Foundations.Text.Templating/)
162163
- [Source code](https://github.com/PosInformatique/PosInformatique.Foundations)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<ItemGroup>
4+
<ProjectReference Include="..\..\src\Emailing.Templates.Razor\Emailing.Templates.Razor.csproj" />
5+
</ItemGroup>
6+
7+
</Project>

0 commit comments

Comments
 (0)