MailForge 0.1.0

dotnet add package MailForge --version 0.1.0
                    
NuGet\Install-Package MailForge -Version 0.1.0
                    
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="MailForge" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MailForge" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="MailForge" />
                    
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 MailForge --version 0.1.0
                    
#r "nuget: MailForge, 0.1.0"
                    
#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 MailForge@0.1.0
                    
#: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=MailForge&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=MailForge&version=0.1.0
                    
Install as a Cake Tool

MailForge — Transactional Communication for .NET

CI NuGet Version .NET License

MailForge is a unified, layered transactional communication ecosystem for .NET applications. It bridges the gap between lightweight email libraries and large third-party email providers by offering a provider-agnostic framework, a local developer studio, and a self-hosted gateway server.

The developer experience goal: a strongly typed, production-ready transactional email after installing a single package with minimal configuration.

await emailSender.SendAsync(new WelcomeEmail(userModel));

Guiding principle: Provider-agnostic by design. Business logic never couples to a specific sending service.

Why MailForge?

Sending transactional email in .NET usually means choosing between low-level plumbing and vendor lock-in — and repeating the same boilerplate every time. Raw SMTP libraries make you hand-assemble messages, templates, retries, and logging. Vendor SDKs work well but only for that one vendor, so swapping providers rewrites your email classes. MailForge fills that gap: one strongly typed programming model, a real delivery pipeline, and failover across providers — without tying your business logic to any single service.

MailKit / SmtpClient Vendor SDKs (Resend, SendGrid, SES) FluentEmail MailForge
Typed emails (Email<TModel>)
Razor + inline templates add-on
Auto plain-text generation
Delivery pipeline (validation, logging, retries, audit)
Multi-provider failover with precedence
Provider capability contracts
Swap providers without changing email classes ~
Zero-setup testing (FakeEmailProvider)
DI-first registration

How It Works

MailForge is structured into four progressive layers that evolve without architectural rewrites:

┌─────────────────────────────────────────────────────────┐
│                      Developer App                      │
└────────────────────────────┬────────────────────────────┘
                             ▼
┌─────────────────────────────────────────────────────────┐
│              Layer 1: MailForge Framework               │
│                 MailForge (core)                        │
└────────────────────────────┬────────────────────────────┘
                             │
       ┌─────────────────────┼─────────────────────┐
       ▼                     ▼                     ▼
┌───────────────┐     ┌───────────────┐     ┌───────────────┐
│    Layer 2    │     │    Layer 3    │     │    Layer 4    │
│   Providers   │     │ MailForge     │     │ MailForge     │
│ SMTP · Resend │     │ Studio        │     │ Gateway       │
│   · AmazonSES │     │ (Local Dev)   │     │ REST API &    │
│               │     │               │     │ Failover Queue│
└───────┬───────┘     └───────────────┘     └───────┬───────┘
        │                                           │
        ▼                                           ▼
    Internet                                  Delivery Queue
  1. Layer 1 — Core Framework (MailForge): Provider-agnostic contracts plus the developer programming model: typed emails, pipeline, validation, middleware, template rendering, and multi-provider failover with precedence (.NET Standard 2.0 compatible).
  2. Layer 2 — Provider SDK (MailForge.Smtp, MailForge.Resend, MailForge.AmazonSES): Connectors handling authentication, external API communication, and delivery responses.
  3. Layer 3 — Local Studio (MailForge.Studio): ASP.NET Core MVC + HTMX + Bootstrap web companion for local testing, email inspection, live preview, and message replay.
  4. Layer 4 — Gateway (MailForge.Server): Self-hosted service exposing the failover engine over REST with an async delivery queue and normalized webhooks.

Packages

Package Description
MailForge Core framework + contracts: IEmailProvider, IEmailSender, EmailMessage, typed emails, middleware pipeline, validation, Razor/inline rendering, and DI integration
MailForge.Smtp SMTP provider adapter for routing messages to any standard SMTP server
MailForge.Resend Resend API provider adapter
MailForge.AmazonSES Amazon Simple Email Service provider adapter

Installation

dotnet add package MailForge
dotnet add package MailForge.Smtp
dotnet add package MailForge.Resend
dotnet add package MailForge.AmazonSES

Quick Start

Configure the framework once at startup, then send strongly typed emails:

services.AddMailForge(builder => builder
    .UseProvider(new SmtpEmailProvider(new SmtpOptions { Host = "smtp.example.com", Port = 587 }))
    .UseDefaultFrom("noreply@example.com")
    .RegisterTemplate("welcome", "<h1>Welcome @Model.Name</h1>"));

Define a typed email:

public sealed class WelcomeEmail : Email<WelcomeModel>
{
    public WelcomeEmail(WelcomeModel model) : base(model)
    {
        AddTo("user@example.com");
        SetSubject("Welcome {{Name}}!");
        UseTemplate("welcome"); // or SetHtml("...") for an inline template
        AddTag("purpose", "welcome");
    }
}

Send it:

var sender = services.GetRequiredService<IEmailSender>();
var result = await sender.SendAsync(new WelcomeEmail(new WelcomeModel("Jane")));

