MailEngin 0.1.0

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

MailEngin .NET SDK

.NET NuGet License: MIT

The official .NET SDK for sending transactional email through MailEngin. It provides asynchronous APIs, nullable-aware request and response models, cancellation tokens, configurable timeouts, injectable HttpClient instances, and structured exceptions.

This package is for trusted server-side applications only. Never include a MailEngin API key in Blazor WebAssembly, MAUI client applications, desktop binaries, JavaScript, or other distributed client code.

Supported Targets

  • .NET Standard 2.0
  • .NET 8 or newer

Installation

dotnet add package MailEngin

Package Manager Console:

Install-Package MailEngin

Before You Send

  1. Verify a sending domain.
  2. Create an API key and save the full secret.
  3. Create and publish a Developer Template.
  4. Copy the template API name, such as welcome-email.

Store the key in your deployment platform's secret manager or environment:

MAILENGIN_API_KEY=re_your_full_secret_key

MailEngin displays the full key only once. A masked key cannot authenticate requests.

Quick Start

using MailEngin;

using var client = new MailEnginClient(
    Environment.GetEnvironmentVariable("MAILENGIN_API_KEY")
        ?? throw new InvalidOperationException("MAILENGIN_API_KEY is missing."));

var email = await client.Emails.SendAsync(new SendEmailRequest
{
    To = "user@example.com",
    FromEmail = "hello@yourdomain.com",
    TemplateName = "welcome-email",
    Variables = new Dictionary<string, object?>
    {
        ["first_name"] = "Asha",
    },
});

Console.WriteLine(email.Id);

The published template supplies the subject and HTML. Values in Variables replace matching template variables such as {{first_name}}.

Send One Email

var request = new SendEmailRequest
{
    To = "customer@example.com",
    FromEmail = "hello@yourdomain.com",
    TemplateName = "account-verification",
    Variables = new Dictionary<string, object?>
    {
        ["first_name"] = "Asha",
        ["verification_url"] = "https://yourapp.com/verify/token",
    },
    ReplyToMailEngin = true,
};

var email = await client.Emails.SendAsync(request, cancellationToken);
Console.WriteLine($"Queued email {email.Id} at {email.CreatedAt}");

Send request properties

Property Type Required Description
To string Yes Recipient email address.
TemplateName string? Recommended Published template API name or exact display name.
TemplateId string? No Legacy template identifier. Prefer TemplateName.
Variables IDictionary<string, object?>? No Values used to render template variables.
Subject string? Raw HTML only Template subject override, or required subject for raw HTML.
FromEmail string? Recommended Sender on a verified domain authorized for the API key.
Html string? Advanced Raw HTML used when no template is supplied.
ReplyToMailEngin bool? No Route recipient replies into the MailEngin inbox.

Exactly one content source is required: TemplateName, TemplateId, or Html. Raw HTML sends also require Subject.

Send Personalized Bulk Email

Bulk requests support up to 1,000 recipients. Request-level variables apply to every recipient; recipient variables take precedence.

var job = await client.Emails.SendBulkAsync(new SendBulkEmailRequest
{
    To = new List<BulkRecipient>
    {
        new("asha@example.com", new Dictionary<string, object?>
        {
            ["first_name"] = "Asha",
        }),
        new("ben@example.com", new Dictionary<string, object?>
        {
            ["first_name"] = "Ben",
        }),
    },
    FromEmail = "hello@yourdomain.com",
    TemplateName = "product-update",
    Variables = new Dictionary<string, object?>
    {
        ["product_name"] = "MailEngin",
    },
}, cancellationToken);

Console.WriteLine($"Queued {job.QueuedCount} recipients in job {job.JobId}");

For recipients without individual variables:

var job = await client.Emails.SendBulkAsync(new SendBulkEmailRequest
{
    To = new List<BulkRecipient>
    {
        new("a@example.com"),
        new("b@example.com"),
    },
    TemplateName = "maintenance-notice",
});

