Skip to content

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 19 Jun 06:57
· 17 commits to main since this release
Immutable release. Only release title and notes can be modified.
e6f033d

What's Changed

  • feat: add IMAP SEARCH by @Jaro-c in #78
  • feat: add IMAP STARTTLS on port 143 by @Jaro-c in #80
  • feat: enforce MTA-STS on outbound delivery by @Jaro-c in #83
  • feat: manage accounts dynamically through the API by @Jaro-c in #85
  • feat: add token-hash CLI command by @Jaro-c in #88
  • feat: IMAP STATUS, SUBSCRIBE/UNSUBSCRIBE/LSUB, real INTERNALDATE by @Jaro-c in #101
  • fix: enforce DKIM x= expiration before DNS lookup by @Jaro-c in #102
  • fix(dmarc): enforce pct= sampling on failing messages by @Jaro-c in #104
  • chore(smtp): split session.rs under 500-line limit by @Jaro-c in #105
  • fix(spf): add exists: and ptr: mechanism support by @Jaro-c in #109
  • feat: SPF macro expansion (RFC 7208 §7) by @Jaro-c in #110
  • fix: fold Authentication-Results header per RFC 8601 §2.2 by @Jaro-c in #112
  • fix(spf): repair evaluator.rs broken by squash-merge of #109 and #110 by @Jaro-c in #113
  • fix(dmarc): use Mozilla PSL for organizational domain alignment by @Jaro-c in #107
  • feat(dmarc): parse rua= aggregate report URIs (RFC 7489 §6.3) by @Jaro-c in #111
  • fix: harden API auth — CORS, rate limiting, SHA-256 token by @Jaro-c in #99
  • fix: initialize structured logging in the serve command by @Jaro-c in #92
  • chore: add cargo-deny and fix RUSTSEC-2025-0134 by @Jaro-c in #94
  • docs: add install one-liner using custom URL by @Jaro-c in #95
  • chore(deps): bump actions/attest-build-provenance from 3.0.0 to 4.1.0 by @dependabot[bot] in #86
  • feat: add token-hash CLI command by @Jaro-c in #87
  • fix: limit concurrent connections and enforce idle timeouts by @Jaro-c in #90
  • fix: handle SIGTERM and SIGINT for graceful shutdown by @Jaro-c in #97
  • feat: IMAP SEARCH OR/NOT/date/size criteria by @Jaro-c in #114
  • feat: IMAP IDLE push notifications on mailbox change by @Jaro-c in #115
  • fix: advertise IDLE, LITERAL+ and SASL-IR in IMAP capabilities by @Jaro-c in #116
  • feat: add GET /api/v1/accounts/{name}/mailboxes endpoint by @Jaro-c in #117
  • feat: DMARC aggregate report generation and delivery (RFC 7489 §7) by @Jaro-c in #118
  • fix: accept 8-bit message data (8BITMIME, RFC 6152) by @Jaro-c in #119
  • test: cover flush_pending; bring coverage above 90% gate by @Jaro-c in #122
  • refactor: split files exceeding 500-line limit by @Jaro-c in #120
  • refactor: extract dmarc/aggregate tests under 500-line limit by @Jaro-c in #124
  • feat(tlsrpt): parse TLS-RPT policy records (RFC 8460 §3) by @Jaro-c in #126
  • feat(tlsrpt): generate RFC 8460 §4 reports by @Jaro-c in #128
  • ci: pin reusable workflow caller to v1.0.0 with version comment by @Jaro-c in #133
  • chore: fill copyright owner in LICENSE by @Jaro-c in #134
  • fix(smtp): HELO must not advertise ESMTP extensions by @Jaro-c in #255
  • feat(smtp): advertise LIMITS RCPTMAX in EHLO (RFC 9422) by @Jaro-c in #256
  • test(smtp): cover RFC 2920 command pipelining ordering by @Jaro-c in #257
  • feat(smtp): emit RFC 3463 enhanced status codes by @Jaro-c in #258
  • feat(smtp): REQUIRETLS receive-side (RFC 8689) by @Jaro-c in #260
  • feat(smtp): enforce REQUIRETLS on outbound relay (RFC 8689) by @Jaro-c in #261
  • refactor(smtp): extract trace headers into trace module by @Jaro-c in #264
  • ci: wire DCO and line-limit reusable gates by @Jaro-c in #265
  • ci: wire rust-audit (cargo-audit + cargo-deny) gate by @Jaro-c in #267
  • ci: wire rust-supply-chain SBOM and license attribution by @Jaro-c in #268
  • ci: harden release with verify gate and SBOM by @Jaro-c in #270
  • ci: add cargo-fuzz harness for SMTP wire parsers by @Jaro-c in #271
  • ci: add weekly cargo-mutants mutation-testing report by @Jaro-c in #272
  • feat(directory): sub-addressing (RFC 5233) by @Jaro-c in #274
  • feat(accounts): per-domain catch-all delivery by @Jaro-c in #275
  • feat(accounts): domain aliases by @Jaro-c in #276
  • feat(dnsbl): DNS blocklist lookups (RFC 5782) by @Jaro-c in #277
  • feat(smtp): reject DNSBL-listed clients on inbound mail by @Jaro-c in #278
  • feat(antispam): PostgreSQL foundation for the antispam engine by @Jaro-c in #280
  • feat(antispam): sender reputation store by @Jaro-c in #281
  • feat(antispam): record reputation on accepted inbound mail by @Jaro-c in #283
  • refactor(smtp): split server into mod + run by @Jaro-c in #285
  • feat(antispam): reputation screening and first-time-sender delay by @Jaro-c in #286
  • feat(antispam): Bayesian classifier core by @Jaro-c in #287
  • feat(antispam): Bayesian corpus store and scoring by @Jaro-c in #288
  • feat(antispam): auto-train the Bayesian corpus from delivery outcomes by @Jaro-c in #290
  • feat(rules): delivery ruleset matcher by @Jaro-c in #291
  • feat(rules): apply delivery rulesets to local mail by @Jaro-c in #292
  • feat(antispam): quarantine poor-reputation mail to a Rejects mailbox by @Jaro-c in #293
  • feat(antispam): external scanner hook (HTTP) by @Jaro-c in #294
  • feat(metrics): server-side Prometheus metrics core by @Jaro-c in #295
  • feat(observability): /metrics endpoint and instrumentation by @Jaro-c in #296
  • feat(observability): structured logging and auth-failure events by @Jaro-c in #297
  • feat(acme): account key and JWS request signing (RFC 8555) by @Jaro-c in #298
  • feat(acme): JWK thumbprint, key authorization, and directory by @Jaro-c in #299
  • feat(acme): request payloads and response objects by @Jaro-c in #300
  • feat(acme): client orchestration for account and order by @Jaro-c in #301
  • feat(acme): challenge, finalize and certificate flow by @Jaro-c in #302
  • feat(acme): HTTP-01 challenge responder by @Jaro-c in #303
  • feat(acme): CSR generation for finalize by @Jaro-c in #304
  • feat(acme): reqwest HTTP transport by @Jaro-c in #305
  • feat(tls): in-memory and hot-reloadable acceptors by @Jaro-c in #306
  • feat(acme): end-to-end certificate issuance via HTTP-01 by @Jaro-c in #307
  • feat(config): ACME settings section by @Jaro-c in #308
  • feat(smtp): serve TLS via a hot-reloadable acceptor by @Jaro-c in #309
  • feat(acme): HTTP-01 challenge listener by @Jaro-c in #310
  • feat(acme): automatic certificate renewal by @Jaro-c in #311
  • feat(pop3): command parser (RFC 1939) by @Jaro-c in #312
  • feat(pop3): sans-IO session state machine (RFC 1939) by @Jaro-c in #313
  • feat(pop3): TLS-only network server and live wiring by @Jaro-c in #314
  • feat(arc): chain extraction and structural validation (RFC 8617) by @Jaro-c in #315
  • feat(arc): parse ARC-Message-Signature and ARC-Seal headers by @Jaro-c in #316
  • feat(arc): sign and verify ARC-Message-Signature by @Jaro-c in #317
  • feat(arc): sign and verify ARC-Seal by @Jaro-c in #318
  • feat(arc): full chain validation (RFC 8617 §5.2) by @Jaro-c in #319
  • feat(arc): ArcSealer adds a new instance to the chain by @Jaro-c in #320
  • feat(arc): seal inbound mail and wire ARC end to end by @Jaro-c in #321
  • feat(smtp): RFC 3464 delivery status notifications by @Jaro-c in #322
  • feat(antispam): ARF abuse feedback reports (RFC 5965) by @Jaro-c in #323
  • feat(dane): TLSA records and certificate-association matching by @Jaro-c in #324
  • feat(dane): TLS peer authentication policy by @Jaro-c in #325
  • feat(sieve): lexer (RFC 5228) by @Jaro-c in #326
  • feat(sieve): parser and AST (RFC 5228) by @Jaro-c in #327
  • feat(sieve): interpreter by @Jaro-c in #328
  • feat(sieve): apply per-account filters at local delivery by @Jaro-c in #329
  • feat(sieve): address test with address-part support by @Jaro-c in #330
  • feat(sieve): envelope test wired to the SMTP envelope by @Jaro-c in #331
  • feat(sieve): queue filter redirects to the outbound spool by @Jaro-c in #332
  • feat(sieve): vacation autoreply response builder (RFC 5230) by @Jaro-c in #333
  • feat(smtp): parse DSN ESMTP parameters (RFC 3461) by @Jaro-c in #334
  • feat(smtp): advertise DSN in EHLO (RFC 3461) by @Jaro-c in #335
  • feat(antispam): greylisting decision core by @Jaro-c in #336
  • feat(antispam): wire greylisting into inbound SMTP by @Jaro-c in #337
  • feat(sieve): body test (RFC 5173) by @Jaro-c in #338
  • feat(smtp): reject looping mail past the Received hop limit by @Jaro-c in #339
  • feat(queue): Sender Rewriting Scheme (SRS) core by @Jaro-c in #340
  • feat(queue): rewrite forwarded sender via SRS by @Jaro-c in #341
  • feat(queue): return SRS bounces to the original sender by @Jaro-c in #342
  • feat(smtp): SCRAM-SHA-256 server exchange (RFC 5802/7677) by @Jaro-c in #343
  • feat(imap): SPECIAL-USE mailbox attributes (RFC 6154) by @Jaro-c in #344
  • feat(imap): NAMESPACE command (RFC 2342) by @Jaro-c in #345
  • feat(imap): ID command (RFC 2971) by @Jaro-c in #346
  • feat(imap): UIDPLUS APPENDUID response (RFC 4315) by @Jaro-c in #347
  • feat(imap): UIDPLUS COPYUID on COPY and MOVE (RFC 4315) by @Jaro-c in #348
  • feat(imap): UID EXPUNGE command (RFC 4315) by @Jaro-c in #349
  • feat(imap): SORT command (RFC 5256) by @Jaro-c in #350
  • feat(imap): THREAD ORDEREDSUBJECT (RFC 5256) by @Jaro-c in #351
  • feat(imap): UNSELECT and ENABLE commands (RFC 3691, 5161) by @Jaro-c in #352
  • feat(imap): ESEARCH / SEARCH RETURN (RFC 4731) by @Jaro-c in #353
  • feat(imap): QUOTA reporting (RFC 9208) by @Jaro-c in #354
  • feat(imap): enforce storage quota on APPEND by @Jaro-c in #355
  • feat(imap): configure the storage quota by @Jaro-c in #356
  • feat(imap): STATUS SIZE (RFC 8438) by @Jaro-c in #357
  • feat(imap): SEARCH HEADER, CC and BCC criteria (RFC 9051) by @Jaro-c in #358
  • feat(auth): store SCRAM-SHA-256 credentials per account by @Jaro-c in #359
  • feat(smtp): SCRAM-SHA-256 authentication (RFC 4954/5802) by @Jaro-c in #360
  • feat(imap): SCRAM-SHA-256 and PLAIN AUTHENTICATE (RFC 9051/5802) by @Jaro-c in #361
  • feat(totp): TOTP/HOTP two-factor core (RFC 6238/4226) by @Jaro-c in #362
  • feat(jwt): JWT validation core (RFC 7519) by @Jaro-c in #363
  • feat(oauth): OAuth2/OIDC bearer-token verifier by @Jaro-c in #364
  • feat(smtp): OAUTHBEARER/XOAUTH2 authentication (RFC 7628) by @Jaro-c in #365
  • feat(imap): OAUTHBEARER/XOAUTH2 AUTHENTICATE (RFC 7628) by @Jaro-c in #366
  • feat(smtp): SMTPUTF8 internationalized email (RFC 6531) by @Jaro-c in #367
  • feat(imap): CONDSTORE mod-sequences (RFC 7162) by @Jaro-c in #368
  • feat(imap): CONDSTORE CHANGEDSINCE and UNCHANGEDSINCE (RFC 7162) by @Jaro-c in #369
  • feat(sieve): imap4flags setflag/addflag/removeflag (RFC 5232) by @Jaro-c in #370
  • feat(sieve): fileinto/redirect :copy (RFC 3894) by @Jaro-c in #371
  • feat(imap): SEARCH MODSEQ (RFC 7162) by @Jaro-c in #372
  • feat(imap): LIST-STATUS (RFC 5819) by @Jaro-c in #377
  • feat(imap): LIST-EXTENDED SUBSCRIBED selection (RFC 5258) by @Jaro-c in #378
  • feat(smtp): drop clients after too many error replies by @Jaro-c in #379
  • feat(imap): drop clients after too many BAD responses by @Jaro-c in #380
  • feat(pop3): drop clients after too many error responses by @Jaro-c in #381
  • feat(sieve): date test (RFC 5260) by @Jaro-c in #382
  • feat(metrics): count abuse-guard connection drops by @Jaro-c in #383
  • feat(dkim): optional RSA dual-signing (RFC 8463) by @Jaro-c in #384
  • feat(sieve): currentdate test (RFC 5260) by @Jaro-c in #385
  • feat(jmap): Session resource and Core/echo (RFC 8620) by @Jaro-c in #386
  • feat(jmap): Mailbox/get and mail capability (RFC 8621) by @Jaro-c in #387
  • feat(jmap): Email/query (RFC 8621) by @Jaro-c in #388
  • feat(jmap): Email/get (RFC 8621) by @Jaro-c in #389
  • feat(jmap): Email/set keyword updates (RFC 8621) by @Jaro-c in #390
  • feat(jmap): Email/set destroy (RFC 8621) by @Jaro-c in #391
  • feat(jmap): Identity/get and submission capability (RFC 8621) by @Jaro-c in #392
  • feat(jmap): EmailSubmission/set (RFC 8621) by @Jaro-c in #393
  • feat(jmap): .well-known/jmap autodiscovery (RFC 8620) by @Jaro-c in #394
  • feat(jmap): Email/get bodyValues and body parts (RFC 8621) by @Jaro-c in #395
  • feat(jmap): Mailbox/set create/rename/destroy (RFC 8621) by @Jaro-c in #396
  • feat(jmap): Email/set mailboxIds — move between mailboxes (RFC 8621) by @Jaro-c in #397
  • feat(jmap): Thread/get (RFC 8621) by @Jaro-c in #398
  • feat(totp): per-account TOTP enrollment storage and API (RFC 6238) by @Jaro-c in #399
  • feat(totp): enforce TOTP second factor at login (RFC 6238) by @Jaro-c in #400
  • feat(api): unauthenticated /healthz liveness probe by @Jaro-c in #401
  • feat(imap): BINARY[] fetch with CTE decoding (RFC 3516) by @Jaro-c in #402
  • feat(imap): BINARY.SIZE[] fetch (RFC 3516) by @Jaro-c in #403
  • feat(sieve): reject/ereject action with DSN bounce (RFC 5429) by @Jaro-c in #404
  • feat(sieve): vacation autoresponder (RFC 5230) by @Jaro-c in #405
  • feat(metrics): Sieve delivery outcome counters by @Jaro-c in #406
  • feat(metrics): outbound queue delivery counters by @Jaro-c in #407
  • fix(imap): persistent, stable UIDVALIDITY per mailbox (RFC 3501) by @Jaro-c in #408
  • feat(imap): persistent UIDs that survive expunge (RFC 3501) by @Jaro-c in #409
  • feat(imap): expunge log for QRESYNC VANISHED (RFC 7162) by @Jaro-c in #410
  • feat(imap): QRESYNC SELECT with VANISHED (EARLIER) (RFC 7162) by @Jaro-c in #411
  • feat(imap): ENABLE acknowledges CONDSTORE and QRESYNC (RFC 7162) by @Jaro-c in #412
  • feat(imap): UID FETCH ... VANISHED (RFC 7162) by @Jaro-c in #413
  • feat(imap): OBJECTID — EMAILID, THREADID, MAILBOXID (RFC 8474) by @Jaro-c in #414
  • feat(imap): FETCH SAVEDATE (RFC 8514) by @Jaro-c in #415
  • feat(sieve): variables — set and ${name} expansion (RFC 5229) by @Jaro-c in #416
  • feat(imap): STATUS DELETED and MAILBOXID (RFC 9051/8474) by @Jaro-c in #417
  • feat(jmap): Email/set create (RFC 8621) by @Jaro-c in #418
  • feat(imap): full FLAGS list and PERMANENTFLAGS in SELECT (RFC 9051) by @Jaro-c in #419
  • feat(smtp): AUTH LOGIN mechanism (legacy client compat) by @Jaro-c in #420
  • feat(imap): AUTHENTICATE LOGIN mechanism (legacy client compat) by @Jaro-c in #421
  • feat(pop3): SASL AUTH PLAIN (RFC 5034) by @Jaro-c in #422
  • refactor(sieve): extract test evaluation into sieve/eval.rs by @Jaro-c in #423
  • feat(sieve): match-capture variables ${1}..${N} (RFC 5229) by @Jaro-c in #424
  • feat(jmap): Email/copy (RFC 8621) by @Jaro-c in #425
  • feat(jmap): Quota/get (RFC 9425) by @Jaro-c in #426
  • feat(cli): export an account's mailboxes to mbox (backup/migration) by @Jaro-c in #427
  • feat(cli): import an mbox stream into an account's INBOX (migration) by @Jaro-c in #428
  • test(cli): make export writable to any sink and cover run() by @Jaro-c in #430
  • feat(cli): list the outbound queue (mail queue) by @Jaro-c in #431
  • feat(jmap): Mailbox/query (RFC 8621) by @Jaro-c in #432
  • feat(cli): list configured accounts (mail accounts) by @Jaro-c in #433
  • test(jmap): cover method error paths (missing accountId) by @Jaro-c in #435
  • test(jmap): cover Email/set notFound and accountNotFound paths by @Jaro-c in #436
  • test(api): cover ApiError constructors and responses by @Jaro-c in #437
  • test(arc): cover chain validation failure paths by @Jaro-c in #438
  • test(imap): cover SORT address keys, base subject and guards by @Jaro-c in #439
  • test(acme): cover account key and renewal edge cases by @Jaro-c in #440
  • test(antispam): cover HTTP scanner hook with an in-process server by @Jaro-c in #441
  • test(acme): cover HTTP transport against an in-process server by @Jaro-c in #442
  • test(acme): cover order failure and timeout paths by @Jaro-c in #443
  • feat(cli): create accounts from the command line (mail account-add) by @Jaro-c in #444
  • test(sieve): cover glob matching, literals and envelope edges by @Jaro-c in #445
  • test(smtp): cover SCRAM auth failure and prompt paths by @Jaro-c in #446
  • test(mtasts): cover policy discovery error paths by @Jaro-c in #447
  • test(imap): cover AUTHENTICATE failure and continuation paths by @Jaro-c in #448
  • test(spf): cover DNS-failure, address-family and budget paths by @Jaro-c in #449
  • test(dmarc): cover outcome keywords, From edges and org fallback by @Jaro-c in #450
  • test(sieve): cover reject, vacation tags, else and nested stop by @Jaro-c in #451
  • test(queue): cover outbound client reply-parsing errors by @Jaro-c in #452
  • test(pop3): cover server connection lifecycle paths by @Jaro-c in #453
  • test(imap): cover server loop error and lifecycle paths by @Jaro-c in #454
  • test(pop3): cover the maildir mailbox backend by @Jaro-c in #455
  • test(config): cover secret, ACME, alias and listener validation by @Jaro-c in #456
  • test(storage): cover DKIM signing of relayed mail by @Jaro-c in #457
  • test(dkim): cover signing edge cases and RSA key errors by @Jaro-c in #458
  • test(dkim): cover signature parsing error paths by @Jaro-c in #459
  • test(oauth): cover RS256 build, sub fallback and Debug by @Jaro-c in #460
  • test(imap): cover quoted-printable BINARY decoding by @Jaro-c in #461
  • test(jmap): cover Mailbox/set update/destroy and get id filter by @Jaro-c in #462
  • test(imap): cover command parser argument errors by @Jaro-c in #463
  • test(dkim): cover verify keywords and header-parsing edges by @Jaro-c in #464
  • test(sieve): cover variable expansion edge cases by @Jaro-c in #465
  • test(smtp): cover malformed base64 in AUTH PLAIN/LOGIN by @Jaro-c in #466
  • test(storage): cover vacation suppression and dedup by @Jaro-c in #467
  • test(acme): cover HTTP-01 challenge router over HTTP by @Jaro-c in #468
  • test(imap): cover the QRESYNC vanished expunge log by @Jaro-c in #469
  • test(cli): cover command dispatch over real configs by @Jaro-c in #470
  • test(smtp): cover AUTH LOGIN over a STARTTLS connection by @Jaro-c in #471
  • test(imap): cover APPEND literal collection over TLS by @Jaro-c in #472
  • test(imap): cover AUTHENTICATE LOGIN continuation over TLS by @Jaro-c in #473
  • test(imap): cover IDLE then DONE resuming command mode by @Jaro-c in #474
  • test(imap): cover IDLE poll pushing EXISTS on new mail by @Jaro-c in #475
  • test(servers): cover idle/command timeouts via paused clock by @Jaro-c in #476
  • test(imap): cover idle-timeout during IDLE; dedupe read_until by @Jaro-c in #477
  • feat(webhook): event poster with optional HMAC signing by @Jaro-c in #478
  • feat(webhook): fire MessageReceived on local delivery by @Jaro-c in #479
  • feat(webhook): include Message-ID in MessageReceived by @Jaro-c in #480
  • feat(webhook): DeliveryFailed event on permanent bounce by @Jaro-c in #481
  • feat(config): require https for non-loopback webhook URLs by @Jaro-c in #482
  • feat(metrics): count webhook deliveries and failures by @Jaro-c in #483
  • feat(jmap): /changes methods report cannotCalculateChanges by @Jaro-c in #484
  • docs: update README status, features and roadmap by @Jaro-c in #485
  • feat(smtp): capture per-recipient NOTIFY (RFC 3461), part 1 by @Jaro-c in #486
  • feat(smtp): honor NOTIFY=NEVER, suppress bounces (RFC 3461), part 2 by @Jaro-c in #487
  • docs: drop DSN NOTIFY from the roadmap by @Jaro-c in #488
  • feat(jmap): implement blob download endpoint by @Jaro-c in #489
  • chore(deps): bump actions/checkout from 6.0.3 to 7.0.0 by @dependabot[bot] in #491
  • chore(deps): bump Glyndor/.github/.github/workflows/rust-audit.yml from 1.0.0 to 1.1.0 by @dependabot[bot] in #376
  • chore(deps): bump Glyndor/.github/.github/workflows/line-limit.yml from 1.0.0 to 1.1.0 by @dependabot[bot] in #375
  • chore(deps): bump Glyndor/.github/.github/workflows/rust-supply-chain.yml from 1.0.0 to 1.1.0 by @dependabot[bot] in #374
  • chore(deps): bump Glyndor/.github/.github/workflows/dco.yml from 1.0.0 to 1.1.0 by @dependabot[bot] in #373
  • feat(jmap): implement blob upload endpoint by @Jaro-c in #490
  • fix(config,acme): close secrets-hygiene gaps by @Jaro-c in #492
  • chore: release 0.3.0 by @Jaro-c in #493
  • ci(release): sign release artifacts with the org Ed25519 key by @Jaro-c in #495
  • release: 0.3.0 by @Jaro-c in #494

New Contributors

Full Changelog: v0.2.0...v0.3.0