Skip to content

Command palette

Navigation, language and theme

enpl
All case studies

03 — Own project · running in production in the homelab

A mail microservice for services and AI agents

One HTTP API for sending email from every service and agent: a separate key per service, a full delivery trail in PostgreSQL and a dashboard with GitHub sign-in.

Problem

Every homelab service and every AI agent that had to send an email needed its own SMTP configuration and mailbox password. There was no single place showing what was sent, to whom, on whose behalf and whether it was delivered.

What I built

  • A NestJS API (POST /v1/messages): recipients, CC/BCC, reply-to, base64 attachments (with count and size limits) and a choice of sender — one for external correspondence, one for internal matters.
  • A separate API key per service — every send is attributed, and one service can be cut off without touching the others. Reading the history requires a separate admin token.
  • A full trail in PostgreSQL (Drizzle) — every message gets an accepted event, then sent or failed with the SMTP server's response. Only metadata and a SHA-256 hash are kept for attachments.
  • A Next.js dashboard with GitHub OAuth sign-in (one allowed account): messages, events, statistics.
  • End-to-end tests of the API against an embedded PostgreSQL and a fake SMTP server; scripted deployment with Docker Compose, secrets pulled from a password manager.
  • Publishing through Cloudflare Tunnel and Traefik with a per-IP rate limit — no open ports.

Outcome

  • Services and agents send mail with a single HTTP call, with no SMTP passwords in their configuration.
  • Every send leaves a trail: who requested it, to whom, and with what result.
  • The contact form on this site delivers its messages through this very microservice.

Facing a similar problem?

Describe your process — I'll tell you whether and how it can be solved.

Get in touch