Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
mailrs-outbound-queue
Outbound mail queue primitives for Rust MTAs — DKIM signing, DSN generation, MTA-STS lookup, retry/backoff, and an MX/DANE-aware delivery worker over a store you plug in.
Extracted from mailrs so any Rust MTA project can reuse the parts that are actually painful to get right: signing forwarded mail with ARC, generating standards-compliant Delivery Status Notifications, looking up MTA-STS policies, computing exponential backoff with jitter, and the long tail of "did this 5xx mean I should give up or try later" logic.
Highlights
- Bring your own store — queue state lives behind the [
QueueStore] trait and wake-ups behind [Notifier]. The crate ships no database backend and pulls in no database driver. - A contract you can run — [
store::contract::check_queue_store] checks your implementation against every rule the worker relies on (atomic claim, retry and bounce transitions, crash recovery, admin operations, the suppression list). Call it from one test. - Bundled delivery worker — [
DeliveryWorker] runs the claim-and-deliver loop over anyQueueStore: MX resolution, DANE / MTA-STS aware STARTTLS viamailrs-smtp-client, DKIM signing, ARC sealing for forwarded mail, retry with backoff, DSNs and hard-bounce suppression. - Reference implementations — [
InMemoryQueueStore] and [InMemoryNotifier] are complete, contract-checked implementations for tests and single-process deployments. - Pure primitives —
dkim_sign,dsn,mta_stsandretryare usable on their own.
Quick start
use Arc;
use ;
# async
See examples/in_memory_queue.rs for the store lifecycle without opening sockets.
Plugging in your own store
- Implement [
QueueStore] over your backend.claim_for_deliverymust be atomic — two concurrent claims never return the same row — so several workers can share one store. In SQL that is oneUPDATE … WHERE id IN (SELECT … FOR UPDATE SKIP LOCKED) RETURNING …. - Implement [
Notifier] over whatever reaches every worker process (a pub/sub channel, a databaseLISTEN), or pass [NoopNotifier] and rely onWorkerConfig::poll_interval_secs. - Check the store:
async
Module overview
| Module | Notes |
|---|---|
store |
QueueStore, Notifier, NoopNotifier, InMemoryQueueStore, InMemoryNotifier, StoreError, contract. |
queue |
QueuedMessage, QueueStatus, is_hard_bounce. |
worker |
DeliveryWorker, deliver_domain_static, try_deliver_via_mx. |
dkim_sign |
RFC 6376 DKIM signing + RFC 8617 ARC sealing. |
dsn |
RFC 3464 / 6533 Delivery Status Notification generation. |
mta_sts |
RFC 8461 MTA-STS policy lookup. |
retry |
Backoff schedule + bounce decision. |
What this crate does NOT do
- No SMTP server — see
mailrs-smtp-protofor the inbound state machine. - No DKIM verification — outbound only (signing). Verification lives in
mail-auth. - No SPF / DMARC enforcement on inbound. Those belong upstream of this crate.
- No message storage / threading. See
mailrs-mailbox/mailrs-maildirfor those.
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Performance
Criterion benches: cargo bench -p mailrs-outbound-queue. Per-bench medians + regression budgets are documented in BUDGETS.md (this crate) and the workspace PERFORMANCE.md.