Delivery is validated, logged, audited, and retried on transient failures through the middleware pipeline before reaching the configured provider. For development and tests, omit UseProvider to send through the in-memory FakeEmailProvider.

Providers

Each provider ships in its own package and is registered on the builder the same way; swap providers without touching your email classes.

SMTP

using MailForge.Smtp;

services.AddMailForge(builder => builder.UseProvider(new SmtpEmailProvider(new SmtpOptions
{
    Host = "smtp.example.com",
    Port = 587,
    Username = "user@example.com",
    Password = "password"
})));

Routes through any standard SMTP server, with optional TLS (implicit or STARTTLS) and authentication.

Resend

using MailForge.Resend;

services.AddMailForge(builder => builder.UseProvider(new ResendEmailProvider(new ResendOptions
{
    ApiKey = "re_..."
})));

Amazon SES

using MailForge.AmazonSES;

services.AddMailForge(builder => builder.UseProvider(new AmazonSesEmailProvider(new AmazonSesOptions
{
    Region = "us-east-1",
    AccessKey = "AKIA...",
    SecretKey = "..."
})));

When AccessKey/SecretKey are omitted, the AWS SDK default credential chain is used.

Failover

A FailoverEmailProvider tries a precedence-ordered chain of providers until one succeeds, so a transient outage at one provider does not lose the message. Providers are listed first = tried first.

using MailForge.Smtp;
using MailForge.Resend;

services.AddMailForge(builder => builder
    .UseDefaultFrom("noreply@example.com")
    .UseFailover(
        new SmtpEmailProvider(new SmtpOptions { Host = "smtp.example.com", Port = 587 }),
        new ResendEmailProvider(new ResendOptions { ApiKey = "re_..." })));

By default each route fails over only on transient failures (FailoverPolicy.TransientOnly) with a single attempt. To control behavior per provider, use routes:

builder.UseFailover(
    new ProviderFailoverRoute(new SmtpEmailProvider(new SmtpOptions { Host = "smtp.example.com" })),
    new ProviderFailoverRoute(new ResendEmailProvider(new ResendOptions { ApiKey = "re_..." }),
        FailoverPolicy.AnyFailure, maxAttempts: 2));
  • FailoverPolicy.TransientOnly — fails over on timeouts, rate limits, and temporary errors; permanent failures and rejections surface as-is.
  • FailoverPolicy.AnyFailure — fails over on any failure, including permanent exceptions and provider rejections.
  • maxAttempts — attempts allowed on the same provider before failing over (minimum 1).

When every route fails, the provider throws an EmailException whose IsTransient is true if any failure was retryable. On success, ProviderDeliveryResult.Details records which provider delivered the message.

Live Testing

The sample console app includes live integration checks that send a real message through a provider. They are handy for verifying a provider against smtp4dev or a real service before relying on it in production.

# SMTP (smtp4dev on localhost:25, or any SMTP server)
dotnet run --project MailForge.Console -- live-smtp [host] [port] [to]

# Resend (API key as argument or RESEND_API_KEY)
dotnet run --project MailForge.Console -- live-resend [apiKey] [to]

# Amazon SES (region as argument or AWS_REGION; credentials from the default AWS chain)
dotnet run --project MailForge.Console -- live-ses [region] [to]

Environment variables honored by the live tests:

Variable Purpose
RESEND_API_KEY Resend API key (also accepted as an argument)
AWS_REGION SES region (also accepted as an argument)
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY SES credentials
LIVE_FROM Sender address (default sender@example.com)
LIVE_TO Recipient address (default recipient@example.com)

Repository Layout

MailForge/              Layer 1 core framework + contracts (typed emails, pipeline, DI)
MailForge.Smtp/         Layer 2 SMTP provider
MailForge.Resend/       Layer 2 Resend provider
MailForge.AmazonSES/    Layer 2 Amazon SES provider
MailForge.Tests/        xUnit test suite
MailForge.Console/      Sample console application

Supported Frameworks

  • .NET 10+: Optimized for high-performance runtimes and modern C# idioms.
  • .NET Standard 2.0: Broad compatibility across .NET 5+, .NET Core 2.0+, and .NET Framework 4.6.1+.

License

Apache License 2.0. See LICENSE.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  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.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on MailForge:

Package Downloads
MailForge.AmazonSES

MailForge.AmazonSES is a provider adapter for the MailForge transactional communication ecosystem. Delivers MailForge messages through the Amazon Simple Email Service API.

MailForge.Resend

MailForge.Resend is a provider adapter for the MailForge transactional communication ecosystem. Delivers MailForge messages through the Resend email API.

MailForge.Smtp

MailForge.Smtp is a provider adapter for the MailForge transactional communication ecosystem. Routes MailForge messages to any standard SMTP server for delivery.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0 50 8/4/2026

Phase 1 framework MVP: typed Email<TModel>, Razor and inline template rendering, auto plain-text generation, middleware pipeline (logging, retries, auditing), validation, FakeEmailProvider, and services.AddMailForge(...) DI integration.