This .NET Core 3.1 library is an abstraction of the approach we use over at Skyhop to send transactional emails to our subscribers. We believe that having a flexible method is vital to the ability to flexibly send emails.
This core principle behind this library is based on several prior blog posts:
- Rendering Razor views by supplying a model instance
- Using the RazorViewToStringRenderer with Asp.Net Core 3
There is a blog post which extensively describes the approach and background of this library available over here.
Installation
The NuGet hosted package is available.
Install it using the following commands:
Using the NuGet Package Manager
Install-Package Skyhop.Mail
Using the .NET CLI
dotnet add package Skyhop.Mail
You should reference this project on your template project (or at least the project which contains your views and view-models). After which there are two changes you will need to make to your .csproj
file:
- Set the SDK target to
Microsoft.NET.Sdk.Razor
. - Make sure you add the
AddRazorSupportForMvc
element to the file so that it looks like this:
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
Samples which can be used as a reference can be found in this repository.
Usage
- Add the
Skyhop.Mail
project to your template project. - Use the
.AddMailDispatcher()
extension method on yourIServiceCollection
as follows. Note that this library expects you to bring your own transport mechanism.
services.AddMailDispatcher(builder =>
{
builder.DefaultFromAddress = new MimeKit.MailboxAddress("Email Support", "support@example.tld");
});
- Add an implementation of
IMailSender
to yourIServiceCollection
. In the example project a simple Smtp implementation is included. - Add views and viewmodels to your templating project.
- Use the DI container to grab a
MailDispatcher
instance. Usage from code can be as follows. After this you can send an email based on the viewmodel as follows:
await _mailDispatcher.SendMail(
data: new ServiceActionModel
{
ActionName = "Starting",
Timestamp = DateTime.UtcNow
},
to: new[] { new MailboxAddress("John Doe", "john.doe@example.tld") });
Convention based view loading
If you would like to load all views in *.Views.dll
's you can use an overload AddMailDispatcher
, this overload enables the extension of IMvcCoreBuilder
. We created an extension which will find and load all *.Views.dll
files as application parts:
services.AddMailDispatcher(options =>
{
options.DefaultFromAddress = new MailboxAddress("Email Support", "support@example.tld");
},
builder => builder.AddViewsApplicationParts());
Gotchas
The following limitations are currently available. Feel free to submit a PR to fix one or more of those
- This library only works with projects which target
netcoreapp3.1
. This is a limitation based on the requirements of theMicrosoft.AspNetCore.Mvc.Razor.RuntimeCompilation
dependency. - It is expected that a view-model is only used once within a view. The code will use the first view it encounters that has the chosen model.