[0.16.19] - 2026-08-24
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
- WebUI:
oauthClientIdsetting inApplication, which allows the WebUI to use a different OAuth client than the default. - Sieve:
env.spam.scoreandenv.spam.is_spamvariables, which expose the spam filter result to system scripts running at theDATAstage. - CalDAV:
vCardVersionsetting inAddressBook, which allows the default vCard version to be specified when the client does not request a specific version.
Changed
- MySQL & MariaDB: Key columns are now
VARBINARY(255)with a full-length primary key instead ofTINYBLOB. Note: Existing deployments should run, once per table, for each of the tablesa,d,e,f,g,h,j,k,l,m,n,o,p,q,r,s,t,u,w,xandythe commandALTER TABLE a MODIFY k VARBINARY(255) NOT NULL;.
Fixed
- ACME:
- Order and authorization failures are never logged, so an order rejected by the CA.
- An order rejected by the CA marks the renewal task as permanently failed.
- CalDAV:
- Attendee addresses whose
mailto:URI percent-encodes a fullname-addrare silently dropped from the scheduling snapshot. - Attendees whose calendar user address cannot be parsed should be flagged with
SCHEDULE-STATUS=3.7. - The RSVP link in an iMIP invitation stamps
PARTSTATon the organizer's copy of the event only, leaving a local attendee's own copy atNEEDS-ACTIONand sending the organizer no reply. MKCALENDAR,MKCOLandPROPPATCHstore the display name, description, time zone and the other per-user properties under the authenticated account rather than the account that owns the collection.
- Attendee addresses whose
- Directory:
- An empty column, attribute or claim returned by an external directory is synchronized as an empty string rather than a missing value.
/api/discoversplits the account name on@without accounting for the%master user separator or the recovery administrator.
- FoundationDB: Older chunked entries are not deleted.
- IMAP:
SETACLandDELETEACLfail to resolve an identifier spelled with uppercase characters. - iMIP: Invitations, replies and cancellations reference a
TZIDparameter with no matchingVTIMEZONEcomponent whenever the event was stored without one. - JMAP:
AddressBook/get: A new account's default address book is never recorded.Email/getandEmail/parsewithfetchAllBodyValuesreturn body values only for the parts listed intextBodyorhtmlBody, omitting every othertext/*part inbodyStructure.Email/setwrites display names as an RFC 2047 encoded-word wrapped in a quoted-string, which RFC 2047 forbids.Mailbox/set,AddressBook/setandCalendar/setstoreisSubscribedand the other per-user properties under the authenticated account rather than the account named in the request.Principal/queryreturns no results when thenameoremailfilter is spelled with uppercase characters.FileNode/set: File nodes created over JMAP are returned with a<D:href>holding the raw name over WebDAV.
- Meilisearch:
- Queries return at most 1000 results, as the
maxTotalHitspagination setting is left at the Meilisearch default. - Searches combining several terms return documents that match only some of them.
- A task confirmation timeout is reported as a success when
failOnTimeoutis disabled.
- Queries return at most 1000 results, as the
- Import:
--importalways aborts with the target database already containing data in the key range being imported. - MTA:
- A domain
catchAllAddresspointing to a mailing list or a sub-addressed mailbox is accepted atRCPT TOand then rejected at local delivery with550 5.5.0 Mailbox not found. is_local_address()andis_local_domain()expression functions do not match an address or domain spelled with uppercase characters.- Relay routes are rejected with
host resolves loopback address, which prevents relaying through a local proxy or tunnel.
- A domain
- MySQL, MariaDB & PostgreSQL: Range scans, range deletions and store purges run as a single unbounded statement, so on servers that enforce a statement timeout they abort on large accounts and tasks such as account deletion can never complete.
- Network:
local_portandlocal_ipreport the address Stalwart is bound to rather than the address the client connected to when the connection arrives through a trusted proxy. - Task manager:
totalDeadlineis not enforced on tasks that fail with a specific retry time.- Indexing tasks are dropped after
maxAttemptsfailures, so a search store that is unavailable or overloaded leaves messages permanently missing from the index. - Indexing tasks are dropped when the document metadata read returns no data, which can happen on SQL read replicas that have not yet caught up with the primary.
- The DNS management task republishes the DKIM records of retired keys that the DKIM rotation task had already removed from the zone.
- Sieve:
spamtestreturns only1or10(andspamtest :percentonly0or100), so scripts cannot act on intermediate spam scores. - Spam filter:
MIME_BADis tagged whenever the declaredContent-Typeof an attachment is not byte identical to the type detected from its magic bytes.