One configuration section, one call, and the mail is out the door.
English | 繁體中文 · Changelog · API Reference · NuGet
Notification mails. Nightly report mails. Verification mails. The kind of email an application sends, not a person. Ozakboy.Mail exists so that sending one takes an SmtpMailConfig section in appsettings.json and a single method call — no SMTP client lifetime to manage, no MIME tree to assemble, no TLS mode to guess.
✉ · · · ✈
using Ozakboy.Mail;
IMail mail = new Mail(configuration);
var receivers = new List<MailInfo> { new MailInfo("someone@example.com", "Someone") };
mail.SendMail(
receivers,
null, // CC
null, // attachments
"Your nightly report is ready",
"<p>The report finished at 03:00.</p>");The same thing, asynchronously, with cancellation:
IMailAsync mail = new Mail(configuration);
await mail.SendMailAsync(
receivers,
null,
null,
"Your nightly report is ready",
"<p>The report finished at 03:00.</p>",
true,
cancellationToken);With CC and an attachment:
var cc = new List<MailInfo> { new MailInfo("manager@example.com", "Manager") };
var attachments = new List<AttachmentsInfo>
{
new AttachmentsInfo
{
FileName = "report.pdf",
FileType = MediaTypeNames.Application.Pdf,
FileStream = File.OpenRead("report.pdf"),
},
};
await mail.SendMailAsync(receivers, cc, attachments, "Monthly report", "<p>Attached.</p>");The attachment streams are disposed for you once the send succeeds — see the stream ownership contract.
A small SMTP sending library with a deliberately narrow surface:
SendMail/SendMailAsync— multiple recipients, CC, attachments, HTML or plain-text bodies- Configuration from
appsettings.json, or straight from aVSmtpMailConfigobject when your settings come from environment variables - Two interfaces so you can inject either style:
IMail(sync) andIMailAsync(async)
And what it is not: no BCC, no templating engine, no queueing or retry layer, no mail-merge, no IMAP/POP. If you need those, use MailKit directly — that is what this library is built on.
MailKit underneath, not System.Net.Mail. The .NET built-in SmtpClient only speaks STARTTLS, so port 465 (implicit SSL) simply never worked — a classic afternoon lost to "my settings are right but nothing sends". Since 1.1.0 the transport is MailKit with SecureSocketOptions.Auto, which negotiates the right mode for 465, 587 and 25 without you telling it which.
Errors that tell you where to look. A failed send does not surface a raw socket error. It throws InvalidOperationException with the four things actually worth checking — network, host/port, firewall, credentials — with your configured host and port interpolated, and the original exception preserved as InnerException for your logs.
No learning curve to pay off. MailKit is excellent and correspondingly large: SmtpClient, MimeMessage, BodyBuilder, MimePart, ContentType, SecureSocketOptions. To send a notification mail you should not have to learn any of them. Here the vocabulary is MailInfo, AttachmentsInfo, and one method.
Sync is really sync. The synchronous path calls MailKit's synchronous API. There is no .Result or .Wait() hidden inside waiting to deadlock your UI or ASP.NET context.
dotnet add package Ozakboy.Mail1. Add the SMTP section to appsettings.json:
{
"SmtpMailConfig": {
"Host": "smtp.gmail.com",
"Port": 587,
"UserName": "your-email@gmail.com",
"Password": "your-app-password",
"Name": "Sender display name"
}
}Gmail requires an app password, not your account password. Port 587 (STARTTLS) and 465 (implicit SSL) both work.
Need the sender address to differ from the login account (AWS SES, unauthenticated relays)? Add the optional
"SenderAddress"field — new in 1.2.0. See Configuration.
2. Register it (ASP.NET Core):
builder.Services.AddScoped<IMail, Mail>();
builder.Services.AddScoped<IMailAsync, Mail>();Or build it by hand in a console app:
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
IMail mail = new Mail(configuration);Settings living in environment variables instead? Skip IConfiguration entirely:
IMailAsync mail = new Mail(new VSmtpMailConfig
{
Host = Environment.GetEnvironmentVariable("SMTP_HOST"),
Port = int.Parse(Environment.GetEnvironmentVariable("SMTP_PORT")),
UserName = Environment.GetEnvironmentVariable("SMTP_USER"),
Password = Environment.GetEnvironmentVariable("SMTP_PASSWORD"),
Name = "Sender display name",
});3. Send. That is the whole setup.
✈ · · · ✉
| Target framework | Supported |
|---|---|
| .NET 10.0 | ✅ |
| .NET 9.0 | ✅ |
| .NET 8.0 | ✅ |
| .NET Standard 2.1 | ✅ |
| .NET Standard 2.0 | ✅ |
.NET Standard 2.0 covers .NET Framework 4.6.1+, .NET Core 2.0+ and Mono/Xamarin/Unity.
Dependencies: MailKit, Microsoft.Extensions.Configuration.Abstractions, Microsoft.Extensions.Configuration.Binder.
Upgrading from 1.0.x? Nothing to change — see the migration guide.
| Getting Started | Install, configure, first mail — sync and async |
| Configuration | Every SmtpMailConfig field, environment variables, common mail providers |
| API Reference | Every public member, parameter and exception |
| Migration | 1.0.x → 1.1.0 |
| Changelog | Version history |
MIT.
