Skip to main content

Asynchronous email dispatcher microservice with scheduling, rate limiting, attachments, and a FastAPI REST API.

Project description

genro-mail-proxy

PyPI version Tests codecov Documentation Python 3.10+ License

A microservice that decouples email delivery from your application.

What it does

genro-mail-proxy sits between your application and SMTP servers. Your application sends messages to the proxy via REST API; the proxy handles delivery with:

  • Persistent queue: Messages are stored in SQLite and survive restarts
  • Automatic retry: Failed deliveries are retried with exponential backoff
  • Rate limiting: Per-account limits (minute/hour/day) shared across instances
  • Priority queuing: Four levels (immediate, high, medium, low) with FIFO within each
  • Delivery reports: Results are posted back to your application via HTTP callback
  • Multi-tenancy: Multiple organizations can share one instance with separate accounts
┌─────────────┐      REST       ┌──────────────────┐      SMTP      ┌─────────────┐
│ Application │ ──────────────► │ genro-mail-proxy │ ─────────────► │ SMTP Server │
└─────────────┘                 └──────────────────┘                └─────────────┘
       ▲                               │
       │                               │
       └───────────────────────────────┘
                delivery reports

When to use it

Consider this proxy when:

  • Multiple application instances need shared rate limits for outbound email
  • Email delivery should not block your application's main request flow
  • Delivery tracking is needed with central logging and Prometheus metrics
  • Retry logic is required without implementing it in every service
  • Multi-tenant isolation is needed for different organizations or environments

When NOT to use it

This proxy adds operational complexity. Direct SMTP may be simpler when:

  • You have a single application instance with low email volume
  • Latency is acceptable (direct SMTP adds ~500-600ms per send)
  • No retry logic is needed (transactional emails with immediate feedback)
  • No rate limiting is required by your SMTP provider
  • You prefer fewer moving parts in your infrastructure

Quick start

Docker:

docker run -p 8000:8000 \
  -e GMP_API_TOKEN=your-secret-token \
  genro-mail-proxy

CLI:

pip install genro-mail-proxy
mail-proxy start myserver

Then configure a tenant, add an SMTP account, and start sending messages.

Command-line interface

The mail-proxy CLI manages instances without going through the HTTP API:

# Instance management
mail-proxy list                          # List all instances
mail-proxy start myserver                # Start an instance
mail-proxy stop myserver                 # Stop an instance
mail-proxy myserver info                 # Show instance details

# Tenant management
mail-proxy myserver tenants list         # List tenants
mail-proxy myserver tenants add acme     # Add a tenant (interactive)

# Account management (per tenant)
mail-proxy myserver acme accounts list   # List SMTP accounts
mail-proxy myserver acme accounts add    # Add account (interactive)

# Message operations
mail-proxy myserver acme messages list   # List queued messages
mail-proxy myserver acme send email.eml  # Send from .eml file
mail-proxy myserver acme run-now         # Trigger immediate dispatch

Each instance stores its configuration in ~/.mail-proxy/<name>/mail_service.db. The CLI supports both command-line arguments and interactive prompts for complex operations.

REST API

The proxy exposes a FastAPI REST API secured by X-API-Token:

  • POST /commands/add-messages - Queue messages for delivery
  • GET /messages - List queued messages
  • POST /commands/run-now - Trigger immediate dispatch cycle
  • GET /accounts - List SMTP accounts
  • GET /metrics - Prometheus metrics

See API Reference for details.

Attachment handling

The proxy supports multiple attachment sources:

Format Example Description
base64:content base64:SGVsbG8= Inline base64-encoded content
/absolute/path /tmp/file.pdf Local filesystem absolute path
relative/path uploads/doc.pdf Relative to configured base_dir
@params @doc_id=123 HTTP POST to default endpoint
@[url]params @[https://api.example.com]id=456 HTTP POST to specific URL

A two-tiered cache (memory + disk) reduces redundant fetches. Filenames can include an MD5 hash marker (report_{MD5:abc123}.pdf) for cache lookup.

Configuration

Configuration via config.ini or environment variables (prefixed with GMP_):

[attachments]
base_dir = /var/attachments
http_endpoint = https://api.example.com/attachments
http_auth_method = bearer
http_auth_token = your-secret-token

cache_memory_max_items = 100
cache_disk_dir = /var/cache/mail-proxy

See Usage for all options.

Performance notes

  • Request latency: ~30ms to queue a message (vs ~600ms for direct SMTP)
  • Throughput: Limited by SMTP provider rate limits, not the proxy
  • Memory: Attachment content is held in memory during send; use HTTP endpoints for large files

The SQLite database handles typical workloads but doesn't scale well under high concurrency. For high-volume deployments, consider running multiple instances with separate databases.

Development

pip install -e ".[dev]"
pytest

License

Apache License 2.0 — see LICENSE for details.

Copyright 2025 Softwell S.r.l. — Genropy Team

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

genro_mail_proxy-0.4.0.tar.gz (174.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

genro_mail_proxy-0.4.0-py3-none-any.whl (93.2 kB view details)

Uploaded Python 3

File details

Details for the file genro_mail_proxy-0.4.0.tar.gz.

File metadata

  • Download URL: genro_mail_proxy-0.4.0.tar.gz
  • Upload date:
  • Size: 174.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for genro_mail_proxy-0.4.0.tar.gz
Algorithm Hash digest
SHA256 130b7219a3086ffed36b5cc75304fcfeb0e37aa8852527b97fa3d143b6c6d5bd
MD5 6fa8c23729ece49fcbac3c8e88d59c93
BLAKE2b-256 19e2a74f37c15fdb1d232ae31fcc0c4a0feb36c66eecb7cbfb6f3bf6de64692d

See more details on using hashes here.

Provenance

The following attestation bundles were made for genro_mail_proxy-0.4.0.tar.gz:

Publisher: publish.yml on genropy/genro-mail-proxy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file genro_mail_proxy-0.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for genro_mail_proxy-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fba0ee1ab1a541ed967ba14a74bc35f050d1b54fd481b914289f5c6364da1b67
MD5 05ee56a11f053e117dbc8e526f96a989
BLAKE2b-256 00ff627863b7f08a4978e9997a132610b8d7b576f1395f8116ba84b710530de3

See more details on using hashes here.

Provenance

The following attestation bundles were made for genro_mail_proxy-0.4.0-py3-none-any.whl:

Publisher: publish.yml on genropy/genro-mail-proxy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page