CodeLogic.Mail
4.9.102
dotnet add package CodeLogic.Mail --version 4.9.102
NuGet\Install-Package CodeLogic.Mail -Version 4.9.102
<PackageReference Include="CodeLogic.Mail" Version="4.9.102" />
<PackageVersion Include="CodeLogic.Mail" Version="4.9.102" />
<PackageReference Include="CodeLogic.Mail" />
paket add CodeLogic.Mail --version 4.9.102
#r "nuget: CodeLogic.Mail, 4.9.102"
#:package CodeLogic.Mail@4.9.102
#addin nuget:?package=CodeLogic.Mail&version=4.9.102
#tool nuget:?package=CodeLogic.Mail&version=4.9.102
CodeLogic.Mail
SMTP sending and IMAP reading for CodeLogic 4 — with a built-in template engine, attachments, and RFC 2177 IDLE push notifications.
Compose messages with a fluent MailBuilder, send them over SMTP, render variable-substitution templates (conditionals, loops, and layouts), and read mailboxes over IMAP — including live IDLE push. Built on MailKit and MimeKit. Every fallible operation returns a MailResult / MailResult<T> carrying a categorised MailError instead of throwing on protocol, auth, or timeout errors.
Install
dotnet add package CodeLogic.Mail
Quick start
using CL.Mail;
await Libraries.LoadAsync<MailLibrary>();
await CodeLogic.ConfigureAsync();
await CodeLogic.StartAsync();
var mail = Libraries.Get<MailLibrary>();
// Compose with the fluent builder and send via SMTP.
var message = mail.CreateMessage()
.From("noreply@example.com", "My App")
.To("user@example.com")
.Subject("Welcome!")
.HtmlBody("<h1>Hello</h1><p>Welcome aboard.</p>")
.TextBody("Hello — welcome aboard.")
.Build();
MailResult result = await mail.Smtp.SendAsync(message);
if (!result.IsSuccess)
Console.WriteLine($"Send failed ({result.Error}): {result.ErrorMessage}");
Features
- SMTP sending — plain-text and/or HTML bodies, CC/BCC, attachments, custom headers, and message priority. A fresh connection is opened per send (no pooling).
- Fluent
MailBuilder—mail.CreateMessage()composes an immutableMailMessage;Build()throws if sender, recipients, subject, or a body are missing. - Template engine — JSON-backed templates with
{{var}}/${var}/{var}substitution (HTML-encoded in HTML bodies;{{{var}}}for trusted HTML),{{#if}}…{{#else}}…{{/if}}conditionals,{{#each}}…{{/each}}loops, and{{#section}}/ layout composition. Values are inserted once: placeholders inside a value are never expanded. - Templated send —
SendTemplatedAsyncrenders a template by id and sends it in one call. - IMAP reading — list folders, fetch and page messages, fetch by UID with attachments, search, move/copy/delete, and add/remove flags.
- IMAP IDLE — RFC 2177 push notifications via
StartIdleAsyncand theNewMailReceivedevent. - Result-based errors —
MailResult/MailResult<T>carryIsSuccess, a categorisedMailError, anErrorMessage, and aMessageId.
Configuration
Auto-generated on first run as config.mail.json. The Imap section is optional — omit it to disable IMAP entirely.
{
"Enabled": true,
"Smtp": {
"Host": "smtp.example.com",
"Port": 587,
"Username": "noreply@example.com",
"Password": "your-password-or-app-password",
"SecurityMode": "StartTls",
"TimeoutSeconds": 30
},
"Imap": {
"Host": "imap.example.com",
"Port": 993,
"Username": "inbox@example.com",
"Password": "your-password-or-app-password",
"SecurityMode": "SslTls",
"TimeoutSeconds": 30,
"EnableIdle": false,
"IdleRefreshMinutes": 25
},
"DefaultFromEmail": "noreply@example.com",
"DefaultFromName": "My App",
"TemplateDirectory": "templates"
}
| Setting | Default | Description |
|---|---|---|
Enabled |
true |
Master switch; when false the services aren't created and health reports disabled. |
Smtp.Host / Smtp.Port |
smtp.example.com / 587 |
SMTP server and port. |
Smtp.Username / Smtp.Password |
"" |
SMTP credentials (use an app password where required). |
Smtp.SecurityMode |
StartTls |
None, StartTls (STARTTLS, port 587), or SslTls (implicit TLS, port 465). |
Smtp.TimeoutSeconds |
30 |
SMTP connect/operation timeout. |
Imap |
null |
Optional; omit the whole section to disable IMAP. |
Imap.SecurityMode |
SslTls |
None, StartTls, or SslTls (implicit TLS, port 993). |
Imap.EnableIdle |
false |
Enable RFC 2177 IDLE push monitoring. |
Imap.IdleRefreshMinutes |
25 |
IDLE connection refresh interval (1–28; keep under 29). |
DefaultFromEmail / DefaultFromName |
null |
Fallback sender when a message omits From. |
TemplateDirectory |
templates |
Template folder; relative to the library data dir unless absolute. |
Changing config while running
With CodeLogic 4.9+, config.mail.json applies live when changed through Libraries.UpdateConfigAsync, Libraries.ReloadConfigAsync, or the config file watcher. Only what changed is rebuilt:
- SMTP settings:
mail.Smtpis replaced. Every send opens its own connection, so sends already running finish on the old settings. - Template directory:
mail.TemplateProviderandmail.TemplateEngineare replaced. - IMAP settings (added, changed or removed):
mail.Imapis replaced and the old connection is closed. Re-readmail.Imap— don't keep the old instance — and callStartIdleAsyncagain if you were idling. enabled: can be switched either way.
Other settings (default sender, ...) are read when used and need nothing rebuilt.
Documentation
Full guide: CL.Mail documentation
Requirements
- CodeLogic 4.9+ · .NET 10
- MailKit 4.x · MimeKit 4.x
License
MIT — see LICENSE.
| 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. |
NuGet packages (1)
Showing the top 1 NuGet packages that depend on CodeLogic.Mail:
| Package | Downloads |
|---|---|
|
CodeLogic.WebLogic
Web application toolkit for CodeLogic 4 — routing, templates, forms, an ordered security pipeline, auth flows and realtime. No third-party dependencies beyond CodeLogic.*. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.9.102 | 33 | 10/26/2026 |
| 4.9.98 | 229 | 10/25/2026 |
| 4.8.93 | 60 | 9/23/2026 |
| 4.8.87 | 62 | 9/13/2026 |
| 4.8.86 | 48 | 9/13/2026 |
| 4.8.85 | 52 | 9/12/2026 |
| 4.6.72 | 241 | 6/20/2026 |
| 4.6.69-preview | 61 | 6/20/2026 |
| 4.5.2 | 132 | 5/24/2026 |
| 4.5.2-preview.68 | 86 | 6/20/2026 |
| 4.5.1 | 182 | 5/24/2026 |
| 4.5.1-preview.56 | 113 | 5/24/2026 |
| 4.4.2-preview.53 | 80 | 5/24/2026 |
| 4.4.1 | 130 | 5/24/2026 |
| 4.0.5 | 124 | 5/15/2026 |
| 4.0.4 | 135 | 5/9/2026 |
| 4.0.3 | 138 | 5/9/2026 |
| 3.3.1 | 638 | 4/18/2026 |
| 3.3.0 | 136 | 4/18/2026 |
| 3.2.11 | 139 | 4/18/2026 |
# CL.Mail — Changelog
All notable changes to **CodeLogic.Mail** are documented here. Versions follow
[Semantic Versioning](https://semver.org/).
## 2026-10-27
### Security
- **HTML bodies encode substituted values.** `SimpleTemplateEngine` inserted every value into
`HtmlBody` as-is, so a user-supplied value (a user name, a browser description) could inject
markup or links into an e-mail. In `HtmlBody` and HTML layouts, `{{var}}`, `${var}` and `{var}`
are now HTML-encoded. Subjects and text bodies are unchanged.
- **Values are inserted once.** Substitution ran the three placeholder syntaxes one after another,
and loop output was substituted again by the outer pass, so a value containing `${other}` or
`{other}` was expanded: user text could pull other variables (links, tokens) into the message.
All syntaxes are now replaced in a single pass and nothing inside a value is expanded.
### Added
- **`{{{var}}}`** inserts a value without encoding, for values that are trusted HTML.
### Fixed
- **Text layouts get the text sections.** With a layout, the text layout was rendered with the
child's *HTML* sections (including `body`). Text and HTML layouts now each receive their own
sections, and a child's section wins over a variable of the same name.
### Upgrade notes
- Templates that pass ready-made HTML in a variable must switch that placeholder to `{{{var}}}`.
## 2026-10-24
### Added
- **Live config changes** (requires CodeLogic 4.9+). `MailLibrary` implements `IConfigReloadable`: a
change to `config.mail.json` made through `Libraries.UpdateConfigAsync`, `Libraries.ReloadConfigAsync`
or the config file watcher is applied without a restart, rebuilding only what changed. Changed SMTP
settings replace `Smtp` (sends in flight finish on the old settings); a changed template directory
replaces `TemplateProvider`/`TemplateEngine`; changed IMAP settings replace `Imap` and close the old
connection (re-read `Imap` and restart IDLE). `Enabled` can be switched either way.
## 2026-09-12
### Changed
- Unified the version line with the CodeLogic framework on **4.8.x**. Every official
library and the framework now share one `major.minor`, so a given `4.8.<patch>`
means the same generation across all packages.
- `version.txt` moved from `4.6` to `4.8`. The patch component remains the CI run
number, composed at pack time; `AssemblyVersion` stays pinned at `Major.Minor.0.0`
(now `4.8.0.0`) so every patch in the line loads interchangeably.
## 2026-06-20
### Documentation
- Full rewrite of the README and the multi-page docs set to the CodeLogic.Libs
house style. The README is now concise, Markdown-only, and NuGet-safe; the
guide is split into **Overview & Sending** (`docs/libs/mail/index.md`) and
**Receiving & Templates** (`docs/libs/mail/receiving-templates.md`), with the
old `docs/libs/mail.md` reduced to a redirect stub and the docs navigation
updated accordingly. No API changes.
## [4.5.1] — 2026-06-20
### Documentation
- Rewrote the README and the Mail & Templates guide to match the current public
API. The previous docs described members that no longer exist (`EmailMessage`,
`EmailAttachment`, `ReplyTo`, `RenderTemplateAsync`, `ReadInboxAsync`,
`ImapFilter`, `MarkAsReadAsync`, the `SendAsync(from:, to:, …)` /
`SendTemplateAsync` overloads, and the `UseSsl` / `FromAddress` config keys).
- Documented the real surface: the fluent `MailBuilder` (`CreateMessage()`),
`SmtpService.SendAsync(MailMessage)`, `MailLibrary.SendTemplatedAsync`, the
`MailResult` / `MailError` result model, and the JSON-backed template system
(`MailTemplate`, `IMailTemplateProvider`, `IMailTemplateEngine`).
- Documented previously undocumented features: template conditionals
(`{{#if}}`/`{{#else}}`), loops (`{{#each}}`), sections and layouts; the
`${var}` / `{var}` placeholder syntaxes; the full IMAP API (fetch/page, fetch
by UID, search via `ImapSearchCriteria`, move/copy/delete, flag operations,
folder management); and RFC 2177 IMAP IDLE push (`StartIdleAsync` /
`NewMailReceived`) with its `EnableIdle` / `IdleRefreshMinutes` config keys.
- Corrected the documented config schema and `SecurityMode` values
(`None` / `StartTls` / `SslTls`).
## [4.5.0] — 2026-05-24
### Changed
- **Unified versioning.** All CodeLogic.Libs now share a single version line
controlled by `version.txt` in the repo root. This is a version alignment
release — no functional changes to this library.
## [4.0.4] — 2026-04-16
### Changed
- README + manifest refresh for the v4 baseline. No functional changes vs 4.0.3.
- `LibraryManifest.Version` now reads from assembly metadata.
## [4.0.2] — 2026-04-09
### Changed
- Annotated mail configuration with `[ConfigField]` for the admin UI surface.
- Aligned with the v4 baseline across all libraries.
### Fixed
- Resolved null-reference warnings in `ImapService`.
## [4.0.0] — 2026-04-09
Major rewrite. Republished as v4.0.0 to reset the version line under the
unified v4 baseline. SMTP / IMAP services + a CodeLogic-native template
provider.
### Notes
- Earlier history is retained in the
[git log](https://github.com/zyntal-com/CodeLogic.Libs/commits/main/CL.Mail).