Mailbridge is a Rust library for sending application email without tying your code to one provider's SDK or request model. It gives services one typed API for building, validating, sending, queueing, retrying, and rate-limiting transactional email while keeping provider-specific behavior behind opt-in feature flags.
Use it when your application needs to send operational email such as verifications, password resets, receipts, alerts, invitations, and product notifications through Hyvor Relay, SendGrid, Mailgun, SendPulse, Resend, Mailjet, Brevo, Bird, or SMTP. The goal is to make provider switching and local testing practical without leaking API keys, message bodies, or provider SDK types through the rest of your codebase.
Mailbridge is not a marketing automation platform, campaign manager, template designer, or address-book system. It focuses on the reliable delivery path that Rust services need at runtime.
- Usage guide
- Architecture and design
- Telemetry guide
- Roadmap
- Changelog
- Contributing
- Contributors
- Security policy
hyvor-relay,api,rustls,queue-memory, andrate-limitare enabled by default.smtpenables SMTP submission throughlettre.queue-sqlite,queue-postgres, andqueue-scyllaenable durable queue adapters.telemetryemitstracingevents and spans without API keys, message bodies, or full recipient lists.sendgrid,sendpulse,mailgun,resend,mailjet,brevo, andbirdenable opt-in HTTP providers for those transactional email services.
Use queue-memory for tests and local development. It is process-local and
does not survive restarts.
Use queue-sqlite for single-node durable queueing.
Use queue-postgres when the application already operates PostgreSQL or needs
SQL visibility. The adapter uses row locking with FOR UPDATE SKIP LOCKED.
Use queue-scylla for high-throughput distributed queueing only when the
deployment can own Scylla operations. The adapter creates:
{table}for item rows keyed by(bucket, id).{table}_duefor due-time scans keyed by(bucket, available_at_ms, id).{table}_dead_lettersfor failed messages.
Scylla operational notes:
- Tune bucket count to spread queue scans across partitions. The default is 64.
- Keep lock timeout longer than normal provider latency and shorter than worker recovery requirements. The default is five minutes.
- Reservation uses lightweight transactions, so size worker concurrency and bucket count with LWT cost in mind.
- Replication strategy, compaction, dead-letter retention, TTL, and schema migration policy belong to the application deployment.
- Live tests use
MAILBRIDGE_TEST_SCYLLA_URI,MAILBRIDGE_TEST_SCYLLA_KEYSPACE, andMAILBRIDGE_TEST_SCYLLA_TABLE.
Live persistent-backend tests are local opt-in only. They never run when the
standard CI environment variable is present.
PostgreSQL live tests run only when MAILBRIDGE_RUN_PERSISTENT_TESTS=true and
MAILBRIDGE_TEST_POSTGRES_URL are set.
ScyllaDB live tests run only when MAILBRIDGE_RUN_PERSISTENT_TESTS=true and
MAILBRIDGE_TEST_SCYLLA_URI are set. The keyspace must already exist.
This project is licensed under the MIT License.