github stalwartlabs/stalwart v0.16.24

4 hours ago

[0.16.24] - 2026-09-27

If you are upgrading from v0.16.x, replace the binary (or run docker pull). If you are upgrading from v0.15.x and below, please read the upgrading documentation for more information on how to upgrade from previous versions.

Added

  • DNS: PowerDNS Authoritative provider for automatic DNS record management.

Changed

Fixed

  • Troubleshoot tool: TLSA records are looked up for every MX host, including hosts whose zone is not DNSSEC signed.
  • Spam filter:
    • OpenPhish and PhishTank entries containing uppercase characters never match, since message URLs are lowercased while HTTP lookup entries keep their original case. HTTP lookups now match keys case-insensitively.
    • URL shortener links are followed using the lowercased URL, so case-sensitive short links resolve to the wrong destination or not at all.
    • Incremental training never advances its position past the first run, so every retained sample added since then is trained again, and counted again in the reservoir, on each run until it expires.
    • Updating the rules only adds new objects, so upstream changes to existing rules, DNSBL servers, HTTP lookups, lookup keys and file extensions never reach an existing installation.
    • Updating the rules reports success when objects fail to import, or when a configuration error stops the updated settings from being activated.
  • JMAP:
    • A PushSubscription created within the verification rate limit window of another one on the same account never receives its PushVerification, since the blocked verification is dropped instead of being sent once the window expires.
    • A push notification retried after a failed delivery can report an older state than a change queued during the failed attempt, since the older state changes are merged last and overwrite the newer ones.
    • Changes made while a push request is in flight are not delivered until the next change reaches the same subscription, since a successful delivery cancels the pending retry.
    • The VAPID aud claim is derived from a hand-written parse of the push URL, so a crafted push URL can make the server sign a token for a push service other than the one the request is sent to.
    • Email/import rejects a blobId that refers to a Blob/upload creation id in the same request ("#u0") with Invalid blob id..
    • Email/set with a full mailboxIds object identical to the current mailboxes, together with a keyword change, stores the message with IMAP UID 0, so IMAP clients stop seeing it.
  • MTA:
    • A node without the outboundMta role stops replying to DATA and to JMAP submissions once about 1024 messages have been queued on it.
    • MX records are resolved through the DNSSEC-validating resolver even when DANE is disabled.
    • A DATA stage Sieve script does not see headers added by milters or MTA hooks, and discards every milter and MTA hook change when it edits the message.
  • MySQL: Range deletions and search index removals start with a single unbounded DELETE and switch to chunks only after a timeout.
  • IMAP: COPY and MOVE fail with NO [CONTACTADMIN] when another session changes the same message at the same time.
  • Autodiscover: Implicit TLS ports (993, 995, 465) are advertised with <Encryption>TLS</Encryption>, which Outlook reads as STARTTLS.
  • HTTP: Idle keep-alive connections are never closed.

Check binary attestation here

Don't miss a new stalwart release

NewReleases is sending notifications on new releases.