Skip to content

Sysopoly/email-service

Repository files navigation

sysopoly-email-service

A lightweight, multi-tenant email delivery service built with Go and the Resend API. Designed as an internal microservice that provides templated email sending for the Sysopoly platform.

Features

  • Multi-domain support — configure multiple sending domains (e.g., sethabit.com, sysopoly.com) via environment variables
  • Template engine — built-in HTML + plain-text email templates with dynamic data injection
  • Batch sending — send multiple emails in a single API call via Resend's batch endpoint
  • Request tracing — automatic request ID generation and propagation for distributed tracing
  • Internal auth — API key authentication for service-to-service communication
  • Graceful shutdown — proper signal handling for zero-downtime deployments
  • Structured logging — JSON-formatted logs via slog with environment-aware log levels

Architecture

┌─────────────────┐         ┌──────────────────┐         ┌─────────────┐
│  Internal Svc   │──POST──▶│  Email Service   │──HTTP──▶│  Resend API │
│  (scheduler,    │         │  (Gin + auth)    │         │             │
│   auth, api)    │         └──────────────────┘         └─────────────┘
└─────────────────┘

Configuration

All configuration is via environment variables:

Variable Required Default Description
RESEND_API_KEY Yes Resend API key for sending
INTERNAL_API_KEY Yes Shared secret for authenticating internal callers
PORT No 8086 HTTP server port
ENVIRONMENT No development development or production
DEFAULT_DOMAIN No sethabit Default domain alias when none specified
DOMAIN_<ALIAS> Yes (≥1) Domain config: name|from|replyto
LOGGING_SERVICE_URL No Remote logging endpoint

Domain Configuration

Each domain is configured via a DOMAIN_<ALIAS> environment variable with pipe-separated values:

DOMAIN_SETHABIT="sethabit.com|SetHabit <noreply@sethabit.com>|support@sethabit.com"
DOMAIN_SYSOPOLY="sysopoly.com|Sysopoly <noreply@sysopoly.com>|"

API

All endpoints (except /health) require the X-Internal-API-Key header.

GET /health

Health check — returns 200 OK with service status.

POST /send

Send a single email.

{
  "domain": "sethabit",
  "to": ["user@example.com"],
  "subject": "Welcome!",
  "template": "welcome",
  "template_data": { "name": "Alice" },
  "tags": { "campaign": "onboarding" }
}

POST /send-batch

Send multiple emails in one request.

{
  "messages": [
    { "to": ["a@example.com"], "subject": "Hello", "html": "<p>Hi</p>" },
    { "to": ["b@example.com"], "subject": "Hello", "template": "welcome" }
  ]
}

Built-in Templates

Template Purpose
welcome New user onboarding
gdpr_report GDPR data export notification
account_deleted Account deletion confirmation
marketing_campaign Generic marketing email with CTA

Development

# Run tests
make test

# Run with race detector
make test-race

# Build binary
make build

# Run locally (requires env vars)
make run

# Docker
docker compose up --build

Deployment

The service is deployed as a container via GitHub Actions. The workflow builds, tests, and pushes to GHCR on every push to master.

docker pull ghcr.io/sysopoly/sysopoly-email-service:latest

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages