VersionDrift
Product

Stalwart Mail Server 1.0.1 → 1.1.0

3 releases · 0 breaking changes · 0 security fixes · 0 advisories fixed

0security0breaking0deprecated31feature54fix

Breaking changes

None in the release notes.

Security changes

None in the release notes.

Every release in between

featurePasskeys (WebAuthn) for accounts in the internal directory:
featurePasswordless sign-in on the built-in login page, for the authorization code and device flows, with a "Sign in with a passkey" button and browser autofill. Passkeys are not a second factor: signing in with a passkey does not ask for the TOTP code.
featurePasskey objects (x:Passkey) to register, list, rename and delete passkeys, with the new x:Passkey/registrationOptions method. Registering a passkey requires the current password, and the TOTP code when one is set. Passkeys are listed in the WebUI under Account > Credentials.
featureES256, Ed25519 and RS256 keys, with attestation none or self-attested packed.
featuremaxPasskeys limit per account (default 10) in the Authentication settings, and as a per-account quota.
featureThe relying party ID is the host of the public URL, so the WebUI must run on that host or one of its subdomains.
featureStalwart Keep as an in-memory store, lookup store, cluster coordinator and cache swap store (keep feature).
fixMTA:
fixThe reply after the message data is now read with dataTimeout instead of rcptToTimeout.
fixShutdown now drains outbound deliveries in progress (up to 8 seconds) and releases their queue locks, so a restart no longer causes duplicate deliveries or a 10 minute delay in clusters.
fixA queue update that fails after a successful delivery (for example during a database failover) is now retried while the queue lock is held, instead of the message being delivered again.
fixIn clusters, a node that takes over a queued message now reads it at the latest committed version (FoundationDB) or from the primary (SQL read replicas), so a message another node has just delivered is not delivered again and its queue quota is not released twice.
fixMilter header edits follow libmilter: SMFIR_ADDHEADER appends, SMFIR_INSHEADER inserts at its position in the whole header list, folded values are written with CRLF, and values that are not UTF-8 are accepted (also MTA hook header edits).
fixJMAP:
fixPushSubscription/get now returns the verificationCode of verified subscriptions instead of always returning null.
fixFileNode/set rejects a Directory role that another Directory in the account already has (draft-ietf-jmap-filenode-20), and FileNode/copy no longer copies role.
fixEmail/set body parts with a raw header:Content-Type (or Content-Disposition) no longer get a second, generated header field; giving the same header field both raw and through a body part property (type, disposition, cid, ...) is rejected with invalidProperties.
fixCalendar: an RSVP (JMAP or CalDAV) on an invitation that was stored without scheduling now sends the iTIP REPLY to the organizer.
fixDKIM: a signature whose DNS record cannot be built (such as a DKIM2 ML-DSA-44 key created before v1.0.2) no longer stops publishing, rotation and deletion of the domain's other DKIM signatures.
fixACME: Domain subjectAlternativeNames are validated on save; a name containing a dot that is outside the domain and its aliases and has no public suffix (such as webmail.test) is rejected instead of failing every renewal.
fixStorage:
fixMySQL/MariaDB: connections no longer switch to the local Unix socket reported by the server (@@socket), which could reach a different local server than the configured host.
fixSQLite: a path that is a directory now stores the database there as stalwart.db (the setup wizard carried the RocksDB directory over), and the field is described as a database file.
fixPostgreSQL: the wait for server replies is bounded by the new responseTimeout setting (default 2m) and the login handshake by connectTimeout; /healthz/ready returns 503 while the data store is not answering.
fixBootstrap: New installations set up with an external directory (LDAP, SQL, OIDC) now get the default roles, so directory users can log in.
fixCluster: Notifications over Redis/Valkey: subscribing is bounded by connectTimeout and idle subscriptions are pinged every 15 seconds, so a dead or unresponsive server is detected and the subscription is re-established.
fixNetwork: Listeners on a wildcard address (0.0.0.0 or ::) now start when the kernel binds them to a specific address, such as in FreeBSD jails without VNET.
fixEnterprise:
fixAfter a lapsed license is renewed, the metrics and tracing stores and the data store read replicas are restored without a restart.
fixQueued messages and their contents are now scoped to the tenant that owns them.
fixACME renewal rejects certificates naming identifiers that were not ordered, and tenant domains can only request certificate names within the domain or its aliases (an existing tenant domain with other names stops renewing until they are removed).
fixSuccessful Enterprise license renewals are now logged, with the new key's account limit and validity period.
featureApps registered in Stalwart: add the scopes the app needs to its OAuthClient scopes (only a superuser can allow full), and have the app request them.
otherApps signing in through an external OpenID Connect provider: create the scopes in the provider and assign them to the apps that need them.
otherWebUI: no action needed.
featureBlob storage:
featureBlob encryption at rest. Blobs can be encrypted by the server with symmetric keys (AES-256-GCM or ChaCha20-Poly1305) defined as SymmetricKey objects.
featureZstandard compression for blobs (zstd in compressionAlgorithm).
featureBlobRecode task, which rewrites stored blobs with a chosen compression and encryption.
featureSTALWART_UPDATE_ROLE_PERMISSIONS environment variable. When set to true (or 1), startup adds to each default role every permission introduced after v1.0.0 that a new install would give that role and that the role is missing.
featureOAuth: Stalwart scopes urn:stalwart:oauth:scope:security, urn:stalwart:oauth:scope:settings and urn:stalwart:oauth:scope:full, so clients signing in through Stalwart or an external OpenID Connect provider can manage app passwords, API keys and account settings.
fixJMAP:
fix/copy methods called with the same accountId and fromAccountId return a clear error message.
fixPushSubscription objects created with an empty types list no longer receive StateChange notifications, and EmailPush notifications are delivered regardless of types.
fixIMAP SEARCH accepts up to 32 levels of nested filters, so free-text searches from Apple Mail no longer fail with Too many nested filters.
fixOIDC: Bearer tokens are routed to the OpenID Connect directory whose issuer matches before the domain in their claims is tried, so a claim naming a domain the server does not host no longer sends the token to the default directory.
fixSecurity: Editing a default role, or a role nested in one, now invalidates the cached access tokens of accounts and groups that use the default role sets.
featureEncryption:
featureOpenPGP (RFC 9580): v4 and v6 keys; RSA (2048 to 8192 bits), ECDH on NIST P-256, P-384 and P-521, legacy Curve25519, X25519 and X448 encryption keys; SEIPD v1 and SEIPD v2 with AES-OCB or AES-GCM, selected from the key's features and preferences.
featurePost-quantum OpenPGP (RFC 9980): ML-KEM-768+X25519 and ML-KEM-1024+X448 keys, with AES-256.
featureS/MIME (RFC 8551): RSA with PKCS #1 v1.5 or RSA-OAEP, ECDH on NIST P-256, P-384 and P-521, X25519 and X448 (RFC 8418) and post-quantum ML-KEM-512, ML-KEM-768 and ML-KEM-1024 (RFC 9936) certificates; CMS EnvelopedData with AES-256-CBC and AuthEnvelopedData with AES-256-GCM (RFC 5083).
featureHeader protection (RFC 9788) for encrypted messages, including Subject hiding and legacy display for messages sent through the gateway.
featurePublic keys: per-key authenticatedEncryption (AES-GCM with RSA-OAEP) and strictKeyWrapEncoding (RFC 5753 encoding instead of the Outlook-compatible one) switches, and server-computed keyType, fingerprints, capabilities and warnings (expiring soon, weak RSA, address mismatch, post-quantum only, no…
featureEncryption gateway: encrypts outgoing messages for remote recipients with their OpenPGP keys or S/MIME certificates, with a per-recipient gatewayOutbound policy (disable, opportunistic or required), a minimum key trust level, a separate encrypted copy per recipient with its own DKIM and DKIM2…
featureExternal public keys: superuser-managed keys of remote recipients, entered manually or kept up to date from Web Key Directory (WKD), keys.openpgp.org (VKS), HKP keyservers or DNSSEC-validated OPENPGPKEY (RFC 7929) and SMIMEA (RFC 8162) records, with trust levels, pinning, approval of key changes,…
featureKey harvesting: S/MIME certificates (with their advertised capabilities) and Autocrypt keys are learned from DMARC-authenticated incoming mail, controlled by the harvestKeys expression.
featureS/MIME certificate trust: bundled Mozilla email root certificates, custom trust anchors (SmimeTrustAnchor), intermediate certificate retrieval through Authority Information Access and daily certificate revocation list checks.
featureNew encryption.* telemetry events and metrics, including the encryption.key-lookup-time histogram.
featureDKIM2:
featureDSNs are signed with a domain that matches a recipient in the rt= of the reported message, as required by spec-08 section 16.2. When no hosted domain matches, the DSN is signed with DKIM only.
featureDSNs about forwarded messages are propagated to the previous hop in the DKIM2 chain, with the forwarding destination removed and the returned headers restored to how the message arrived (spec-08 section 16.3). This applies to inbound DKIM2 DSNs and to DSNs generated for messages Stalwart…
featureNew dkim2.dsn-not-aligned and dkim2.dsn-propagated telemetry events.
featureOAuth: Application objects have an oauthScopes list of extra scopes that the WebUI requests at sign-in, for external identity providers that release a claim only with a scope of its own.
featureOIDC directories: superuser-only trustedProvider setting lets a tenant-owned directory reach an identity provider on a private network.
fixDKIM: Relaxed body canonicalization ignores whitespace-only lines at the end of the body (RFC 6376, section 3.4.4), which produced a bh= that other implementations rejected.
fixiTIP: A full REQUEST with an older SEQUENCE no longer removes a newer override from the attendee's copy (RFC 5546, section 2.1.5).
fixApplications: A cached application bundle that failed the manifest check (such as the WebUI 1.x bundle left by v0.16 in a shared blob store) was never replaced, so /admin and /account returned 404; it is now downloaded again.
fixHTTP: Error responses sent before the request body is read (such as a 401) include Connection: close, instead of the connection being closed without notice.
fixHTTP: A response with an invalid header value, such as a JMAP download whose accept parameter contains a line break, returns 500 instead of aborting the connection.
fixIMAP
fixRENAME refuses to move a mailbox into its own subtree (such as A to A/B/C) with NO [CANNOT], instead of creating a parent loop.
fixSingle-level mailbox names are checked against maxMailboxNameLength, which only applied to names containing /.
fixClient quirks are detected from the ID command, and UIDONLY is not enabled for Microsoft's sync service (Microsoft Office 365), which left the new Outlook without folders or mail.
fixMailboxes: IMAP, JMAP and Sieve fileinto accept names of up to maxMailboxNameLength octets (RFC 8621, section 1.6.1); JMAP Mailbox/set rejected names of exactly that length.
fixJMAP
fixMessages added with IMAP APPEND/MULTIAPPEND or Email/import send an EmailPush with their id, so push subscribers no longer get an empty notification.
fixEmail/queryChanges with collapseThreads reports the previous representative of a thread as removed when a newer email joins the thread, and adds it back when that email is destroyed.
fixEmail/set places inline attachments that have a cid (image, audio or video, disposition not attachment) in multipart/related with the HTML body instead of multipart/mixed, so clients display them in the message body and Email/get returns them in attachments.
fixEmail/get, Email/set, Email/copy and SearchSnippet/get return notFound for an Email id destroyed by a thread merge instead of resolving it with the stale threadId.
fixThe upload endpoint rejects uploads to accounts the caller is not a member of and to account ids that do not exist, as Blob/upload already did.
fixOAuth: Scope values the server does not know, such as the OpenID Connect email and profile scopes, are ignored at the authorization endpoint instead of failing with invalid_scope (OpenID Connect Core, section 3.1.2.1).
fixOAuth: App passwords and API keys are refused at interactive sign-in (WebUI login and device code approval), which issued a session with the account's full permissions and skipped two-factor authentication.
fixMilter
fixSMFIC_BODY carries only the message body instead of the whole message, so milters no longer receive the headers twice.
fixHeader names and values that are not valid UTF-8 are sent to the milter as raw bytes instead of empty strings.
fixSearch indexing
fixAn email whose blob is missing is logged and skipped instead of failing its whole index partition and being retried forever.
+8 more items in the release notes
See how far your stack has drifted from upstream. Release data from vendors’ own sources · feed under CC BY 4.0 · Code under AGPL-3.0 Settings Feed status