v0.16.25

stalwartlabs/stalwartv0.16.25Oct 5, 2026by github-actions[bot]

Upgrading?

AI Summary

This release focuses on fixing critical bugs across the mail server infrastructure, including issues with JMAP multi-domain handling, Autodiscover schema responses, IMAP authentication timeouts, and DKIM rotation logic. It also resolves problems with the Spam filter, MTA queue enforcement, and WebUI startup errors.

Key Highlights

  • Fixed JMAP `MaskedEmail` creation failure for accounts with addresses on multiple domains.
  • Fixed Autodiscover returning incorrect schema (Outlook instead of ActiveSync).
  • Improved IMAP authentication error handling to prevent connection timeouts.
  • Resolved DKIM rotation issues related to manual DNS management and failed propagation.
  • Fixed Spam filter behavior regarding Pyzor digests and DNSBL caching.

Full Release Notes

## [0.16.25] - 2026-10-05

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](https://github.com/stalwartlabs/stalwart/blob/main/UPGRADING/v0_16.md) for more information on how to upgrade from previous versions.

## Added

## Changed

## Fixed
- JMAP: Creating a `MaskedEmail` with `emailDomain` fails with `forbidden` for every domain when the account has addresses on more than one domain.
- Autodiscover: Requests for a response schema other than Outlook's, such as ActiveSync (`mobilesync`), are answered with the Outlook settings instead of error 601.
- IMAP:
  - `LOGIN` and `AUTHENTICATE` with a wrong, expired or unknown app password or API key are answered with an untagged `NO`, so clients keep waiting for the command to complete until the connection times out.
  - The failed login that exceeds the maximum number of authentication failures is answered with an untagged `NO` before the connection is closed.
- DKIM:
  - A rotation moves the active key to retiring even when its successor fails to publish or propagate, so outgoing mail is sent unsigned until a retry publishes the new key. The DNS write failure is also not logged and the task reports success.
  - Keys created while DNS management was manual, or before DKIM was added to the published records, are never rotated after DNS management becomes automatic. Domains already affected start rotating once a `DkimManagement` task is created for them.
  - After switching DNS management from automatic to manual, a due rotation activates a new key that was never published in DNS, so signatures fail verification, and retiring the old key is retried forever.
- Spam filter:
  - Messages with no text line long enough for a Pyzor digest are checked with the digest of empty input and tagged `PYZOR`.
  - DNSBL answers with several return codes, such as a Spamhaus ZEN listing in both SBL and PBL, are scored for only the first code returned.
  - DNSBL lookups that return "not listed" are cached for 24 hours regardless of the zone's negative TTL.
  - Removing a duplicate training sample of a message reclassified on the same day clears the blob link of the sample that is kept.
- MTA: Queue quotas with an empty `match` expression are never enforced, including the global queue quota created on first start.
- RocksDB: The info log (`LOG`, `LOG.old.*`) grows without limit because log rotation and retention are left at RocksDB defaults.
- WebUI: A blob store read error at startup, such as an S3 authentication failure, stops the web interface from being downloaded.


<hr />

### Check binary attestation [here](https://github.com/stalwartlabs/stalwart/attestations/52732142)

Related Repositories