AspNetCore.MailKitMailer
1.2.2
dotnet add package AspNetCore.MailKitMailer --version 1.2.2
NuGet\Install-Package AspNetCore.MailKitMailer -Version 1.2.2
<PackageReference Include="AspNetCore.MailKitMailer" Version="1.2.2" />
paket add AspNetCore.MailKitMailer --version 1.2.2
#r "nuget: AspNetCore.MailKitMailer, 1.2.2"
// Install AspNetCore.MailKitMailer as a Cake Addin #addin nuget:?package=AspNetCore.MailKitMailer&version=1.2.2 // Install AspNetCore.MailKitMailer as a Cake Tool #tool nuget:?package=AspNetCore.MailKitMailer&version=1.2.2
AspNetCore.MailKitMailer (by Malte)
This Mail Client is baded on MailKit to provide HTML-Emails rendered by razor view engine for .NET 6.x
Other Versions
For best support look at the table below please:
Each minor version has its own support for each .net version. Future major releases are only released for the next, current and lts support versions.
.NET Version | Package Version | Branch |
---|---|---|
.NET Core 3.1 | 1.0.x | 1.0.x |
.NET 5 | 1.1.x | 1.1.x |
.NET 6 | 1.2.x | 1.2.x |
Third Party Dependencies
Install
Using the nuget package manager:
Install-Package AspNetCore.MailKitMailer
Using the dotnet cli:
dotnet add package AspNetCore.MailKitMailer
Enable it:
// Startup.cs
public IServiceProvider ConfigureServices(IServiceCollection services) {
services.AddAspNetCoreMailKitMailer(Configuration)
.RegisterAllMailContexesOfCallingAssembly(); // This will add all MailerContexes defined in the calling assembly (see below for more options)
}
Configuration
You can configure the mailer via IConfiguration using your appsettings.json (I highly recommend to use the AppSecrets in production mode for storing your password/login)
{
"MailKitMailer": {
"Host": "localhost",
"Port": 0,
"UseSSL": true,
"CheckCertificateRevocation": false,
"Username": "user",
"Password": "pass",
"FromAddress": {
"Name": "Community",
"Email": "noreply@localhost"
}
}
}
Configuration Entries and their meanings
Configuration Entry Name | Description | Default Value | Type |
---|---|---|---|
Host | The host to the smtp server | null | String |
Port | The Port to connect to the smtp server | 0 | Integer |
UseSSL | Enforces SSL usage for smtp connection | false | Boolean |
CheckCertificateRevocation | Force MailKot to dont check for certificate revocation | false | Boolean |
Username | The Username to authenticate to the smtp server | null | String |
Password | The Password to authenticate to the smtp server | null | String |
FromAddress | The From Address for all mails (default from address) | null | FromAddress |
FromAddress.Name | The name for the from address (e.g. John Doe) | undefined | String |
FromAddress.Email | The email for the from address (e.g. john.doe@localhost) | undefined | String |
Usage
Preparing your view folder
Create an folder in your root web project folder called Mailer-Views
Add the following files with its contents for the start:
_ViewStart.cshtml
@{
Layout = "_Layout";
}
_ViewImports.cshtml
@using MailKitMailerExample
@using MailKitMailerExample.Models
@using MailKitMailerExample.Models.MailModels
@using AspNetCore.MailKitMailer.Helper
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, AspNetCore.MailKitMailer // this will add the mailkit css helper to inline css files
Shared/_Layout.cshtml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Integration Tests</title>
</head>
<body>
<div class="inttest-body">
@RenderBody()
</div>
</body>
</html>
Now your view folder is set up for using the mailer.
Creating your contex
Fist we need to create or mailing contex. Create an class called "TesTmailer".
Our Testmailer class will extend AspNetCore.MailKitMailer.Data.MailerContextAbstract
.
using System;
using System.Collections.Generic;
using System.Linq;
using AspNetCore.MailKitMailer.Data;
using AspNetCore.MailKitMailer.Domain;
using AspNetCore.MailKitMailer.Models;
using MailKitMailerExample.Models.MailModels;
namespace MailKitMailerExample.Mailer
{
public class TestMailer : MailerContextAbstract
{
public IMailerContextResult WelcomeMail(string username, string email)
{
return this.HtmlMail(new EmailAddressModel(username, email),
$"Welcome {username}!",
new WelcomeModel() { Username = username, Date = DateTime.Now });
}
}
}
For explaining: The Method "WelcomeMaiL" will prepare an HtmlMessage (Possible is also plain text Message. Use the helper function "TextMessage" in this case)
Since our method is called "WelcomeMail" and we didnt provide an addtitional view name the mailer will try to render the view "WelcomeMail" in the ~/Mailer-Views/TestMailer/
or ~/Views/Mailer/TestMailer
directory.
Fallback paths for this whould bne ~/Views/Mailer/WelcomeMail.cshtml
or ~/Mailer-Views/WelcomeMail.cshtml
All we need to do now is extracting our class to an Interface that extends AspNetCore.MailKitMailer.Domain.IMailerContext
public interface ITestMailer:AspNetCore.MailKitMailer.Domain.IMailerContext
{
IMailerContextResult WelcomeMail(string username, string email);
}
public class TestMailer : MailerContextAbstract, ITestMailer
{
...
}
Now we create a view located in ~/Mailer-Views/TestMailer
called WelcomeMail.cshtml
Sending the Mail
Assuming we are using it inside an MvcController all we have to do is to inject the IMailClient
.
using AspNetCore.MailKitMailer.Domain;
using MailKitMailerExample.Mailer;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MailKitMailerExample.Controllers
{
[Route("test")]
public class TestController : Controller
{
private readonly IMailClient client;
public TestController(IMailClient client)
{
this.client = client;
}
[HttpGet("welcome")]
public IActionResult Welcome()
{
string username = "John.Doe";
string useremail = "john@example.com";
this.client.Send<ITestMailer>(x => x.WelcomeMail(username, useremail));
return View();
}
}
}
As we see we are injecting the mail client and calling our contex to prepare the message. Then we are sending it, in one line.
Default Values
Our contex can provide an load of default values. Lets assume our welcome mail should go also to "admin@example.com":
namespace MailKitMailerExample.Mailer
{
public class TestMailer : MailerContextAbstract, ITestMailer
{
public TestMailer() {
this.DefaultReceipients.Add(new EmailAddressModel("admin", "admin@localhost"));
}
public IMailerContextResult WelcomeMail(string username, string email)
{
return this.HtmlMail(new EmailAddressModel(username, email),
$"Welcome {username}!",
new WelcomeModel() { Username = username, Date = DateTime.Now });
}
}
}
In the contructor you see we are adding the admin@locahost address to DefaultReceipients
.
This will cause if we send an mail we will also send it to all addresses located in DefaultReceipients
.
Same for DefaultCCReceipients
for cc and DefaultBCCReceipients
for bcc.
Sending Attachments
Sending attachment is as easy as sending an default mail.
Lets create a new contex method for this in our TestMailer
:
public IMailerContextResult Test_Attachment(string attachmentPath)
{
return HtmlMail(
new EmailAddressModel("test", "test@localhost"),
"Test-Attachment",
null,
null,
x => x.Add(attachmentPath)
);
}
You see something different here. We have this anonymous function that adds an file path for some kind of collection. Thats our attachment collection. It will hold information of planned attachments and its content type. On send the mail client will resolve this and add it to the mail.
You can also download files to add as attachments. Just provide an type of "Uri
" then.
Second paramter in our x.Add method is the content type. So you can override the content type if youn want to.
Extract it to our interface and test it.
Auto-Registering Contexes
AspNetCore.MailKitMailer is able to register all mail contexes to services that match an certain criteria:
The class has to be public
The class exntends AspNetCore.MailKitMailer.Data.MailerContextAbstract
.
If you want to register it as interface your interface needs to also extend AspNetCore.MailKitMailer.Domain.IMailerContext
.
This all done your mail contex is automaically available via dependency injection.
Tag Helper
Ive created an tag helper based on the old approach of https://www.meziantou.net/inlining-a-stylesheet-using-a-taghelper-in-asp-net-core.htm
<mailer-inline-style href="css/site.css"></mailer-inline-style>
This call will load the file css/site.css file as inline style.
By default the base path is the Web-Root e.g. "wwwroot".
You can change this by setting use-content-root
to true
. If this cases it uses the main content root.
Caching The tag supports caching. It will cache if an memory cache is registered the result in the memory cache. If an distributed cache is registerted it will prefer this.
To force the use of memory cache you can set force-memory-cache
to true
.
Url Helper
AspNetCore.MailKitMailer comes with an UrlHelper to provide AbsoluteUrls for mail bodies.
Usage:
href="@Url.MailerAbsoluteAction("Index","Home")"
This will generate an absolute url to the action Index
of Controller Home
.
See https://github.com/nfMalde/AspNetCore.MailKitMailer/blob/main/src/AspNetCore.MailKitMailer/Helper/UrlHelper.cs for more info.
Examples
There is an fully working example .net core project located at https://github.com/nfMalde/AspNetCore.MailKitMailer/tree/main/examples/MailKitMailerExample. Feel free to download it and play arround. Also this project got a few integration tests where you can see all different type of usages.
Contribute / Donations
If you got any Ideas to improve my projects feel free to send an pull request.
If you like my work and want to support me (or want to buy me a coffee/beer) paypal donation are more than appreciated.
Changelog
Version | Changes |
---|---|
1.2.2 | Updated Dependecies for .NET 6 |
1.1.1 | Updated Changed Log for 1.1.x |
1.1.0 | Initial .NET 5 Release |
1.0.2 | Updated Examples |
1.0.1 | Updated Docs |
1.0.0 | Initial Release |
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net6.0
- HtmlAgilityPack (>= 1.11.42)
- MailKit (>= 3.2.0)
- Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation (>= 6.0.4)
- Microsoft.Extensions.Configuration (>= 6.0.1)
- Microsoft.Extensions.Configuration.Binder (>= 6.0.0)
- Microsoft.Extensions.Options (>= 6.0.0)
- Newtonsoft.Json (>= 13.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
* Updated dependencies
* Removed obsolete WebClient and added http client instead
* Fixed Attachment Builder for filedownload when no content type is set
* Attachment Builder now respects the Content-Disposition Header if no filename in url is found
* Created .NET 6 compiled version using updated dependencies