CosmoMail 1.1.0
See the version list below for details.
dotnet add package CosmoMail --version 1.1.0
NuGet\Install-Package CosmoMail -Version 1.1.0
<PackageReference Include="CosmoMail" Version="1.1.0" />
<PackageVersion Include="CosmoMail" Version="1.1.0" />
<PackageReference Include="CosmoMail" />
paket add CosmoMail --version 1.1.0
#r "nuget: CosmoMail, 1.1.0"
#:package CosmoMail@1.1.0
#addin nuget:?package=CosmoMail&version=1.1.0
#tool nuget:?package=CosmoMail&version=1.1.0
CosmoMail
CosmoMail is a lightweight .NET 10 SMTP client and MIME generation library built around direct socket transport, fluent message composition, and Fluid-based templating.
It supports plain text and HTML bodies, attachments, inline images, STARTTLS, SMTP authentication, reusable message/template objects for high-throughput send paths, and lightweight IMAP inbox access.
Features
- Direct SMTP transport over sockets and
System.IO.Pipelines - Fluent message builder for sender, recipients, headers, priority, text, and HTML
- MIME generation for
multipart/alternative,multipart/mixed, andmultipart/related - Attachments and inline images with base64 encoding
- STARTTLS and
PLAIN/LOGINauthentication helpers - Lightweight IMAP client for inbox login, mailbox selection, and header listing
Fluidtemplate support for reusable subject, text, and HTML rendering- UTF-8-safe header/body handling and structural response validation
- Cached payload and envelope reuse for repeated sends of the same message
Usage
Simple Send
using CosmoMail;
var message = new SmtpMessage()
.SetFrom("admin@company.com", "System Admin")
.AddTo("vip@customer.com", "Important User")
.AddCc("logs@company.com")
.SetHighPriority()
.SetSubject("Daily Analytics Snapshot")
.SetBody("This is your raw system fallback output.")
.SetHtmlBody("<h1>Daily Snapshot</h1><p>Welcome back!</p>");
await using var client = new CosmoMailClient("localhost", debug: true);
await client.ConnectAsync("mail.yourserver.com", 587);
await client.EhloAsync();
await client.StartTlsAsync("mail.yourserver.com");
await client.EhloAsync(); // Re-announce capabilities inside the TLS boundary
await client.AuthenticateAsync("LOGIN", "username", "secure_password");
await client.SendMessageAsync(message);
await client.QuitAsync();
Management UI
CosmoMail.Management is a small server-rendered Blazor UI built on CosmoApiServer.Core. It provides:
- SMTP settings and message composition in one browser form
- saved SMTP profiles in SQLite
- recent send history in SQLite
- attachment path support for files available on the server
Run it with:
dotnet run --project CosmoMail.Management/CosmoMail.Management.csproj
Default URL:
http://localhost:9181
Optional environment variables:
COSMOMAIL_UI_PORT: UI listen port, default9181COSMOMAIL_UI_DB: SQLite path or fullData Source=...connection stringCOSMOMAIL_SERVERCOSMOMAIL_PORTCOSMOMAIL_CLIENT_HOSTNAMECOSMOMAIL_USERNAMECOSMOMAIL_PASSWORDCOSMOMAIL_FROMCOSMOMAIL_RECIPIENT
Templates, Inline Images, and Attachments
using CosmoMail;
var template = new SmtpTemplate(
subject: "Hello {{ Name }}! Your bill is ready.",
html: @"
<h1>Hey {{ Name }}!</h1>
<p>Attached is your formal receipt generated at {{ Time }}.</p>
<img src='cid:system-logo' alt='Company Logo' />"
);
var message = await template.RenderAsync(new {
Name = "John",
Time = DateTime.Now.ToString("F", System.Globalization.CultureInfo.InvariantCulture)
});
message.SetFrom("billing@company.com", "Billing Dept")
.AddTo("john.doe@company.com", "John Doe");
byte[] logoBytes = File.ReadAllBytes("logo.jpg");
message.WithInlineImage("system-logo", logoBytes, "image/jpeg");
byte[] pdfBytes = File.ReadAllBytes("receipt.pdf");
message.WithAttachment("receipt_2026.pdf", pdfBytes, "application/pdf");
// Transmit via `SendMessageAsync(message)`...
IMAP Inbox Access
using CosmoMail;
await using var imap = new CosmoImapClient("localhost", debug: false);
await imap.ConnectAsync("mail.yourserver.com", 143);
await imap.StartTlsAsync("mail.yourserver.com");
await imap.LoginAsync("username", "secure_password");
var mailbox = await imap.SelectMailboxAsync("INBOX");
var messages = await imap.ListMessageSummariesAsync(25);
foreach (var message in messages)
{
Console.WriteLine($"{message.Date:u} {message.From} {message.Subject}");
}
await imap.LogoutAsync();
Testing & Confidence
CosmoMail.Tests uses a mock TcpListener-based SMTP server to validate transport commands, response handling, UTF-8-safe payload generation, MIME structure, and failure paths.
The current suite contains 37 xUnit tests.
dotnet test
Benchmarks
CosmoMail.Benchmarks compares CosmoMailClient against MailKit for the same local SMTP send flow using an in-process fake SMTP server.
dotnet run -c Release --project CosmoMail.Benchmarks/CosmoMail.Benchmarks.csproj
For a fast in-process comparison without the full BenchmarkDotNet run:
dotnet run -c Release --project CosmoMail.Benchmarks/CosmoMail.Benchmarks.csproj -- --quick
The benchmark project currently covers three scenarios:
SimpleText: one plain-text message on a fresh connectionRichMime: HTML + text + inline image + attachmentsBurst10: ten messages on one reused connection
Each scenario measures a full SMTP send flow:
ConnectAsync/ConnectAsyncEHLOSendMessageAsync/SendAsyncQUIT/DisconnectAsync
Current stable BenchmarkDotNet results on this machine:
| Scenario | CosmoMail | MailKit |
|---|---|---|
SimpleText |
443.8 us, 18.01 KB |
457.5 us, 44.31 KB |
RichMime |
826.8 us, 408.58 KB |
1,577.0 us, 571.58 KB |
Burst10 |
2,297.0 us, 57.96 KB |
2,669.1 us, 188.67 KB |
Latest generated reports:
BenchmarkDotNet.Artifacts/results/SmtpSendBenchmarks-report-github.mdBenchmarkDotNet.Artifacts/results/SmtpSendBenchmarks-report.csvBenchmarkDotNet.Artifacts/results/SmtpSendBenchmarks-report.html
Performance Notes
The current implementation includes a few transport and MIME-path optimizations that materially affect the benchmark results:
- Cached UTF-8 wire payloads for repeated sends of the same
SmtpMessage - Cached SMTP envelope commands (
MAIL FROMandRCPT TO) for repeated sends - Direct
PipeWritercommand writes to avoid extra command-string encoding allocations - Simple-text fast path for non-multipart messages
- Direct base64 appends into the final MIME builder instead of allocating intermediate base64 strings for each MIME part
These changes matter most for:
SimpleText, where transport overhead dominatesRichMime, where MIME serialization and allocation pressure dominateBurst10, where reusing the same message across one SMTP session highlights payload and envelope caching
| Product | Versions 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. |
-
net10.0
- Cosmo.Transport (>= 1.0.2)
- Fluid.Core (>= 2.31.0)
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.8 | 82 | 6/17/2026 |
| 2.0.7 | 84 | 6/17/2026 |
| 2.0.4 | 97 | 5/24/2026 |
| 2.0.3 | 95 | 5/24/2026 |
| 2.0.2 | 94 | 5/23/2026 |
| 2.0.1 | 97 | 5/23/2026 |
| 2.0.0 | 94 | 5/23/2026 |
| 1.1.7 | 177 | 4/25/2026 |
| 1.1.6 | 110 | 4/25/2026 |
| 1.1.5 | 133 | 4/23/2026 |
| 1.1.4 | 118 | 4/23/2026 |
| 1.1.3 | 117 | 4/23/2026 |
| 1.1.2 | 118 | 4/14/2026 |
| 1.1.1 | 104 | 4/14/2026 |
| 1.1.0 | 118 | 4/10/2026 |