A successful bulk response confirms that recipients were queued. It is not a guarantee that every message was delivered.

Send Raw HTML

Published templates are recommended for reusable product email. For a one-off message, provide both Subject and Html:

var email = await client.Emails.SendAsync(new SendEmailRequest
{
    To = "user@example.com",
    FromEmail = "reports@yourdomain.com",
    Subject = "Your report is ready",
    Html = "<h1>Report ready</h1><p>You can download it now.</p>",
});

Cancellation

Both send methods accept a CancellationToken:

using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var email = await client.Emails.SendAsync(request, cancellation.Token);

Caller cancellation produces a MailEnginException with code request_aborted. Expiry of the SDK timeout produces request_timeout.

Sender Selection

MailEngin resolves the sender in this order:

  1. FromEmail supplied in the request.
  2. Sender saved in the published Developer Template.
  3. noreply@<authorized-domain> fallback.

The sender domain must be verified and authorized for the API key.

Error Handling

API, timeout, cancellation, malformed-response, and network failures throw MailEnginException:

try
{
    await client.Emails.SendAsync(request, cancellationToken);
}
catch (MailEnginException error)
{
    Console.Error.WriteLine(error.Message);
    Console.Error.WriteLine(error.Status);       // HTTP status, when available
    Console.Error.WriteLine(error.ErrorCode);    // Machine-readable error code
    Console.Error.WriteLine(error.RequestId);    // Include when contacting support
    Console.Error.WriteLine(error.RetryAfter);   // Seconds supplied with HTTP 429
    Console.Error.WriteLine(error.Body);         // Original response body
    Console.Error.WriteLine(error.IsRetryable);
}

IsRetryable is true for network errors, timeouts, HTTP 408, HTTP 429, and 5xx responses. The SDK never retries sends automatically because a retry could create a duplicate email until idempotency keys are supported.

Invalid local input throws ArgumentException before an API request is made.

Configuration

using var client = new MailEnginClient(
    apiKey: apiKey,
    baseUrl: "https://api.mailengin.app",
    timeout: TimeSpan.FromSeconds(15),
    httpClient: httpClient);
Constructor argument Default Description
apiKey None Full server-side MailEngin API key.
baseUrl https://api.mailengin.app Override for local, test, or dedicated environments.
timeout 30 seconds Maximum duration applied to each request.
httpClient New client Injectable shared or mocked HttpClient.

If you inject an HttpClient, your application owns it and the SDK will not dispose it. If the SDK creates the client, dispose MailEnginClient when the application scope ends.

ASP.NET Core Integration

Register one typed singleton and let IHttpClientFactory manage the HTTP transport:

builder.Services.AddHttpClient("MailEngin");
builder.Services.AddSingleton(serviceProvider =>
{
    var factory = serviceProvider.GetRequiredService<IHttpClientFactory>();
    var configuration = serviceProvider.GetRequiredService<IConfiguration>();
    var apiKey = configuration["MailEngin:ApiKey"]
        ?? throw new InvalidOperationException("MailEngin API key is missing.");

    return new MailEnginClient(apiKey, httpClient: factory.CreateClient("MailEngin"));
});

Back MailEngin:ApiKey with an environment variable or secret manager, not a committed settings file.

Testing

Inject an HttpClient backed by a custom HttpMessageHandler to return deterministic responses. The repository xUnit tests cover headers, field mapping, bulk limits, errors, and cancellation without requiring a real customer API key.

Development

dotnet restore
dotnet test -c Release
dotnet pack src/MailEngin/MailEngin.csproj -c Release -o artifacts

See CONTRIBUTING.md for contribution rules and PUBLISHING.md for maintainer release instructions.

Resources

License

Released under the MIT License. Copyright 2026 MailEngin.

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 is compatible.  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 was computed.  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

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
0.1.0 93 9/1/2026