HtmlForgeX.Email
1.8.0
dotnet add package HtmlForgeX.Email --version 1.8.0
NuGet\Install-Package HtmlForgeX.Email -Version 1.8.0
<PackageReference Include="HtmlForgeX.Email" Version="1.8.0" />
<PackageVersion Include="HtmlForgeX.Email" Version="1.8.0" />
<PackageReference Include="HtmlForgeX.Email" />
paket add HtmlForgeX.Email --version 1.8.0
#r "nuget: HtmlForgeX.Email, 1.8.0"
#:package HtmlForgeX.Email@1.8.0
#addin nuget:?package=HtmlForgeX.Email&version=1.8.0
#tool nuget:?package=HtmlForgeX.Email&version=1.8.0
HtmlForgeX.Email
Typed, client-conscious HTML emails in C#, without requiring HTML or CSS in application code.
HtmlForgeX.Email is built for the reality of email rendering:
- Tables + inline styles for predictable layout (especially Outlook).
- Typed components (classes/enums/fluent methods) instead of raw HTML/CSS.
- No runtime NuGet dependencies in the shipped package.
- Opt-in dark-mode support via stable
hfx-*hooks and theme tokens. - Bounded dependency-free image processing, including managed PNG/JPEG resize and compression before CID or Base64 embedding.
- Transport-neutral output for MIME libraries and mail APIs (multi-targets
netstandard2.0,net472,net8.0+).
Quick start
using HtmlForgeX.Email;
var email = new Email()
.WithSubject("Welcome to the product")
.WithLanguage("en")
.WithThemeMode(EmailThemeMode.Auto) // Light/Dark/Auto
.ConfigureLayout(maxWidth: "680px") // Container width & padding
.WithAccentColor("#4f46e5", "#a5b4fc"); // Brand accent (light/dark)
email.Head.AddTitle("Welcome - HtmlForgeX.Email");
email.Body.PreheaderText = "Welcome to the product!";
email.Body.EmailBox(box => {
box.EmailHero(hero => hero
.WithIcon("👋")
.WithEyebrow("WELCOME")
.WithTitle("Thanks for signing up")
.WithSubtitle("Everything here is built from typed components."));
box.EmailAlert(alert => {
alert.Type = EmailAlertType.Info;
alert.Title = "No HTML/CSS needed";
alert.Message = "Compose emails with C# objects; HtmlForgeX.Email renders the email-safe markup.";
});
box.EmailButtonGroup(group => {
group.AddButton("Get started", "https://example.com/start", EmailButtonStyle.Primary);
group.AddButton("Docs", "https://example.com/docs", EmailButtonStyle.Secondary);
});
});
var result = await email.RenderAsync(); // HTML, plain text, CID resources, attachments, diagnostics
var html = result.Html;
var plainText = result.PlainText;
Render results & diagnostics
Render() / RenderAsync() now return an EmailRenderResult with:
HtmlPlainText,Subject,Preheader,Language, andTextDirectionInlineResourcesformultipart/relatedCID partsAttachments, including correctly described ICS/vCard payloadsEstimatedSizeBytesDiagnosticsproduced during that specific render
using HtmlForgeX.Email;
var email = new Email()
.SetEmbeddingWarnings(true)
.EnableInlineImageAttachments()
.ConfigureImageOptimization(maxWidth: 800, maxHeight: 600, quality: 85)
.ConfigureLayout(maxWidth: "640px");
email.Body.Add(new EmailImage("Assets/Images/logo.png", "120")
.WithAlternativeText("Company logo"));
var result = await email.RenderAsync();
foreach (var resource in result.InlineResources) {
Console.WriteLine($"{resource.ContentId} -> {resource.MimeType} ({resource.Data.Length} bytes)");
}
foreach (var diagnostic in result.Diagnostics) {
Console.WriteLine($"[{diagnostic.Category}/{diagnostic.Severity}] {diagnostic.Message}");
}
EnableInlineImageAttachments() is the normal delivery path. Use EnableBase64ImageEmbedding() only
for a deliberate standalone HTML/data-URI artifact; Base64 increases message size and client support varies.
The managed optimizer resizes and re-encodes PNG and JPEG images. It preserves GIF and other unsupported formats byte-for-byte so animated content is not accidentally flattened. Source bytes, decoded dimensions, and total decoded pixels are bounded; if a supported image cannot be decoded safely, the original bytes are kept and an image-embedding diagnostic is recorded.
The library does not send mail. A transport adapter should construct multipart/alternative from
PlainText and Html, attach InlineResources as CID parts, and add Attachments as regular MIME parts.
Migration notes
The compatibility-oriented defaults are intentionally conservative:
- New emails render in light mode unless dark-mode support is explicitly enabled with
WithThemeMode(Dark)orWithThemeMode(Auto). EnableImageEmbedding()now selects CID inline resources; useEnableBase64ImageEmbedding()only when a data URI is an explicit requirement.- The document shell is HTML5 rather than claiming XHTML Strict conformance.
Render()andRenderAsync()return the complete transport-neutral package. Existing code that only needs markup can continue usingToString()or readresult.Html.- CSS line-height values supplied as unitless ratios are normalized to percentages for broader email-client compatibility.
For document-level inspection, use the configuration helpers:
var totalDiagnostics = email.Configuration.GetDiagnosticCount();
var embeddingWarnings = email.Configuration.GetDiagnostics(
severity: EmailDiagnosticSeverity.Warning,
category: EmailDiagnosticCategory.ImageEmbedding);
email.Configuration.ClearDiagnostics(); // optional, if you want a fresh slate
If you want a runnable sample, see:
HtmlForgeX.Email.Examples/Email/EmailRenderDiagnostics.cs
Common components (basics)
Tables
var table = new EmailTable()
.AddHeader("Item", "Qty", "Total")
.AddRow("Pro (1 year)", "1", "$299")
.AddRow("Support", "1", "$99");
Mobile stacked tables (email clients)
var table = new EmailTable()
.WithMobileStackedLayout()
.WithMobileStackedBreakpoint(560)
.WithMobileStackedLabelWidth("40%")
.AddHeader("Target", "Duration", "Checked", "Stage")
.AddRow("ADRODC.ad.evotecc.pl", "0:06:08", "09:48:17Z", "Critical");
Note: stacked layout renders a second table for CSS switching, which increases HTML size.
Donut charts (quality presets)
var donut = new EmailDonutChart()
.WithQuality(EmailDonutChartQuality.Balanced)
.AddSegment("Core", 62, "#4f46e5")
.AddSegment("Support", 24, "#0ea5e9")
.AddSegment("Training", 14, "#f59e0b");
Notes:
Compact= fewer cells (smaller HTML, faster in Outlook).Smooth= denser grid (rounder edges, larger HTML).
Key/value details (nullable-safe)
var kv = new EmailKeyValueTable()
.WithNullValueMode(EmailNullValueMode.Placeholder, "n/a")
.AddRow("Order", "ORD-2048")
.AddRow("Delivered to", (string?)null); // respects NullValueMode
How it works (and why)
Email clients do not behave like browsers. The safest cross-client approach is still:
- Table-first layout (predictable in Outlook/Gmail/legacy clients)
- Inline styles for critical presentation (many clients strip or rewrite
<style>blocks) - MSO conditional comments + VML for Outlook Windows rendering (Word engine)
HtmlForgeX.Email renders an HTML5 email document and relies on:
- minimal head CSS for broad support
- inline styles for layout/typography
- stable
hfx-*class hooks to apply dark-mode overrides where safe
Themes & dark mode (typed)
Theme changes are done via the per-email Theme palette — no custom CSS needed:
email.WithThemeMode(EmailThemeMode.Light | Dark | Auto)email.ConfigureTheme(theme => ...)email.WithAccentColor(...),email.WithSurfaceColor(...),email.WithTextColor(...)
See:
Docs/Theming.mdDocs/DarkMode.md
Email standards & compatibility notes
There is no single “HTML email standard” enforced across clients. HtmlForgeX.Email follows the de‑facto constraints used by production transactional emails:
- Document: renders an HTML5 document with typed language and text-direction metadata
- Accessibility: uses
role="presentation"for layout tables, emits explicit image alt attributes, and reports missing meaningful alt text - Alternatives: generates a plain-text alternative unless one is supplied explicitly
- Attachments: includes iCalendar and vCard generators plus render-package attachment descriptors
- Markup: safe HTML + table layout (avoid modern layout primitives like flex/grid)
- CSS: inline for critical rules; only minimal head CSS + responsive media queries where supported
- Outlook Windows (classic): uses the MS Word HTML engine → limited CSS; VML is the reliable fallback for shapes/backgrounds
- Gmail: generally strong support, but sanitizes/rewrites markup; prefer inline styles and simple selectors
- Apple Mail: WebKit-based, typically the most standards-friendly
Tip: Always validate in real clients (Gmail web/app, Outlook desktop, Outlook.com, Apple Mail) — browser previews can mislead, especially for dark mode.
Client landscape (practical view)
Email rendering depends on the client family more than on “HTML standards”:
- Outlook (classic) on Windows: MS Word rendering engine (very limited CSS). Use tables, avoid advanced selectors, and prefer VML for shapes/backgrounds.
- Outlook.com / “new” Outlook: web engine (much closer to browser behavior than classic Outlook).
- Gmail (web + apps): strong support, but sanitizes and rewrites markup; inline styles are the safest baseline.
- Apple Mail: WebKit-based and generally the most standards-friendly.
If you need pixel-perfect visuals everywhere, you typically end up with client-specific fallbacks. HtmlForgeX.Email tries to keep this typed and library-internal (no raw HTML/CSS required from users).
Component inventory (high level)
The library ships composable primitives and higher-level “cards”. A non-exhaustive map:
- Layout:
EmailBox,EmailSection,EmailRow/EmailColumn,EmailGrid,EmailMediaObject,EmailInlineStack,EmailContent - Layout/compat:
EmailBackgroundImageBox(CSS background + Outlook VML fallback) - Text/media:
EmailHero,EmailHeading,EmailText,EmailTextBlock,EmailLink,EmailImage,EmailAvatar,EmailIconCircle - Interactive:
EmailButton,EmailButtonGroup,EmailOtpCode,EmailSurveyOptions,EmailNpsRating,EmailEmojiRating - Tables/data:
EmailTable,EmailDynamicTable,EmailKeyValueTable,EmailDnsRecordsTable,EmailComparisonTable - Utility cards:
EmailAlert,EmailCalloutCard,EmailEmptyStateCard,EmailProfileCard,EmailMapCard,EmailShippingProgress, many more - Charts (table-rendered):
EmailBarChart,EmailSparklineBars,EmailDonutChart,EmailHeatmap,EmailStatusTimeline - Attachments:
EmailIcsCalendar(ICS),EmailVCard(VCF), andEmailAttachmentdescriptors
For real-world compositions, browse and run the examples:
HtmlForgeX.Email.Examples
Recent "interactive inbox" demos added to the examples project:
EmailInteractiveTestResults- QA dashboard with quick actions, typed result rows and recent activityEmailInteractiveReleaseApproval- release gate email with sign-off actions, rollout waves and checklist stateEmailInteractiveCustomerEscalation- escalation thread with reply/assign actions and a typed triage planEmailInteractiveSecurityReview- security triage email with findings, containment checklist and analyst activityEmailInteractiveRenewalDesk- renewal-risk dashboard with account plan and commercial next stepsEmailInteractiveRoadmapVote- prioritization email with typed candidates and vote/spec shortcuts
Development
Generate example emails:
dotnet run --project HtmlForgeX.Email.Examples -c Release --framework net10.0
Run tests:
dotnet test HtmlForgeX.Email.sln -c Release
| Product | Versions 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 is compatible. 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 is compatible. 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. |
-
.NETFramework 4.7.2
- No dependencies.
-
.NETStandard 2.0
- No dependencies.
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on HtmlForgeX.Email:
| Package | Downloads |
|---|---|
|
EventViewerX.Reporting
Typed HTML, Excel, and email reporting for EventViewerX. |
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on HtmlForgeX.Email:
| Repository | Stars |
|---|---|
|
EvotecIT/EventViewerX
Windows Event Log tooling for PowerShell and .NET: typed queries, reporting, export, WEC, automation, and the PSEventViewer module.
|