TwoRivers.Emailing 2.0.0-beta.8

This is a prerelease version of TwoRivers.Emailing.
dotnet add package TwoRivers.Emailing --version 2.0.0-beta.8
                    
NuGet\Install-Package TwoRivers.Emailing -Version 2.0.0-beta.8
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TwoRivers.Emailing" Version="2.0.0-beta.8" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TwoRivers.Emailing" Version="2.0.0-beta.8" />
                    
Directory.Packages.props
<PackageReference Include="TwoRivers.Emailing" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add TwoRivers.Emailing --version 2.0.0-beta.8
                    
#r "nuget: TwoRivers.Emailing, 2.0.0-beta.8"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package TwoRivers.Emailing@2.0.0-beta.8
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=TwoRivers.Emailing&version=2.0.0-beta.8&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=TwoRivers.Emailing&version=2.0.0-beta.8&prerelease
                    
Install as a Cake Tool

TwoRivers.Emailing

Provides strongly-typed Email and EmailAddress value objects, email validation, and a fluent MailMessageBuilder for composing emails. Defines an IEmailSender interface for sending email messages. Designed to be used with dependency injection and can be easily mocked for testing.

Installation

You can install the TwoRivers.Emailing package via NuGet Package Manager Console:

Install-Package TwoRivers.Emailing

Or via .NET CLI:

dotnet add package TwoRivers.Emailing

Features

Value Objects

  • Email: Strongly-typed email address value object
  • EmailAddress: Combines display name and email address (compatible with System.Net.Mail.MailAddress)

Email Validation

Multiple validation strategies:

  • MailAddressEmailValidator: Uses .NET's built-in MailAddress parsing
  • W3CEmailValidator: Validates against W3C email specification
  • StrictEmailValidator: Strict validation with additional rules
  • PatternEmailValidator: Regex-based validation
  • ParsingEmailValidator: Configurable parsing validator

MailMessageBuilder

Fluent API for building email messages with:

  • Markdown-to-HTML rendering
  • Multiple recipients (To, CC, BCC)
  • Priority and importance settings
  • Attachments
  • Plain text and HTML bodies
  • Integration with ClaimsPrincipal for user emails

FluentValidation Integration

  • EmailAddressPropertyValidator: Validates email properties in FluentValidation rules

Usage

using TwoRivers.Emailing;

public class EmailService
{
	private readonly MailMessageBuilder _builder;
	private readonly IEmailSender _sender;

	public EmailService(MailMessageBuilder builder, IEmailSender sender)
	{
		_builder = builder;
		_sender = sender;
	}

	public async Task SendWelcomeEmailAsync(ClaimsPrincipal user)
	{
		var message = _builder
			.SendFrom("Support", "support@example.com")
			.To(user)  // Automatically extracts name and email from claims
			.WithSubject("Welcome!")
			.WithPriority(MailPriority.High)
			.AppendLine("# Welcome to Our Service")
			.AppendLine()
			.AppendLine("We are excited to have you on board!")
			.AppendLine()
			.Append("Get started by visiting your [dashboard](https://example.com/dashboard).")
			.Build();

		await _sender.SendAsync(message);
	}
}

Implementing IEmailSender

To use the TwoRivers.Emailing package, create an implementation of the IEmailSender interface to send emails. Here's an example using SMTP:

using System.Net.Mail;
using TwoRivers.Emailing;

public class SmtpEmailSender : IEmailSender
{
	private readonly SmtpClient _smtpClient;

	public SmtpEmailSender(SmtpClient smtpClient)
	{
		_smtpClient = smtpClient;
	}

	public async Task SendAsync(MailMessage message, CancellationToken cancellationToken = default)
	{
		await _smtpClient.SendMailAsync(message, cancellationToken);
	}
}

Email Validation

using TwoRivers.Emailing;

public class RegistrationService
{
	private readonly IEmailValidator _validator;

	public RegistrationService(IEmailValidator validator)
	{
		_validator = validator;
	}

	public Boolean IsValidEmail(String email)
	{
		return _validator.IsValid(email);
	}
}

Dependency Injection Setup

using Microsoft.Extensions.DependencyInjection;
using TwoRivers.Emailing;

// Configure email options
services.Configure<EmailOptions>(options =>
{
	options.DefaultFromAddress = "noreply@example.com";
	options.DefaultFromName = "Example Service";
});

// Register validators
services.AddSingleton<IEmailValidator, W3CEmailValidator>();

// Register builder (scoped for per-request isolation)
services.AddScoped<MailMessageBuilder>();

// Register email sender
services.AddSingleton<IEmailSender, SmtpEmailSender>();

// Configure SMTP client
services.AddSingleton<SmtpClient>(sp => new SmtpClient
{
	Host = "smtp.example.com",
	Port = 587,
	EnableSsl = true,
	Credentials = new NetworkCredential("username", "password")
});

FluentValidation Integration

using FluentValidation;
using TwoRivers.Emailing;

public class UserRegistrationRequest
{
	public String Email { get; set; }
	public String Name { get; set; }
}

public class UserRegistrationValidator : AbstractValidator<UserRegistrationRequest>
{
	public UserRegistrationValidator()
	{
		RuleFor(x => x.Email)
			.NotEmpty()
			.SetValidator(new EmailAddressPropertyValidator());
	}
}

Best Practices

Use MailMessageBuilder

The MailMessageBuilder provides a fluent API and handles common tasks like markdown rendering:

// Good - fluent and readable
var message = builder
	.To("John Doe", "john@example.com")
	.WithSubject("Invoice #12345")
	.AppendLine("## Invoice Details")
	.Build();

// Avoid - manual construction
var message = new MailMessage();
message.To.Add(new MailAddress("john@example.com", "John Doe"));
message.Subject = "Invoice #12345";
message.Body = "<h2>Invoice Details</h2>";
message.IsBodyHtml = true;

Leverage Value Objects

Use Email and EmailAddress types instead of strings:

// Good - strongly typed
public void SendNotification(EmailAddress recipient)
{
	// Type safety ensures valid email addresses
}

// Avoid - stringly typed
public void SendNotification(String recipient)
{
	// No compile-time guarantee of validity
}

Choose the Right Validator

Different validators for different needs:

// Strict validation for user registration
services.AddSingleton<IEmailValidator, StrictEmailValidator>();

// Lenient validation for email imports
services.AddSingleton<IEmailValidator, MailAddressEmailValidator>();

// W3C-compliant validation
services.AddSingleton<IEmailValidator, W3CEmailValidator>();

License

This project is licensed under the MIT License. See the LICENSE file for details.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0-beta.8 72 3/5/2026
2.0.0-beta.7 63 3/5/2026
2.0.0-beta.6 62 3/5/2026
2.0.0-beta.5 60 3/4/2026
2.0.0-beta.4 61 3/4/2026
2.0.0-beta.3 59 3/3/2026
2.0.0-beta.2 71 3/3/2026
2.0.0-beta.1 59 3/3/2026
2.0.0-beta.0 67 3/3/2026
1.1.6 118 2/26/2026
1.1.5 105 2/25/2026
1.1.4 107 2/22/2026
1.1.3 108 2/22/2026
1.1.2 109 2/22/2026
1.1.1 117 2/22/2026
1.1.0 113 2/22/2026
1.0.0 140 2/17/2026
Loading failed