v0.16.21

stalwartlabs/stalwartv0.16.21Sep 6, 2026by github-actions[bot]

AI Summary

This release focuses on stability and security improvements across JMAP, IMAP, and MTA components, including fixes for calendar recurrence handling and spam filtering. It introduces a new configuration option for DKIM signing in Sieve scripts.

Key Highlights

  • Sieve scripts now support DKIM signing via the new `SieveUserInterpreter.dkimSignDomain` setting.
  • JMAP calendar and address book requests now return all properties when the properties argument is omitted.
  • IMAP pipelined commands now receive individual tagged responses instead of dropping subsequent commands.
  • LDAP authentication security is tightened to reject accounts without passwords during unauthenticated binds.

New Features

  • Sieve DKIM signing configuration (`SieveUserInterpreter.dkimSignDomain`)

Full Release Notes

## [0.16.21] - 2026-09-06

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
- Sieve: Messages generated by user scripts are DKIM signed through the new `SieveUserInterpreter.dkimSignDomain` setting, which defaults to the account's own domain.

## Fixed
- JMAP:
  - `CalendarEvent/set` requests that ask for scheduling messages are rejected with a `forbidden` error when the account cannot send them.
  - `Calendar/get` and `AddressBook/get` return every property when the `properties` argument is omitted or `null`.
  - EventSource `ping` events advertise the interval in seconds rather than milliseconds.
  - Calendar synthetic ids returned when expanding recurrences identify an occurrence by its recurrence id.
- IMAP: Every command in a pipelined `STATUS` or `FETCH` batch receives its tagged completion, instead of the first failing command dropping the responses for all commands queued behind it.
- WebDAV: Accounts without a storage quota no longer advertise a 4 GiB limit in `DAV:quota-available-bytes`.
- MTA: Inbound DMARC and TLS aggregate reports that a reporter sends more than once are imported again as a duplicate entry.
- Spam filter: Domain and URL blocklists are queried only for text written as a link.
- iTIP: Detaching an occurrence that the recurrence rule already generates is sent as a `METHOD:REQUEST` carrying the `RECURRENCE-ID` instead of a `METHOD:ADD`.
- Sieve: `fileinto :specialuse` and `specialuse_exists` accept special-use attributes in the `\Trash` form.
- LDAP: Active Directory servers that answer an unauthenticated bind (a non-empty DN with a zero-length password) with success no longer authenticate accounts without a password.
- Network: Listeners bound to the unspecified IPv6 address (`[::]`) fall back to IPv4 when socket creation fails with `EPROTONOSUPPORT`.
- OpenTelemetry: log exporter does not include the parent span's attributes.


<hr />

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