MailForge Studio
MailForge Studio is a local development inbox. It captures every message your pipeline
sends — through its own IEmailProvider — into a SQLite store, renders a web dashboard,
and exposes an SMTP relay you can point any mail tool at. Nothing leaves your machine.
App pipeline → StudioEmailProvider → SQLite store → Dashboard (localhost) · SMTP relay
Wiring
AddMailForgeStudio registers the capture store, the StudioEmailProvider, and optionally
the SMTP relay. Point the MailForge pipeline at the Studio provider:
services.AddMailForgeStudio(options =>
{
options.DatabasePath = "mailforge-studio.db";
options.EnableSmtpRelay = true; // default
options.SmtpRelayPort = 2525; // 0 picks an ephemeral port
});
services.AddMailForge(builder => builder
.UseDefaultFrom("noreply@mailforge.dev")
.UseProvider(sp => sp.GetRequiredService<StudioEmailProvider>()));
Everything the pipeline "sends" lands in the local inbox instead of the internet.
Configuration (StudioCaptureOptions)
| Option | Default | Purpose |
|---|---|---|
DatabasePath |
mailforge-studio.db |
SQLite file; delete it to reset the inbox (schema rebuilds on next use) |
EnableSmtpRelay |
true |
Run the local SMTP listener |
SmtpRelayHost |
127.0.0.1 |
Relay bind address |
SmtpRelayPort |
2525 |
Relay port; 0 picks an ephemeral port |
BuildConnectionString() |
— | SQLite connection string (pooling disabled so the file is never locked) |
Storage Model
IStudioCaptureStore exposes the inbox: CapturedMessage (from, subject, html/text bodies,
priority, timestamps), plus CapturedRecipient, CapturedAttachment, and CapturedHeader
children. The StudioEmailProvider stores the EmailMessage faithfully, and
MimeMessageConverter round-trips raw MIME for SMTP-relay captures and exports.
Web Dashboard
StudioWebHost.Build(StudioWebOptions), or run it directly with StudioWebHost.StartAsync.
It serves an HTML dashboard (/, /messages/{id}) and a JSON API grouped at
/api/messages:
| Route | Method | Purpose |
|---|---|---|
/api/messages/ |
GET | Paginated inbox list (StudioMessageQuery search/filter) |
/api/messages/{id} |
GET | Message detail |
/api/messages/{id}/export?format=eml\|html\|json |
GET | Export in the given format (StudioMimeExporter) |
/api/messages/{id}/raw |
GET | Regenerated raw MIME source (.eml) |
/api/messages/{id}/attachments/{attachmentId} |
GET | Attachment download |
/api/messages/{id}/replay |
POST | Re-send a captured message via SMTP (MessageReplayer) |
Replay SMTP targets are configured in StudioWebOptions (SmtpHost, SmtpPort,
TimeoutMilliseconds).
Running the Demo
The console app has two harnesses (no provider credentials needed):
dotnet run --project MailForge.Console -- studio-demo # sends samples + prints inbox
dotnet run --project MailForge.Console -- studio-web # dashboard on http://127.0.0.1:5000
studio-web [port] [dbPath] [relayPort] — the relay listens on relayPort (default 2525;
pass off to disable it). When dbPath is omitted both commands share a temporary
mailforge-studio.db, so studio-demo output shows up in the dashboard.