<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Stalwart | Stalwart Blog</title><description/><link>https://stalw.art/</link><language>en</language><item><title>DKIM2 and DMARCbis have landed, and Stalwart speaks them first</title><link>https://stalw.art/blog/dkim2-dmarcbis/</link><guid isPermaLink="true">https://stalw.art/blog/dkim2-dmarcbis/</guid><description>Email authentication just took its biggest step in a decade. DKIM2 rebuilds DKIM around a verifiable chain of custody that survives forwarding, stops replay, and makes bounces provable, while DMARCbis trades the Public Suffix List for a live DNS tree walk and writes a decade of operational lessons back into the spec. Both are now fully implemented in Stalwart v0.16.12, the first mail server to support them, and both can be tested straight from the browser at the mail-auth playground.

</description><pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Email authentication has quietly held the internet’s mail together for two decades, and it has just taken its biggest step forward yet. Two efforts arrived at once. &lt;strong&gt;DKIM2&lt;/strong&gt; (currently at &lt;a href=&quot;https://datatracker.ietf.org/doc/draft-ietf-dkim-dkim2-spec/&quot;&gt;draft -04&lt;/a&gt;) reworks DKIM so that a signature is no longer a lonely statement about content but one link in a verifiable chain of custody that follows a message from author to final recipient: forwarding stops breaking signatures, replayed mail no longer verifies, and a bounce can prove it is genuine. &lt;strong&gt;DMARCbis&lt;/strong&gt; (published in May 2026 as &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc9989/&quot;&gt;RFC 9989&lt;/a&gt;, &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc9990/&quot;&gt;RFC 9990&lt;/a&gt;, and &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc9991/&quot;&gt;RFC 9991&lt;/a&gt;) is the long-awaited successor to DMARC: it replaces the static Public Suffix List with a live DNS tree walk, retires the tags that never worked, and folds a decade of hard-won operational lessons back into the standard.&lt;/p&gt;
&lt;p&gt;Both matter because email authentication is what keeps a phisher from putting your bank’s domain in the &lt;code dir=&quot;auto&quot;&gt;From:&lt;/code&gt; line, and until now the machinery that does it has been showing its age. This post walks through what each protocol changes and why it matters.&lt;/p&gt;
&lt;p&gt;It is also an announcement. As of &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/releases&quot;&gt;Stalwart v0.16.12&lt;/a&gt;, both DKIM2 and DMARCbis are fully implemented, and Stalwart is the first mail server to support them. Anyone curious can sign and verify DKIM2 messages, and run DMARCbis checks, directly from the browser at the &lt;a href=&quot;https://mail-auth.stalw.art&quot;&gt;mail-auth playground&lt;/a&gt;, no install required. More on that at the end; first, the protocols.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;meet-dkim2&quot;&gt;Meet DKIM2&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;DKIM (DomainKeys Identified Mail, &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc6376&quot;&gt;RFC 6376&lt;/a&gt;) does one deceptively simple thing: it lets a domain take responsibility for a message. The sending server hashes a chosen set of header fields and the body, signs the result with a private key, and staples the outcome to the message in a &lt;code dir=&quot;auto&quot;&gt;DKIM-Signature&lt;/code&gt; header. The matching public key lives in DNS at &lt;code dir=&quot;auto&quot;&gt;selector._domainkey.domain&lt;/code&gt;, so any receiver can fetch it, recompute the hashes, and confirm two things: the message really was authorised by that domain, and nothing covered by the signature changed along the way.&lt;/p&gt;
&lt;p&gt;That is the whole promise. A valid signature means “this domain vouches for this content.” It says nothing about who the message was for, where it has been, or where it is going next. For nearly twenty years that was enough, and DKIM quietly became one of the load-bearing walls of email authentication.&lt;/p&gt;
&lt;p&gt;On its own, a DKIM pass is just a true statement about some domain. &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc9989/&quot;&gt;DMARC&lt;/a&gt; is what turns it into a decision. DMARC ties authentication to the domain a human actually sees, the one in the &lt;code dir=&quot;auto&quot;&gt;From:&lt;/code&gt; header, through a rule called &lt;strong&gt;identifier alignment&lt;/strong&gt;: a DKIM result only counts toward DMARC if the signing domain (&lt;code dir=&quot;auto&quot;&gt;d=&lt;/code&gt;) lines up with the &lt;code dir=&quot;auto&quot;&gt;From:&lt;/code&gt; domain. Pass alignment on either DKIM or SPF and the message clears DMARC; fail both and it meets the domain’s published policy, which can mean quarantine or outright rejection.&lt;/p&gt;
&lt;p&gt;This is exactly why a broken DKIM signature is not a cosmetic problem. When DKIM breaks on a message from a domain publishing &lt;code dir=&quot;auto&quot;&gt;p=reject&lt;/code&gt;, and SPF cannot save it either, that message is gone. Which brings us to the reason DKIM2 exists: over two decades of real-world routing, DKIM1 signatures break far more often than anyone would like, and in a few cases they hold when we wish they wouldn’t.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;issues-with-dkim1&quot;&gt;Issues with DKIM1&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;None of what follows is a knock on the original design. These are the seams that two decades of deployment pulled apart, and they are the exact list DKIM2 sets out to close.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Anyone could be the recipient.&lt;/strong&gt; A DKIM1 signature is bound to the content, not to a destination. Capture one legitimately signed message and you can replay it to millions of other addresses, unchanged, and every copy still verifies. The replay rides on the original signer’s good reputation, which is precisely what makes it valuable to abusers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Forwarding breaks the signature, silently and ambiguously.&lt;/strong&gt; The moment a mailing list tags a subject, a gateway rewrites a link, or a forwarder appends a footer, the signed hashes no longer match and the signature fails. Worse, a verifier cannot tell an innocent &lt;code dir=&quot;auto&quot;&gt;[list]&lt;/code&gt; prefix from wholesale replacement by an attacker. Both look identical: broken.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;There was no record of the road travelled.&lt;/strong&gt; DKIM1 leaves no trustworthy trace of the path a message took. The &lt;code dir=&quot;auto&quot;&gt;Received&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;Return-Path&lt;/code&gt; headers are unauthenticated and trivial to forge, so there is no chain of custody to reason about.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ARC was a patch that receivers struggle to trust.&lt;/strong&gt; &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8617&quot;&gt;ARC&lt;/a&gt; tried to preserve authentication across intermediaries by having each hop attest to what it saw, but it sits alongside DKIM as a separate overlay, and in practice most receivers report that they cannot confidently trust ARC seals.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Header signing was inconsistent.&lt;/strong&gt; DKIM1 lets the signer choose which headers to cover and offers multiple canonicalization modes, which leaves gaps an attacker can slip unsigned headers through and makes signatures needlessly fragile.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Bounces could not be trusted, and hurt bystanders.&lt;/strong&gt; Because the return path can name a domain that never handled the message, a Delivery Status Notification (DSN) can land on a forged, innocent third party. This is &lt;strong&gt;backscatter&lt;/strong&gt;, and the fear of it is why deferred bounces, the kind a provider would send after deciding a message is spam an hour later, are largely impractical today.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Feedback was ad hoc.&lt;/strong&gt; Intermediaries and senders exchange informal signals about how mail is performing, but there is no standard for requesting or routing that feedback, so it is inconsistent and often unhelpful.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;dkim2-in-a-nutshell&quot;&gt;DKIM2, in a nutshell&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;DKIM2 keeps everything that worked and changes the thing that did not. The cryptography is familiar: hash the message, sign it, publish the public key in DNS at the same &lt;code dir=&quot;auto&quot;&gt;_domainkey&lt;/code&gt; location DKIM1 already uses. What changes is that a signature stops being a lonely statement about content and becomes one link in a &lt;strong&gt;verifiable chain of custody&lt;/strong&gt; that follows the message from originator to final recipient.&lt;/p&gt;
&lt;p&gt;To do that, DKIM2 splits the old single header into two, each with its own job.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;Message-Instance&lt;/code&gt;&lt;/strong&gt; header describes the message at a point in time. It carries a revision number, a set of cryptographic fingerprints over the headers and body at that revision, and, when a hop has changed something, a compact “recipe” that spells out how to undo the change (the mechanism covered later that makes forwarding survivable).&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;DKIM2-Signature&lt;/code&gt;&lt;/strong&gt; header records the envelope the message actually travelled with, then signs over it. Alongside the familiar DKIM pieces, the signing domain, the selector, the signature itself and a timestamp, it captures the SMTP &lt;code dir=&quot;auto&quot;&gt;MAIL FROM&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;RCPT TO&lt;/code&gt; of that hop, a sequence number so the signatures form an ordered chain, and a small set of flags that a sender or intermediary can raise to forbid fan-out, mark legitimate fan-out, or request feedback. Putting the envelope inside the signature is what lets consecutive hops be checked for consistency; recording who signed and in what order is what turns a pile of signatures into a chain.&lt;/p&gt;
&lt;p&gt;Two counters drive everything. One counts signatures, one per hop. The other counts message revisions, incremented only when a hop actually changes the content. A purely transparent forwarder that touches nothing does not even need to be DKIM2-aware.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;one-mechanism-per-broken-promise&quot;&gt;One mechanism per broken promise&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The elegance of DKIM2 is that a handful of mechanisms retire the whole list above at once.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Replay&lt;/strong&gt; is answered by putting the envelope inside the signature. Each &lt;code dir=&quot;auto&quot;&gt;DKIM2-Signature&lt;/code&gt; records the &lt;code dir=&quot;auto&quot;&gt;MAIL FROM&lt;/code&gt; (&lt;code dir=&quot;auto&quot;&gt;mf=&lt;/code&gt;) and &lt;code dir=&quot;auto&quot;&gt;RCPT TO&lt;/code&gt; (&lt;code dir=&quot;auto&quot;&gt;rt=&lt;/code&gt;) it was sent with, and consecutive hops must line up: the sending domain of one hop has to match a recipient domain of the previous one. A message replayed to a different recipient no longer forms a valid chain. A sender can add &lt;code dir=&quot;auto&quot;&gt;donotexplode&lt;/code&gt; to forbid fan-out, and a mailing list marks legitimate fan-out with &lt;code dir=&quot;auto&quot;&gt;exploded&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Forwarding breakage&lt;/strong&gt; is answered by recipes. A hop that modifies the message records a reversible recipe, so downstream verifiers can undo the change and re-check every earlier signature instead of throwing the whole thing out.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The missing chain of custody&lt;/strong&gt; is the chain itself: each hop appends its own signature over the current snapshot and all prior signatures, forming a tamper-evident sequence from author to recipient.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ARC’s role&lt;/strong&gt; is absorbed natively. The chain does what ARC attempted, without a parallel set of headers, and DKIM2 explicitly ignores both legacy &lt;code dir=&quot;auto&quot;&gt;DKIM-Signature&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;ARC-*&lt;/code&gt; headers so the two schemes can coexist during migration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Inconsistent header signing&lt;/strong&gt; is answered by a single fixed canonicalization and a defined hashing scheme, removing the per-signer guesswork.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Backscatter&lt;/strong&gt; is answered by routing bounces along the recorded chain, covered next.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Feedback&lt;/strong&gt; gets a standard channel through the &lt;code dir=&quot;auto&quot;&gt;feedback&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;feedhere&lt;/code&gt; flags.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One caveat, contrary to a common claim: DKIM2 can require &lt;em&gt;more&lt;/em&gt; signature checks, not fewer. A modified message adds a signature at every hop, and a verifier may need to check the whole chain. What the draft does allow is checking the most recently applied signature first and stopping at the first failure, so an unmodified message can often be cleared with a single verification.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;recipes-putting-a-message-back-the-way-it-was&quot;&gt;Recipes: putting a message back the way it was&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;This is the mechanism that makes forwarding survivable, so it is worth seeing in full.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;recipe&lt;/strong&gt; is a small JSON object, base64-encoded into the &lt;code dir=&quot;auto&quot;&gt;r=&lt;/code&gt; tag, that tells a verifier how to turn the &lt;em&gt;current&lt;/em&gt; message back into the &lt;em&gt;previous&lt;/em&gt; one. It has two optional parts, &lt;code dir=&quot;auto&quot;&gt;&quot;h&quot;&lt;/code&gt; for header fields and &lt;code dir=&quot;auto&quot;&gt;&quot;b&quot;&lt;/code&gt; for the body, and each is a list of steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;{&quot;c&quot;: [start, end]}&lt;/code&gt; copies a range of lines or header instances from the current message, inclusive.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;{&quot;d&quot;: [&quot;value&quot;, ...]}&lt;/code&gt; inserts literal values that used to be there.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Two numbering rules matter. Header instances are counted &lt;strong&gt;bottom-up&lt;/strong&gt; (the last &lt;code dir=&quot;auto&quot;&gt;Subject:&lt;/code&gt; is number 1, the one above it is 2), and body lines are counted &lt;strong&gt;top-down&lt;/strong&gt; (the first line is 1). An empty step list &lt;code dir=&quot;auto&quot;&gt;[]&lt;/code&gt; for a header means “remove every instance.” A body recipe of &lt;code dir=&quot;auto&quot;&gt;null&lt;/code&gt; is a special case: it means the previous body genuinely cannot be reconstructed, which a verifier may accept from an entity it trusts, for example a contractually arranged redaction service.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;a-message-through-two-hops&quot;&gt;A message through two hops&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;Alice sends a note to a mailing list.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hop 1, the originator signs.&lt;/strong&gt; The message leaves &lt;code dir=&quot;auto&quot;&gt;example.com&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;From: alice@example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;To: list@lists.example.org&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Subject: Trip report&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Had a great time.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;See you soon.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;She stamps it with the first revision and the first signature (hashes abbreviated):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Message-Instance: m=1; h=sha256:Hh1...:Bh1...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;DKIM2-Signature: i=1; m=1; t=1782394336; d=example.com;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;s=ed25519:ed25519-sha256:rDU9v...;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;mf=PGFsaWNlQGV4YW1wbGUuY29tPg==;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;rt=PGxpc3RAbGlzdHMuZXhhbXBsZS5vcmc+&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;mf=&lt;/code&gt; value decodes to &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;alice@example.com&gt;&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;rt=&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;list@lists.example.org&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hop 2, the list revises.&lt;/strong&gt; The list software tags the subject and appends an unsubscribe footer, so the message is now:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;From: alice@example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;To: list@lists.example.org&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Subject: [list] Trip report&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Had a great time.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;See you soon.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;--&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Unsubscribe: https://lists.example.org/u&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Two things changed: the subject gained a &lt;code dir=&quot;auto&quot;&gt;[list]&lt;/code&gt; prefix, and two lines were appended. The list computes the recipe that reverses both. The subject (one instance, so number 1) is replaced with its old literal value, and the body copies the two original lines while dropping the footer:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;h&quot;&lt;/span&gt;&lt;span&gt;:{&lt;/span&gt;&lt;span&gt;&quot;subject&quot;&lt;/span&gt;&lt;span&gt;:[{&lt;/span&gt;&lt;span&gt;&quot;d&quot;&lt;/span&gt;&lt;span&gt;:[&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Trip report&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;]}]},&lt;/span&gt;&lt;span&gt;&quot;b&quot;&lt;/span&gt;&lt;span&gt;:[{&lt;/span&gt;&lt;span&gt;&quot;c&quot;&lt;/span&gt;&lt;span&gt;:[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;]}]}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Read the body step as “to rebuild the previous body, copy current lines 1 through 2, and stop.” The footer at current lines 3 and 4 simply is not copied, so it disappears on reversal. The list base64-encodes that JSON into &lt;code dir=&quot;auto&quot;&gt;r=&lt;/code&gt;, records a fresh fingerprint, and adds its own signature:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Message-Instance: m=2; h=sha256:Hh2...:Bh2...;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;r=eyJoIjp7InN1YmplY3QiOlt7ImQiOlsiVHJpcCByZXBvcnQiXX1dfSwiYiI6W3siYyI6WzEsMl19XX0=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;DKIM2-Signature: i=2; m=2; t=1782394500; d=lists.example.org;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;s=ed25519:ed25519-sha256:9aBc...;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;mf=PGJvdW5jZXNAbGlzdHMuZXhhbXBsZS5vcmc+;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;rt=PGJvYkBleGFtcGxlLm5ldD4=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The chain of custody holds because hop 2’s &lt;code dir=&quot;auto&quot;&gt;mf=&lt;/code&gt; domain (&lt;code dir=&quot;auto&quot;&gt;lists.example.org&lt;/code&gt;) matches hop 1’s &lt;code dir=&quot;auto&quot;&gt;rt=&lt;/code&gt; domain (&lt;code dir=&quot;auto&quot;&gt;lists.example.org&lt;/code&gt;), and &lt;code dir=&quot;auto&quot;&gt;d=lists.example.org&lt;/code&gt; matches the rightmost labels of that &lt;code dir=&quot;auto&quot;&gt;mf=&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Final recipient, Bob, verifies.&lt;/strong&gt; His server works backwards:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check the chain lines up: hop 2’s sending domain matches hop 1’s recipient domain. Good, no replay.&lt;/li&gt;
&lt;li&gt;Verify each signature’s cryptography over its reconstructed input.&lt;/li&gt;
&lt;li&gt;Recompute the &lt;code dir=&quot;auto&quot;&gt;m=2&lt;/code&gt; fingerprint against the message as received. It matches.&lt;/li&gt;
&lt;li&gt;Apply the &lt;code dir=&quot;auto&quot;&gt;r=&lt;/code&gt; recipe to rebuild the &lt;code dir=&quot;auto&quot;&gt;m=1&lt;/code&gt; message: restore the subject to &lt;code dir=&quot;auto&quot;&gt;Trip report&lt;/code&gt; and drop the footer.&lt;/li&gt;
&lt;li&gt;Recompute the &lt;code dir=&quot;auto&quot;&gt;m=1&lt;/code&gt; fingerprint against that reconstruction. It matches Alice’s original signature.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Alice’s signature validates even though the list rewrote her subject and appended a footer. And because every change is spelled out, Bob can see &lt;em&gt;exactly&lt;/em&gt; what the list did. A footer tweak and a malicious body swap no longer look the same.&lt;/p&gt;
&lt;p&gt;Bottom-up header numbering is not decoration; it is what keeps duplicated headers unambiguous. A recipe that deletes the middle of three &lt;code dir=&quot;auto&quot;&gt;Subject:&lt;/code&gt; headers, for instance, reads as copy the bottom one, insert the deleted literal, copy the top one:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;h&quot;&lt;/span&gt;&lt;span&gt;:{&lt;/span&gt;&lt;span&gt;&quot;subject&quot;&lt;/span&gt;&lt;span&gt;:[{&lt;/span&gt;&lt;span&gt;&quot;c&quot;&lt;/span&gt;&lt;span&gt;:[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;]},{&lt;/span&gt;&lt;span&gt;&quot;d&quot;&lt;/span&gt;&lt;span&gt;:[&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;four&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;]},{&lt;/span&gt;&lt;span&gt;&quot;c&quot;&lt;/span&gt;&lt;span&gt;:[&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;]}]}}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And a hop that redacts content under an arrangement the verifier trusts marks the body as unreconstructable rather than pretending it can be undone:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;b&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The chain still verifies up to that point; the body just cannot be rewound past it.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;bounces-carry-their-own-proof&quot;&gt;Bounces carry their own proof&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The same chain that stops replay also fixes bounces, and this is where DKIM2 quietly closes the backscatter problem for good.&lt;/p&gt;
&lt;p&gt;First, DKIM2 stops trusting the headers that lie. &lt;code dir=&quot;auto&quot;&gt;Received&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;Return-Path&lt;/code&gt; are ignored outright. The authoritative return address is reconstructed from the signed &lt;code dir=&quot;auto&quot;&gt;mf=&lt;/code&gt; tags in the chain instead. The rule is blunt: a DSN must be addressed to the &lt;code dir=&quot;auto&quot;&gt;mf=&lt;/code&gt; of the highest-numbered &lt;code dir=&quot;auto&quot;&gt;DKIM2-Signature&lt;/code&gt;, that is, the hop that actually handed the message over, never the visible envelope sender. And if that &lt;code dir=&quot;auto&quot;&gt;mf=&lt;/code&gt; is the null reverse path (&lt;code dir=&quot;auto&quot;&gt;mf=&amp;#x3C;&gt;&lt;/code&gt;), no DSN is sent at all. Backscatter has nowhere to land.&lt;/p&gt;
&lt;p&gt;Better still, a DKIM2 bounce can prove it is genuine. A DSN is itself an ordinary DKIM2 message: a &lt;code dir=&quot;auto&quot;&gt;multipart/report&lt;/code&gt; sent with &lt;code dir=&quot;auto&quot;&gt;MAIL FROM &amp;#x3C;&gt;&lt;/code&gt;, carrying its own &lt;code dir=&quot;auto&quot;&gt;Message-Instance&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;DKIM2-Signature&lt;/code&gt;, that embeds the original signed message (as a full &lt;code dir=&quot;auto&quot;&gt;message/rfc822&lt;/code&gt; copy or just its &lt;code dir=&quot;auto&quot;&gt;text/rfc822-headers&lt;/code&gt;). Because the original’s signature chain travels back inside the bounce, the receiver should re-verify the whole thing:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The DSN’s own signing domain should align with the recipient recorded in the returned message’s last &lt;code dir=&quot;auto&quot;&gt;rt=&lt;/code&gt; tag.&lt;/li&gt;
&lt;li&gt;That returned message’s last signature should be one this system actually produced, checked against its &lt;code dir=&quot;auto&quot;&gt;d=&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;mf=&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The embedded message’s headers, and its body if present, verify against the &lt;code dir=&quot;auto&quot;&gt;Message-Instance&lt;/code&gt; fingerprints.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Pass all three and the bounce is provably about a message you really sent to a recipient you really handed it to. Fail, and it must not be propagated further. That is what finally makes deferred bounces safe: a provider can accept a message, decide an hour later that it is spam, and send a signed bounce back along the recorded path, with no risk of mailbombing an innocent bystander. As the DSN travels back, each hop peels off the signature it added and forwards the bounce one step further toward the origin, so every party learns only about its own leg of the journey.&lt;/p&gt;
&lt;p&gt;A signature that used to vouch only for content now vouches for the entire journey: who sent it, who it was for, what each hop changed, and where a failure is allowed to go.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;arc-steps-aside&quot;&gt;ARC steps aside&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;DKIM2 is not the first attempt to keep authentication alive across forwarders. ARC (&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8617&quot;&gt;RFC 8617&lt;/a&gt;) got there first, and it is worth a moment because it explains a lot about the shape of DKIM2. When an intermediary changed a message and broke DKIM, ARC let that intermediary record what it had seen just before the change and add its own signature. Each hop stamps an ARC set of three headers: &lt;code dir=&quot;auto&quot;&gt;ARC-Authentication-Results&lt;/code&gt; captures the authentication verdict the hop saw on input, &lt;code dir=&quot;auto&quot;&gt;ARC-Message-Signature&lt;/code&gt; signs the message as the hop passed it on, and &lt;code dir=&quot;auto&quot;&gt;ARC-Seal&lt;/code&gt; signs the chain so far. A downstream receiver could confirm the chain was cryptographically intact and read the upstream verdicts.&lt;/p&gt;
&lt;p&gt;The catch is that ARC records observations, not changes. A valid chain proves a message was handled, not that the handling was correct, and it never says what was actually modified. To act on an ARC chain a receiver has to decide whether it trusts every signer in it, which in practice means running a reputation system for thousands of forwarders across the open internet. That trust fabric never materialized. A decade on, there is no working internet-scale ARC reputation deployment and no plan for one, so early adopters fell back to hand-maintained allow lists of known intermediaries: useful inside a data center or a consortium, not on the wider internet. Receivers were also left to invent their own policy for how many hops to honor and how to treat partial or broken chains, so behaviour never converged. The IETF’s DMARC working group is now moving to reclassify RFC 8617 as Historic and discourage new deployments (&lt;a href=&quot;https://datatracker.ietf.org/doc/draft-ietf-dmarc-arc-to-historic/&quot;&gt;draft-ietf-dmarc-arc-to-historic&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;DKIM2 removes the very thing that made ARC unworkable: the separate trust fabric. Rather than ask a receiver to trust an intermediary’s account of what it saw, DKIM2 has each hop record exactly what it changed as a reversible recipe. The verifier undoes those changes and re-checks the originator’s own signature, so trust flows back to the domain that actually authored the message rather than to every forwarder along the way. And because the recipe spells out each modification, a receiver can tell an innocent subject tag from something worth worrying about, the “what changed” question ARC left open. The handling assertions ARC was genuinely good at fold into the same chain, with no parallel reputation system holding them up.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;meet-dmarcbis&quot;&gt;Meet DMARCbis&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;After more than a decade of RFC 7489 doing quiet, load-bearing work behind the world’s inboxes, DMARC has a proper successor. In May 2026 the IETF published three new Standards Track documents, RFC 9989, RFC 9990, and RFC 9991, collectively known as DMARCbis. They obsolete the original 2015 specification (and fold in the experimental Public Suffix Domain work from RFC 9091).&lt;/p&gt;
&lt;p&gt;Nothing about the day-to-day promise of DMARC has changed. What changed is the plumbing underneath it, and a few of those changes are the kind that quietly fix problems operators have lived with for years.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;tldr&quot;&gt;TL;DR&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;For anyone who wants the gist before the details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Public Suffix List is gone. Finding the boundary of an organization now happens with a live DNS lookup called the &lt;em&gt;tree walk&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code dir=&quot;auto&quot;&gt;pct&lt;/code&gt; sampling tag is retired. A simpler &lt;code dir=&quot;auto&quot;&gt;t&lt;/code&gt; testing flag takes its place.&lt;/li&gt;
&lt;li&gt;Two tags graduate from the experimental PSD extension into the core spec: &lt;code dir=&quot;auto&quot;&gt;np&lt;/code&gt; for non-existent subdomains and &lt;code dir=&quot;auto&quot;&gt;psd&lt;/code&gt; for public suffix operators.&lt;/li&gt;
&lt;li&gt;Reporting moved into its own two documents, gained a new XML schema, and picked up an extensibility slot so future additions no longer require reopening the whole standard.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;p=reject&lt;/code&gt; is no longer treated as an unconditional instruction to bounce mail.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Existing DMARC records keep working. The retired tags are simply ignored, so there is no flag day and no forced migration.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;a-quick-refresher-on-dmarc&quot;&gt;A quick refresher on DMARC&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;SPF and DKIM both authenticate a domain, but not the one that matters most to a human reading their mail. SPF checks the envelope sender used during the SMTP conversation, and DKIM checks whatever domain signed the message. Neither is required to match the &lt;code dir=&quot;auto&quot;&gt;From:&lt;/code&gt; address the recipient actually sees, which is exactly the address a phisher wants to forge.&lt;/p&gt;
&lt;p&gt;DMARC closes that gap. It anchors authentication to the visible &lt;code dir=&quot;auto&quot;&gt;From:&lt;/code&gt; domain, the Author Domain, through a property called &lt;em&gt;alignment&lt;/em&gt;: a message passes only when SPF or DKIM authenticates a domain that lines up with the Author Domain. The domain owner publishes a policy in DNS stating what receivers should do with mail that fails (&lt;code dir=&quot;auto&quot;&gt;none&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;quarantine&lt;/code&gt;, or &lt;code dir=&quot;auto&quot;&gt;reject&lt;/code&gt;) and where to send reports. That combination, authentication tied to the visible sender plus a published preference plus feedback, is what made DMARC the backbone of email anti-spoofing.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;issues-with-dmarc&quot;&gt;Issues with DMARC&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;RFC 7489 aged well, but a handful of design decisions turned into recurring headaches:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The Public Suffix List was a soft spot.&lt;/strong&gt; To tell where one organization ends and a registrar’s namespace begins (so that &lt;code dir=&quot;auto&quot;&gt;mail.example.com&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;example.com&lt;/code&gt; are understood to share an owner, while &lt;code dir=&quot;auto&quot;&gt;example.com&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;example.co.uk&lt;/code&gt; do not), receivers leaned on Mozilla’s Public Suffix List. The spec never mandated a specific copy of it, said nothing about how often to refresh it, and openly acknowledged the interoperability risk. A single static file, maintained by volunteers, sat on the critical path of global mail authentication.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The &lt;code dir=&quot;auto&quot;&gt;pct&lt;/code&gt; tag promised more than it delivered.&lt;/strong&gt; It was meant to let a domain roll out a policy to a percentage of mail. In practice only two values behaved consistently across receivers: 0 and 100. Worse, &lt;code dir=&quot;auto&quot;&gt;pct=0&lt;/code&gt; had quietly acquired a special meaning of its own, so the tag was really a two-state switch wearing a percentage costume.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subdomains that did not exist were a spoofing gap.&lt;/strong&gt; A domain could set a strict policy for itself, yet an attacker could still forge a plausible looking subdomain that had never been registered. The experimental PSD DMARC work started to address this, but it lived outside the core standard.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Everything was crammed into one document.&lt;/strong&gt; Core protocol, aggregate reporting, and failure reporting all shared a single RFC, which meant none of them could evolve without dragging the others along.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;dmarcbis-one-specification-becomes-three&quot;&gt;DMARCbis, one specification becomes three&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;DMARCbis splits the old monolith along its natural seams so each piece can advance on its own schedule:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RFC 9989&lt;/strong&gt; is the core protocol: alignment, policy, record syntax, and the new discovery mechanism. It obsoletes both RFC 7489 and RFC 9091.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RFC 9990&lt;/strong&gt; covers aggregate reporting, the daily domain-level XML summaries that most operators actually rely on.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RFC 9991&lt;/strong&gt; covers failure reporting, the detailed per-message reports, and updates the older RFC 6591 reporting format along the way.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The move from a single Informational RFC to three Standards Track documents is not just bookkeeping. It reflects DMARC growing up into a first-class internet standard with the process discipline that implies.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;climbing-the-tree-instead-of-trusting-a-list&quot;&gt;Climbing the tree instead of trusting a list&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The headline change is how a receiver figures out where an organization’s authority begins. Instead of consulting a static list, DMARCbis defines the &lt;em&gt;DNS tree walk&lt;/em&gt;: a live, ordered series of DNS queries that climb from the Author Domain toward the root until they find the records that apply.&lt;/p&gt;
&lt;p&gt;The receiver always queries the full Author Domain first, at &lt;code dir=&quot;auto&quot;&gt;_dmarc.&amp;#x3C;author-domain&gt;&lt;/code&gt;. If nothing definitive turns up there, the walk begins: it drops labels from the left and queries the parent, then that parent’s parent, and so on toward the root. To keep a pathologically long domain from turning into a flood of lookups, the algorithm is capped at eight queries. For names of eight labels or fewer it strips one label at a time, but for anything longer it removes several labels at once so that only seven remain, then continues one label at a time from there. Eight was not arbitrary: names of up to seven labels were observed in real use, so the cap clears actual traffic while still bounding the work.&lt;/p&gt;
&lt;p&gt;The canonical illustration from the spec makes the cap concrete. For &lt;code dir=&quot;auto&quot;&gt;a.b.c.d.e.f.g.h.i.j.mail.example.com&lt;/code&gt;, a receiver issues exactly eight queries and skips the deep intermediate labels entirely:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;_dmarc.a.b.c.d.e.f.g.h.i.j.mail.example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;_dmarc.g.h.i.j.mail.example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;_dmarc.h.i.j.mail.example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;_dmarc.i.j.mail.example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;_dmarc.j.mail.example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;_dmarc.mail.example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;_dmarc.example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;_dmarc.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;For the domains almost everyone actually runs, this is cheap. A name like &lt;code dir=&quot;auto&quot;&gt;mail.marketing.example.com&lt;/code&gt; resolves in a couple of lookups, and DNS caching absorbs most of the cost because the same parent records are queried over and over across many messages.&lt;/p&gt;
&lt;p&gt;Once the walk has collected the records that exist along the path, the receiver selects the Organizational Domain with a short, deterministic set of rules, working from the longest name to the shortest:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A record that declares &lt;code dir=&quot;auto&quot;&gt;psd=n&lt;/code&gt; marks its own domain as the Organizational Domain. Stop there.&lt;/li&gt;
&lt;li&gt;A record that declares &lt;code dir=&quot;auto&quot;&gt;psd=y&lt;/code&gt; (and is not where the walk began) means the Organizational Domain sits one label below it.&lt;/li&gt;
&lt;li&gt;Failing both of those, the record with the fewest labels wins.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To make rule 3 concrete: for &lt;code dir=&quot;auto&quot;&gt;a.mail.example.com&lt;/code&gt;, absent any &lt;code dir=&quot;auto&quot;&gt;psd&lt;/code&gt; signals along the way, the walk settles on &lt;code dir=&quot;auto&quot;&gt;example.com&lt;/code&gt; as the Organizational Domain, exactly the answer the Public Suffix List used to hand back, now derived from live DNS instead.&lt;/p&gt;
&lt;p&gt;The payoff is that the Organizational Domain is now defined by DNS records that the domain owner controls, rather than inferred from a file the owner has no say over. It refreshes as fast as DNS does, and it removes an entire class of “why is the PSL wrong for my domain” problems.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;tuning-the-record-what-arrived-what-retired&quot;&gt;Tuning the record: what arrived, what retired&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The record itself picked up three new tags and lost three old ones. The valid set in DMARCbis is now &lt;code dir=&quot;auto&quot;&gt;v&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;p&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;sp&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;np&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;adkim&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;aspf&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;fo&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;rua&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;ruf&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;psd&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;t&lt;/code&gt;.&lt;/p&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Tag&lt;/th&gt;&lt;th&gt;Status in DMARCbis&lt;/th&gt;&lt;th&gt;What it does&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;np&lt;/code&gt;&lt;/td&gt;&lt;td&gt;New&lt;/td&gt;&lt;td&gt;Policy for non-existent subdomains of the Organizational Domain&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;psd&lt;/code&gt;&lt;/td&gt;&lt;td&gt;New&lt;/td&gt;&lt;td&gt;Declares whether the domain is a public suffix (&lt;code dir=&quot;auto&quot;&gt;y&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;n&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;u&lt;/code&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;t&lt;/code&gt;&lt;/td&gt;&lt;td&gt;New&lt;/td&gt;&lt;td&gt;Testing flag that softens enforcement without turning it off&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;pct&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Removed&lt;/td&gt;&lt;td&gt;Percentage sampling; only 0 and 100 ever worked reliably&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;rf&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Removed&lt;/td&gt;&lt;td&gt;Failure report format; only one format was ever deployed&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;ri&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Removed&lt;/td&gt;&lt;td&gt;Aggregate report interval; effectively fixed at roughly one day&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code dir=&quot;auto&quot;&gt;v&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;p&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;sp&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;adkim&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;aspf&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;fo&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;rua&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;ruf&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Unchanged&lt;/td&gt;&lt;td&gt;Version, policy, subdomain policy, alignment modes, failure options, report destinations&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;A closer look at the newcomers:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;t&lt;/code&gt; replaces &lt;code dir=&quot;auto&quot;&gt;pct&lt;/code&gt; with something clear.&lt;/strong&gt; Rather than pretending to be a dial, the testing flag is a plain switch. The default &lt;code dir=&quot;auto&quot;&gt;t=n&lt;/code&gt; applies the published policy as written. Setting &lt;code dir=&quot;auto&quot;&gt;t=y&lt;/code&gt; signals that the domain is still testing, so compliant receivers step the effective policy down one level: &lt;code dir=&quot;auto&quot;&gt;reject&lt;/code&gt; behaves like &lt;code dir=&quot;auto&quot;&gt;quarantine&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;quarantine&lt;/code&gt; behaves like &lt;code dir=&quot;auto&quot;&gt;none&lt;/code&gt;, with intermediaries free to apply special handling such as rewriting the &lt;code dir=&quot;auto&quot;&gt;From:&lt;/code&gt; header. Crucially, &lt;code dir=&quot;auto&quot;&gt;t&lt;/code&gt; leaves report generation untouched, so a domain can watch the reports roll in while enforcement stays gentle. It is best understood as analogous to the old &lt;code dir=&quot;auto&quot;&gt;pct=0&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;pct=100&lt;/code&gt; behavior rather than an exact reimplementation of it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;np&lt;/code&gt; closes the phantom-subdomain gap.&lt;/strong&gt; It sets the policy for subdomains that do not exist at all, identified by an NXDOMAIN response as described in RFC 8020. If a name has never been registered, an attacker should not be able to send convincing mail from it, and &lt;code dir=&quot;auto&quot;&gt;np&lt;/code&gt; lets a domain say exactly that. When &lt;code dir=&quot;auto&quot;&gt;np&lt;/code&gt; is absent the receiver falls back to &lt;code dir=&quot;auto&quot;&gt;sp&lt;/code&gt;, and then to &lt;code dir=&quot;auto&quot;&gt;p&lt;/code&gt;. The mechanism leans on RFC 8020’s rule that an NXDOMAIN answer means the name and everything beneath it truly does not exist, so it is only as reliable as the DNS returning that answer as the standard requires.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;psd&lt;/code&gt; brings public suffix operators into the fold.&lt;/strong&gt; Registry-style domains such as a country’s &lt;code dir=&quot;auto&quot;&gt;gov&lt;/code&gt; namespace can now declare &lt;code dir=&quot;auto&quot;&gt;psd=y&lt;/code&gt;, which both anchors the tree walk and lets the operator publish a protective default for every registered name underneath. &lt;code dir=&quot;auto&quot;&gt;psd=n&lt;/code&gt; states the opposite, that the domain is its own Organizational Domain, and the default &lt;code dir=&quot;auto&quot;&gt;psd=u&lt;/code&gt; leaves the decision to the tree walk. This is the RFC 9091 experiment, now standardized and freed from its separate registry.&lt;/p&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;sp&lt;/code&gt; tag, meanwhile, keeps its meaning but is redefined in terms of the tree walk: it governs existing subdomains of the Organizational Domain, and it is read only from the record discovered at that Organizational Domain, not from a record sitting on the subdomain itself.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;the-preject-reality-check&quot;&gt;The p=reject reality check&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;One change is less about syntax and more about attitude. &lt;code dir=&quot;auto&quot;&gt;p=reject&lt;/code&gt; is no longer treated as an unconditional order to bounce.&lt;/p&gt;
&lt;p&gt;The tension is real and was debated at length. Strict rejection is what protects the largest consumer mail platforms and the billions of inboxes behind them, and nobody wanted to weaken that. At the same time, blunt rejection breaks legitimate indirect mail flows, mailing lists and forwarders being the classic casualties, and the damage lands on innocent third parties who never chose the policy.&lt;/p&gt;
&lt;p&gt;DMARCbis threads the needle with sharper guidance rather than a weaker mechanism. Three distinct rules do the work:&lt;/p&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Party&lt;/th&gt;&lt;th&gt;Guidance&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Sending domain (general-purpose)&lt;/td&gt;&lt;td&gt;SHOULD NOT publish &lt;code dir=&quot;auto&quot;&gt;p=reject&lt;/code&gt; if users might post to mailing lists; ramp through &lt;code dir=&quot;auto&quot;&gt;none&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;quarantine&lt;/code&gt; first&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sending domain (any &lt;code dir=&quot;auto&quot;&gt;p=reject&lt;/code&gt;)&lt;/td&gt;&lt;td&gt;MUST NOT rely on SPF alone, and MUST apply valid DKIM signatures, since DKIM is what survives forwarding&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Receiver&lt;/td&gt;&lt;td&gt;MUST NOT reject solely because a policy says &lt;code dir=&quot;auto&quot;&gt;reject&lt;/code&gt;; weigh other evidence before acting&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The policy became a strong signal to weigh rather than a trigger to pull blindly.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;reporting-grows-up&quot;&gt;Reporting grows up&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Splitting reporting into its own documents came with real upgrades, not just a new table of contents.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Aggregate reports (RFC 9990)&lt;/strong&gt; move to a new XML namespace, &lt;code dir=&quot;auto&quot;&gt;urn:ietf:params:xml:ns:dmarc-2.0&lt;/code&gt;, and gain an extensibility slot so future data can be added without breaking existing parsers: consumers simply ignore extensions they do not understand. The schema now records how policy was discovered through a &lt;code dir=&quot;auto&quot;&gt;discovery_method&lt;/code&gt; field that distinguishes the old &lt;code dir=&quot;auto&quot;&gt;psl&lt;/code&gt; from the new &lt;code dir=&quot;auto&quot;&gt;treewalk&lt;/code&gt;, reflects the &lt;code dir=&quot;auto&quot;&gt;t&lt;/code&gt; testing flag, and carries the &lt;code dir=&quot;auto&quot;&gt;np&lt;/code&gt; policy. Reporting a DKIM result now requires naming the selector, which makes the reports genuinely more useful for debugging. These reports stay privacy-safe by design: they aggregate domain-level authentication counts and carry no message content and no end-user identifying data such as recipient addresses or the IP addresses of individuals. Transport remains email, with the XML gzipped and delivered as an attachment, and external report destinations still have to prove they consented through a &lt;code dir=&quot;auto&quot;&gt;_report._dmarc&lt;/code&gt; record.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Failure reports (RFC 9991)&lt;/strong&gt; get an honest treatment of why they are used so sparingly. Because they can carry entire messages, headers and body included, they raise real privacy and regulatory concerns, and many large providers disable them outright in favor of aggregate data. The format, updated from RFC 6591, adds a dedicated &lt;code dir=&quot;auto&quot;&gt;dmarc&lt;/code&gt; failure type and a required &lt;code dir=&quot;auto&quot;&gt;Identity-Alignment&lt;/code&gt; field that spells out which mechanisms failed to produce an aligned identifier. Generators must rate-limit what they send, and for public suffix domains they must not act on a &lt;code dir=&quot;auto&quot;&gt;ruf&lt;/code&gt; request at all unless the parties have a specific agreement in place, so a registry operator does not receive a stream of other people’s message content by default.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;what-stayed-exactly-the-same&quot;&gt;What stayed exactly the same&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;For all the moving parts, the fundamentals are untouched, which is worth stating plainly so nobody over-rotates on the release:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Alignment still works the way it always has, in relaxed and strict flavors selected with &lt;code dir=&quot;auto&quot;&gt;adkim&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;aspf&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The three policies, &lt;code dir=&quot;auto&quot;&gt;none&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;quarantine&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;reject&lt;/code&gt;, mean what they always meant.&lt;/li&gt;
&lt;li&gt;DMARC still evaluates only the &lt;code dir=&quot;auto&quot;&gt;From:&lt;/code&gt; header and still builds on SPF and DKIM rather than replacing them.&lt;/li&gt;
&lt;li&gt;Records written for RFC 7489 remain valid. The retired tags are ignored, not rejected, so there is no urgent rewrite waiting on anyone’s to-do list.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;DMARCbis is less a reinvention than a long-overdue tidy-up: the same protocol, with its most useful experiments promoted to the core and a decade of operational lessons written back into the spec. The tree walk alone, trading a static list for live DNS, is the kind of change whose absence will not be missed at all.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;both-protocols-live-in-stalwart-today&quot;&gt;Both protocols live in Stalwart today&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;As of &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/releases&quot;&gt;Stalwart v0.16.12&lt;/a&gt;, DKIM2 (draft -04) and DMARCbis are both fully implemented, and Stalwart is the first mail server to support either of them. Signing, verifying, the chain-of-custody logic, recipe reversal, bounce validation, the DNS tree walk, the new and retired DMARC tags: all of it ships and runs.&lt;/p&gt;
&lt;p&gt;We wanted the protocols to be easy to try without setting up a server, so both are exposed in the browser. At the &lt;a href=&quot;https://mail-auth.stalw.art&quot;&gt;mail-auth playground&lt;/a&gt; anyone can sign a message with DKIM2 and watch it verify, break it and see the chain reject it, or run a message through DMARCbis side by side to see how the tree walk resolves the Organizational Domain. It runs Stalwart’s own authentication code compiled to WebAssembly, so what the playground shows is exactly what the server does, no install and nothing to configure.&lt;/p&gt;
&lt;p&gt;For Rust developers, the same code is available as a library. DKIM2 and DMARCbis live in the &lt;a href=&quot;https://github.com/stalwartlabs/mail-auth&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;mail-auth&lt;/code&gt;&lt;/a&gt; crate, the message authentication library Stalwart itself is built on, which also covers DKIM1, SPF, DMARC, and ARC. It is the engine behind both the server and the playground, and it is open source under the same permissive terms as the rest of Stalwart, so any Rust project can add DKIM2 and DMARCbis support by pulling in a single dependency.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;looking-forward&quot;&gt;Looking forward&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;DKIM2 and DMARCbis pull in the same direction. DKIM2 makes a signature vouch for the whole journey rather than a frozen snapshot of content. Forwarding stops breaking authentication, replayed mail no longer verifies on borrowed reputation, and bounces finally carry their own proof. DMARCbis takes the layer that ties all of this to the domain a person actually reads and rests it on live DNS the domain owner controls, retiring the tags that never worked and the static list that sat on the critical path of global mail. Neither demands a flag day: existing DKIM and DMARC records keep working, and the new mechanisms layer in alongside them.&lt;/p&gt;
&lt;p&gt;Supporting them first is the part of this that Stalwart cares most about. Being early to a standard is how the standard gets tested against real mail before it hardens, and it is how operators who want the newest protections get them without waiting for the rest of the ecosystem to catch up. Stalwart has made a habit of shipping the latest IETF work as it lands, and DKIM2 and DMARCbis are the newest entries on that list. Try them at the &lt;a href=&quot;https://mail-auth.stalw.art&quot;&gt;mail-auth playground&lt;/a&gt;, read the code in the &lt;a href=&quot;https://github.com/stalwartlabs/mail-auth&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;mail-auth&lt;/code&gt;&lt;/a&gt; crate, and upgrade to &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/releases&quot;&gt;v0.16.12&lt;/a&gt; to run them in production.&lt;/p&gt;</content:encoded><category>dkim</category><category>dmarc</category><category>dkim2</category><category>dmarcbis</category><category>email</category><category>security</category><category>rust</category><category>server</category></item><item><title>Zero open bug reports: The road to Stalwart 1.0</title><link>https://stalw.art/blog/road-to-stalwart-1-0/</link><guid isPermaLink="true">https://stalw.art/blog/road-to-stalwart-1-0/</guid><description>Today we released Stalwart v0.16.10, a release that closes every single open bug report we have on record: both the legacy issues on GitHub and the reports filed through our new support portal. With the tracker clear of bugs, we want to share where Stalwart stands today and what is left before we ship version 1.0.

</description><pubDate>Sun, 21 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today we released &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/releases&quot;&gt;Stalwart v0.16.10&lt;/a&gt;, and it comes with a milestone we have been working toward for a while: as of today, there are no open bug reports for Stalwart. This release fixes every reported bug we have on record, both the legacy issues that had accumulated on &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/issues&quot;&gt;GitHub&lt;/a&gt; and the reports submitted through our new &lt;a href=&quot;https://support.stalw.art&quot;&gt;support portal&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We want to be precise about what this means, because it is easy to misread. It does not mean Stalwart is bug free. No non-trivial piece of software is, and we would not claim otherwise. What it means is narrower: as of today there are no open bug reports awaiting a fix. Every issue that a user took the time to report has been triaged and resolved. New reports will arrive, and we will keep working through them, but for now the queue is empty.&lt;/p&gt;
&lt;p&gt;That leaves 108 issues still open on the &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/issues&quot;&gt;GitHub tracker&lt;/a&gt;. These are not bugs. They are minor feature enhancements and requests: refinements, quality-of-life additions, and ideas worth keeping on the list. We will get to them, but none of them block correct operation today.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;latest-fixes&quot;&gt;Latest fixes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The headline of this release is RFC conformance. Stalwart v0.16.10 now passes all 309 tests of the &lt;a href=&quot;https://github.com/jmapio/jmap-test-suite&quot;&gt;JMAP test suite&lt;/a&gt;, a shared conformance effort that aims to align the behaviour of Stalwart, Cyrus, and Fastmail so that JMAP clients see consistent semantics regardless of which server they talk to. Reaching full conformance touched many corners of the JMAP implementation.&lt;/p&gt;
&lt;p&gt;Beyond JMAP, this release implements the latest drafts from the IETF &lt;a href=&quot;https://datatracker.ietf.org/wg/mailmaint/about/&quot;&gt;mailmaint&lt;/a&gt; working group. On the authentication side, Stalwart now supports the &lt;a href=&quot;https://datatracker.ietf.org/doc/draft-ietf-mailmaint-oauth-public/&quot;&gt;OAuth Profile for Open Public Clients&lt;/a&gt; along with client secret verification for confidential clients. On the IMAP side, it implements the &lt;a href=&quot;https://datatracker.ietf.org/doc/draft-ietf-mailmaint-imap-objectid-bis/&quot;&gt;IMAP Extension for Object Identifiers&lt;/a&gt; (OBJECTID+) and adds the &lt;code dir=&quot;auto&quot;&gt;GETJMAPACCESS&lt;/code&gt; command so clients can discover the JMAP session resource URL directly from an IMAP connection. We are glad to share that Stalwart Labs is coauthoring the &lt;code dir=&quot;auto&quot;&gt;OBJECTID+&lt;/code&gt; extension together with Fastmail.&lt;/p&gt;
&lt;p&gt;For the full list, see the &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/releases&quot;&gt;release notes&lt;/a&gt;. We recommend everyone upgrade.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;road-to-10&quot;&gt;Road to 1.0&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;With the bug queue clear, the path to version 1.0 comes down to two pieces of work: finalizing the database schema and a focused round of performance optimization.&lt;/p&gt;
&lt;p&gt;The first is the reason 1.0 matters. The goal is to stabilize and finalize the database schema so that it is flexible enough to avoid migrations after the 1.0 release. Stalwart is already running in production across a wide range of deployments, but committing to a stable on-disk format is a promise we only want to make once we are confident it will hold. We are taking the time now to make the schema general enough that future features can be added without forcing operators through a migration. When 1.0 ships, upgrading should stop being something you schedule a maintenance window for.&lt;/p&gt;
&lt;p&gt;The second is performance. Stalwart is already fast, and that is not an accident: over the past year we have made substantial improvements driven directly by reports from users running it at scale, including deployments with thousands of accounts and others delivering hundreds of thousands of emails per day. Those real-world workloads have been the best optimization guide we could ask for. For 1.0 we want to push further in two specific areas.&lt;/p&gt;
&lt;p&gt;The first is the internal full-text search engine, which matters most for users who do not run an external Elasticsearch or Meilisearch backend and rely on the built-in indexer instead. We want search to be fast out of the box, without an external dependency. The second is a systematic pass over the hot paths in the codebase: benchmarking the code that runs most often to find concrete optimization opportunities, whether that means vectorizing an inner loop, reworking a data structure, or rewriting a section for better cache behaviour. The point is to let measurements, not guesses, decide where the effort goes.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;eta&quot;&gt;ETA&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We expect to release Stalwart 1.0.0 this year, most likely around October and hopefully sooner. Schema work and performance work are both the kind that reward patience, so we would rather give a realistic window than a date we cannot keep. We will keep you posted as the schema settles and the benchmarks come in.&lt;/p&gt;
&lt;p&gt;In the meantime, v0.16.10 is the most conformant and most thoroughly debugged release we have shipped. Thank you to everyone who filed an issue, opened a ticket on the support portal, or sent us a reproducer. An empty bug queue is your work as much as ours, and it is the best possible foundation to build 1.0 on.&lt;/p&gt;</content:encoded><category>release</category><category>jmap</category><category>imap</category><category>oauth</category><category>dane</category><category>idn</category><category>roadmap</category><category>performance</category></item><item><title>Migration proxy: zero-downtime upgrades</title><link>https://stalw.art/blog/migration-proxy/</link><guid isPermaLink="true">https://stalw.art/blog/migration-proxy/</guid><description>A good number of Stalwart deployments are still on an older release for one reason: upgrading between versions meant a maintenance window, and downtime on a mail server is the one thing nobody wants to schedule. We promised a zero-downtime path built from two tools. Vandelay, the data-transfer half, shipped a couple of weeks ago. Today we are shipping the second and final part, the migration proxy, and with it the full workflow is real: a live deployment can move from an older Stalwart version to v0.16 one account at a time, with no scheduled maintenance window and nothing for end users to reconfigure.

</description><pubDate>Wed, 10 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A good number of Stalwart deployments are still running an old release, some on v0.15 and some as far back as v0.11, and in most cases not by choice. Upgrading between versions on a populated server has meant migrating the stored data onto a new on-disk schema, and migrating data means downtime, and downtime on a mail server is the one thing nobody wants to schedule. So the upgrade keeps getting postponed, and a deployment that should be on the current line stays where it is. We promised a way out of that bind: a zero-downtime migration path built from two tools that work together.&lt;/p&gt;
&lt;p&gt;The first of those, Vandelay, &lt;a href=&quot;https://stalw.art/blog/jmap-account-migration/&quot;&gt;shipped a couple of weeks ago&lt;/a&gt;. It is the transfer tool, the part that moves an account’s data, its mail, calendars, contacts, filters and files, from one server to another, one account at a time.&lt;/p&gt;
&lt;p&gt;Today we are shipping the second and final component, the &lt;a href=&quot;https://github.com/stalwartlabs/proxy&quot;&gt;migration proxy&lt;/a&gt;, and with it the full workflow is complete. A live production deployment can now move from an older Stalwart version to v0.16 on an account-by-account basis, with no scheduled maintenance window and nothing for end users to reconfigure. What makes that possible is the proxy standing in front of both the old and the new deployment as a single endpoint, routing each connection to whichever server currently owns the account behind it.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;a-single-endpoint-in-front-of-two-deployments&quot;&gt;A single endpoint in front of two deployments&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The proxy sits on the public mail and web ports that clients already use and terminates each protocol far enough to see who is connecting. From the credentials the client presents, its IMAP, POP3, SMTP, ManageSieve or JMAP login, it derives which account the connection belongs to, looks up which of the two deployments currently owns that account, and bridges the session to it. Because the decision comes from the login itself, clients keep the same hostname, the same ports and the same passwords throughout, and nothing on their devices changes.&lt;/p&gt;
&lt;p&gt;Inbound mail is handled without needing a login to route on. The new deployment becomes the public mail exchanger for the duration of the migration and performs split delivery: a message for an account that has already moved is delivered locally, while a message for an account that still lives on the old server is relayed there. Mail never has to be repointed in the middle of the migration, and it keeps flowing to every account regardless of which side currently holds it.&lt;/p&gt;
&lt;p&gt;Moving an account is then a small, self-contained operation. Vandelay copies the account’s mail, mailboxes, sieve scripts, contacts, calendars and files into the new deployment while the account continues to be served from the old one, so the work is invisible to its owner. When the copy has been verified, a single routing entry is flipped and the account’s next connection lands on the new server. The switch disconnects any live session, which reconnects on its own, and that is the entire visible effect. Until an account accumulates new data on the new server the move stays fully reversible, because the old copy is never removed. The result is that a gradual, account-by-account, reversible migration looks, from the outside, like an ordinary server that never went down.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;migrating-from-other-self-hosted-systems&quot;&gt;Migrating from other self-hosted systems&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Although the immediate reason we built the proxy was Stalwart-to-Stalwart upgrades, the same model works for moving onto Stalwart from another self-hosted mail server. Legacy stacks built on Dovecot and Postfix, the foundation of distributions such as Mail-in-a-Box and mailcow, can sit behind the proxy exactly as an older Stalwart does. The proxy announces the real client to those backends over XCLIENT and the IMAP ID rather than the PROXY protocol, and Vandelay reads their data over IMAP, ManageSieve, CalDAV and CardDAV instead of JMAP, but the shape of the migration is the same: front both servers, copy each account, flip it over, keep a way back. For operators who have been looking for a path off an aging self-hosted deployment and onto a modern open-source server, this is that path, and it comes without a flag day.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;documentation-and-where-to-start&quot;&gt;Documentation and where to start&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Alongside the proxy we are publishing the documentation we promised when Vandelay shipped: a complete, step-by-step migration guide that covers the whole workflow end to end. The &lt;a href=&quot;https://stalw.art/docs/migration/&quot;&gt;migration overview&lt;/a&gt; introduces the two tools and how they fit together, and the &lt;a href=&quot;https://stalw.art/docs/migration/guide/&quot;&gt;migration guide&lt;/a&gt; walks through the entire procedure, from installing the new deployment and configuring the proxy to moving accounts one at a time, validating each one, and finalizing the migration once the old server is empty. The proxy itself lives on &lt;a href=&quot;https://github.com/stalwartlabs/proxy&quot;&gt;GitHub&lt;/a&gt;, with its own &lt;a href=&quot;https://stalw.art/docs/migration/proxy/&quot;&gt;reference documentation&lt;/a&gt; for every configuration option.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;upgrading-to-v016-now-or-waiting-for-10&quot;&gt;Upgrading to v0.16 now, or waiting for 1.0&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;With the migration path complete, the question many operators will reasonably ask is whether to move to v0.16 now or hold out for the next milestone. Stalwart 1.0 is planned for release later this year, and it is worth being clear about how it relates to v0.16.&lt;/p&gt;
&lt;p&gt;We do not foresee 1.0 introducing the kind of major breaking changes that earlier upgrades did. v0.16 is already very close to what 1.0 will be, and the heavy architectural work that made previous upgrades disruptive is behind us. What remains before 1.0 is a final round of performance and code optimization, and until that review is finished we cannot yet promise that the current database schema is final. If it does change, we intend for 1.0 to be an automated upgrade from v0.16 that detects any schema difference and migrates it in place, so that going from v0.16 to 1.0 is a routine update rather than another migration exercise.&lt;/p&gt;
&lt;p&gt;What this means in practice is straightforward. Operators who need something in v0.16 today, whether a specific feature or simply a supported path off a much older release, can migrate now with no downtime, and as described above our aim, though not yet a guarantee, is for the later step to 1.0 to be a routine, automated upgrade rather than another migration. Operators who are comfortable where they are and do not need anything in v0.16 with any urgency may prefer to wait for 1.0 and make a single move then. Both are sound choices, and the difference between them is only timing. For the first time, that timing is no longer dictated by how much downtime a migration would cost.&lt;/p&gt;</content:encoded><category>proxy</category><category>migration</category><category>vandelay</category><category>upgrade</category><category>server</category></item><item><title>Vandelay: the JMAP importer-exporter</title><link>https://stalw.art/blog/jmap-account-migration/</link><guid isPermaLink="true">https://stalw.art/blog/jmap-account-migration/</guid><description>Many Stalwart deployments are running an older version not because the operators want to, but because upgrading across a major release can mean migrating off an older database schema, and that means downtime. We promised a zero-downtime migration path built from two parts, a proxy and a transfer tool, and the question we hear most is when it will arrive. Today we are shipping the first part: Vandelay, a one-shot account migration and backup utility for JMAP that also imports from IMAP, CalDAV, CardDAV, WebDAV, ManageSieve, Maildir, Google Takeout, and (experimentally) Microsoft Exchange.

</description><pubDate>Fri, 29 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A good number of Stalwart deployments are running an older version not because the operators want to be, but because they cannot afford the disruption. Upgrading across a major release sometimes means migrating off an older on-disk schema, and migrating data means downtime, and downtime on a mail server is the one thing nobody wants to schedule. So the upgrade gets postponed, again, and a deployment that should be on the current line stays where it is. The question we get asked most often is when we will ship something to fix exactly this.&lt;/p&gt;
&lt;p&gt;We have said before that the right answer is a zero-downtime migration path, built from two parts: a proxy that sits in front of both the old and the new server so that clients keep working throughout, and a transfer tool that moves account data from one to the other. Today we are shipping the first of those two parts.&lt;/p&gt;
&lt;p&gt;It is called &lt;a href=&quot;https://github.com/stalwartlabs/vandelay/&quot;&gt;Vandelay&lt;/a&gt;, and it is a one-shot account migration and backup utility for JMAP. Yes, it is named after Art Vandelay, the importer-exporter George Costanza made up as a cover story on Seinfeld. The tool imports and it exports, so the reference wrote itself.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;what-vandelay-does&quot;&gt;What Vandelay does&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Vandelay is the JMAP analogue of &lt;a href=&quot;https://github.com/imapsync/imapsync&quot;&gt;imapsync&lt;/a&gt;, generalized from mail to every JMAP data type: mail, contacts, calendars, identities, sieve scripts, and file storage. It works in two stages that never talk to each other directly. An import reads a source account into a local SQLite file that Vandelay calls an &lt;em&gt;archive&lt;/em&gt;; one archive holds exactly one account and fully describes it on its own. An export then pushes an archive into a target JMAP server. Because import and export only ever touch the archive, never each other, the two halves are completely decoupled: you can import today and export next week, import from one protocol and export to JMAP, or keep the archive around and do nothing with it at all.&lt;/p&gt;
&lt;p&gt;A few properties make it pleasant to operate at scale. Both halves are convergent, so re-running an interrupted import or export simply picks up where it left off, with no bookkeeping flags to reset and no half-finished state to clean up; re-running an import later also catches anything new since the last snapshot. Every command takes &lt;code dir=&quot;auto&quot;&gt;--dry-run&lt;/code&gt;, which computes the full plan without writing anything, so you can see exactly what a run would do before it does it. Emails, sieve scripts, and file payloads are content-addressed, stored once by their hash and deduplicated across the archive. Work runs multi-threaded across a worker pool sized to your CPUs, with per-server connection caps respected automatically and no async runtime involved. And each archive remembers which account filled it, so pointing it at a different one by mistake fails unless you explicitly allow it.&lt;/p&gt;
&lt;p&gt;A typical migration is two commands:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# 1. Import an IMAP mailbox into a fresh archive.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;VANDELAY_PASSWORD&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;source-app-password&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;vandelay&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;imap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--url&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;imaps://imap.example.com&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--auth-basic&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;alice@example.com&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;alice.sqlite&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# 2. Push the archive into a target JMAP server.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;VANDELAY_PASSWORD&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;target-password&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;vandelay&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--url&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://jmap.example.org&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--auth-basic&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;alice@example.org&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--account-name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;alice@example.org&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;alice.sqlite&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;There is also an &lt;code dir=&quot;auto&quot;&gt;inspect&lt;/code&gt; command that dumps any object type from an archive (mailbox tree, message list, contacts, calendar events, and so on) without ever opening a network connection, which is handy for verifying a capture before you push it anywhere.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;account-backup-tool&quot;&gt;Account backup tool&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Migrating between Stalwart versions over JMAP is what prompted Vandelay, but it is far from all it does. The first thing that falls out of the design is backup. Because an archive is a self-contained SQLite file that fully describes one account, you can treat it as a per-account backup in its own right. Run an import on a schedule to capture a fresh snapshot, keep the resulting file, and restore it later by running an export against any JMAP target. Since imports are convergent, each scheduled run only has to fetch what changed rather than re-reading the whole account every time.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;migrating-from-legacy-servers-and-formats&quot;&gt;Migrating from legacy servers and formats&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Vandelay reads from a wide range of sources, not just JMAP, which makes it a practical way off an older self-hosted stack. Over IMAP it imports mail from any server, with folder selection by regex, exact name, or SPECIAL-USE role. Over CalDAV and CardDAV it imports calendars and events, address books and contacts, and over WebDAV it imports a file collection as a JMAP &lt;code dir=&quot;auto&quot;&gt;FileNode&lt;/code&gt; tree. ManageSieve brings across sieve scripts and records which one is active. It can also read a local Maildir++ tree straight off disk, with no network involved at all.&lt;/p&gt;
&lt;p&gt;In practice this means Vandelay is a path off Dovecot, Cyrus, Radicale, Baikal, Apache &lt;code dir=&quot;auto&quot;&gt;mod_dav&lt;/code&gt;, and similar servers, and onto a JMAP server such as Stalwart, with mail, calendars, contacts, files, and filters all moving through the same tool.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;moving-off-google-and-microsoft-exchange&quot;&gt;Moving off Google and Microsoft Exchange&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;For accounts that live on a proprietary platform, Vandelay can pull data out of the two big ones. Google data exported through Takeout imports directly: Vandelay scans a directory tree for &lt;code dir=&quot;auto&quot;&gt;.mbox&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;.ics&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;.vcf&lt;/code&gt; files and brings in the mail, calendars, and contacts it finds. It is tuned to the Takeout layout but works on any such tree.&lt;/p&gt;
&lt;p&gt;For Microsoft Exchange, Vandelay can read mailboxes two ways. Over EWS it works against either on-premises Exchange Server or Exchange Online, with autodiscover, Basic auth, pre-acquired bearer tokens, interactive device-code OAuth, and app-only client-credentials OAuth. Over Microsoft Graph it reads Exchange Online mailboxes, using the interactive device-code flow by default.&lt;/p&gt;
&lt;p&gt;One clear caveat: Exchange support is experimental. So far it has only been tested against a mock server, not a real Exchange deployment. The code paths are there and they pass against the mock, but Exchange is a large and quirky target, and we would not feel right calling this production-ready until it has met real mailboxes. If you have an Exchange tenant or an on-prem server and some appetite for testing, this is exactly the kind of help that moves a feature from experimental to supported. Please &lt;a href=&quot;https://github.com/stalwartlabs/vandelay/&quot;&gt;open an issue&lt;/a&gt; with what you find.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;sovereignty-over-your-data&quot;&gt;Sovereignty over your data&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;There is a bigger reason we built the importers as broadly as we did, and it is not only about Stalwart upgrades.&lt;/p&gt;
&lt;p&gt;A lot of email, calendar, and contact data lives today on platforms where the operator, not the user, holds the keys. Getting your own data out of Google or Microsoft in a form you can actually use somewhere else is harder than it should be, and that friction is not accidental. It is what keeps people on a platform long after the reasons for choosing it have faded.&lt;/p&gt;
&lt;p&gt;Owning your data means being able to leave. Vandelay is meant to make leaving straightforward: pull a full account out of a proprietary platform, hold it in an open, inspectable SQLite file that you control, and push it into a modern open-source JMAP server that you run yourself. No lock-in on the way in, and an open format in the middle that you can read with &lt;code dir=&quot;auto&quot;&gt;sqlite3&lt;/code&gt; if you ever want to. Self-hosting is the part of the privacy conversation that is easy to agree with and hard to act on, and a migration tool that actually works is one of the things that makes acting on it realistic.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;what-is-next&quot;&gt;What is next&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Vandelay is the first installment, not the whole story. The zero-downtime migration path we described still needs its second half, the migration proxy that lets clients keep talking to a single endpoint while accounts move from the old server to the new one behind it. That work is underway now, and we expect to release it in about two to three weeks.&lt;/p&gt;
&lt;p&gt;When the proxy ships, we will also publish proper documentation covering the full migration workflow end to end, including how to use Vandelay as part of it. For now, the &lt;a href=&quot;https://github.com/stalwartlabs/vandelay/&quot;&gt;README&lt;/a&gt; is the documentation, and it covers every importer, every flag, and the quick-start path in detail.&lt;/p&gt;
&lt;p&gt;If you have been putting off an upgrade, or you have data sitting on a platform you would rather not be on, &lt;a href=&quot;https://github.com/stalwartlabs/vandelay/&quot;&gt;Vandelay&lt;/a&gt; is ready to try today. We would love to hear how it goes, and if you can help us test the Exchange importers against the real thing, even better.&lt;/p&gt;</content:encoded><category>vandelay</category><category>migration</category><category>backup</category><category>jmap</category><category>imap</category><category>caldav</category><category>carddav</category><category>exchange</category><category>server</category></item><item><title>MTA Hooks at the IETF</title><link>https://stalw.art/blog/mta-hooks-ietf/</link><guid isPermaLink="true">https://stalw.art/blog/mta-hooks-ietf/</guid><description>Two years ago we shipped MTA Hooks in Stalwart Mail Server as a modern, HTTP-based alternative to Milter. In the time since, it has gone from a Stalwart feature to a protocol used across thousands of deployments worldwide, with implementations being built by third parties and interest from major players in the mail filtering ecosystem. We are now taking the next step: standardizing MTA Hooks at the IETF, so that it stops being &quot;the Stalwart way of doing things&quot; and becomes an open protocol that any MTA and any filter can speak.

</description><pubDate>Thu, 21 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h3 id=&quot;what-is-mta-hooks&quot;&gt;What is MTA Hooks&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;If you have been running Stalwart for a while you have probably already met MTA Hooks. We &lt;a href=&quot;https://stalw.art/blog/webhooks/&quot;&gt;introduced it in version 0.8.2&lt;/a&gt;, alongside Webhooks, as part of our broader effort to make Stalwart’s filtering and observability layer feel like the rest of modern infrastructure rather than like 1998.&lt;/p&gt;
&lt;p&gt;MTA Hooks is an HTTP-based protocol that lets a mail server delegate per-stage decisions to external services. At each SMTP stage (connect, ehlo, mail, rcpt, data on the inbound side; delivery, defer, and DSN on the outbound side), the MTA sends an HTTP POST to a registered scanner. The scanner gets the envelope, the parsed message, the raw message, authentication results, TLS state and connection context, and replies with an action (accept, reject, quarantine, and so on) plus optional modifications expressed as JSON Pointer patches. Multiple scanners can be chained. Serialization is JSON or CBOR. Everything is just HTTP over TLS with a documented schema, which means any language with an HTTP library can implement either side without a binary protocol parser in sight.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;why-it-was-built&quot;&gt;Why it was built&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Most mail filtering today still rides on Milter, the protocol Sendmail introduced around the year 2000. Milter does its job, but it carries a number of design choices that have aged poorly. There is no formal specification: the protocol is defined by &lt;code dir=&quot;auto&quot;&gt;libmilter&lt;/code&gt;, a C library whose wire semantics are documented only by reading the source. The two MTAs that support Milter (Sendmail and Postfix) have behaviourally divergent implementations, so a filter that works against one cannot always be relied on to behave identically against the other. Milter has no concept of outbound or post-delivery hooks, which means an entire category of use cases (delivery logging, compliance, DSN policy) sits outside its scope. And because the protocol is binary and C-centric, implementing a Milter filter in Go, Rust, Python, or whatever language your team actually uses is more painful than it should be in 2026.&lt;/p&gt;
&lt;p&gt;MTA Hooks addresses these specifically. It has a written specification. It covers the full SMTP lifecycle, inbound and outbound. It speaks HTTP, so every HTTP load balancer, reverse proxy, observability stack, and auth middleware you already run works out of the box. It has explicit capability negotiation, so a scanner that does not understand a new stage simply will not subscribe to it, and the MTA and the scanner can evolve independently without breaking each other.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;why-standardization-matters&quot;&gt;Why standardization matters&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;We could have kept MTA Hooks as a Stalwart-only feature and called it done. We deliberately did not, for two reasons.&lt;/p&gt;
&lt;p&gt;The first reason is that a protocol that only one mail server speaks is not a protocol, it is an API. If you want filter authors to invest real engineering effort into supporting it, they need confidence that the wire format will not shift under them at our convenience, and that other mail servers will speak it too. Standardization is how you give them that confidence.&lt;/p&gt;
&lt;p&gt;The second reason is the larger one. Email filtering is critical infrastructure for the internet. The mechanism by which a substantial fraction of the world’s mail gets inspected for spam, viruses, and policy violations should not be controlled by a single vendor’s source tree, no matter how friendly the vendor. The right home for a protocol of this scope is an open standards body, and for internet protocols the open standards body that matters is the IETF.&lt;/p&gt;
&lt;p&gt;Standardization also forces a kind of rigour that internal development simply does not. Every assumption gets challenged, every edge case gets named, every security consideration gets cross-examined by people whose job is to find the corner you missed. The current draft is already noticeably better than what we shipped, precisely because reviewers have pushed back on parts we had taken for granted.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;how-the-ietf-actually-works-briefly&quot;&gt;How the IETF actually works, briefly&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;If you have never been near the IETF, the process is shorter to describe than it looks. Someone writes an Internet-Draft, a versioned document describing a proposed protocol. Drafts are individual submissions until a Working Group adopts them, at which point they become Working Group documents. The WG iterates on the document in public, on a mailing list and in meetings, until it reaches consensus. At that point the draft enters Working Group Last Call, then goes to the Internet Engineering Steering Group, and if approved becomes an RFC on the Standards Track.&lt;/p&gt;
&lt;p&gt;For a Working Group to be chartered, the IETF needs to see two things: a clear problem that justifies dedicated effort, and a community of people prepared to actually do the work and use the result. This is established through a Birds of a Feather session, universally abbreviated to BOF. A BOF is a one-time meeting at an IETF where the proponents make the case for the work and the room either does or does not show enough interest to justify forming a Working Group. You get one BOF. If it does not go well, the work does not die exactly, but it loses a substantial amount of momentum and may take a long time to recover.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;where-mta-hooks-is-right-now&quot;&gt;Where MTA Hooks is right now&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The current draft is &lt;a href=&quot;https://datatracker.ietf.org/doc/draft-degennaro-mta-hooks/&quot;&gt;draft-degennaro-mta-hooks-01&lt;/a&gt;. It has been presented twice at IETF meetings: at MAILMAINT at IETF 123 in Madrid, and at DISPATCH at IETF 125. Both sessions encouraged us to proceed toward a BOF. We have submitted the BOF request, and the responsible Area Director has asked us, very reasonably, to spend the time before the BOF building visible community engagement and a worked-out Working Group charter.&lt;/p&gt;
&lt;p&gt;To support that, a dedicated mailing list now exists for the work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;List&lt;/strong&gt;: &lt;a href=&quot;mailto:mtahooks@ietf.org&quot;&gt;mtahooks@ietf.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt;: &lt;a href=&quot;https://mailman3.ietf.org/mailman3/lists/mtahooks.ietf.org/&quot;&gt;https://mailman3.ietf.org/mailman3/lists/mtahooks.ietf.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On the ecosystem side, &lt;a href=&quot;https://rspamd.com/&quot;&gt;Rspamd&lt;/a&gt; plans to implement MTA Hooks support on the scanner side. &lt;a href=&quot;https://fastmail.com&quot;&gt;Fastmail&lt;/a&gt; and &lt;a href=&quot;https://heinlein-support.de&quot;&gt;Heinlein&lt;/a&gt; are also involved in the proposal. And of course MTA Hooks is in production today in every Stalwart deployment that uses it.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;how-you-can-help&quot;&gt;How you can help&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The single most useful thing a Stalwart user can do right now is post to the mailing list. Not a long technical review, not a polished position paper, just a short message saying that you exist, that you are interested in MTA Hooks becoming a standard, and (if applicable) a sentence or two about how you use it or plan to use it. That kind of post takes five minutes to write and is worth a surprising amount when the IETF is deciding whether to charter a Working Group. The IESG and the chairs look very hard at who is going to use the result; visible, named interest from real operators and real integrators is the most persuasive signal there is.&lt;/p&gt;
&lt;p&gt;You do not need to be an IETF regular. You do not need to have read the entire 60-page draft. You do not need to have an opinion on every design decision. If you read this far and the idea of an open standard for MTA filtering matters to you, even passively, please join the list and say so. If you have time to read the draft and push back on anything in it, even better, but the bar for being useful is low and the impact is real.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;what-is-next&quot;&gt;What is next&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The proximate milestone is the BOF, currently targeting IETF 126 if charter discussion converges in time, with a virtual interim BOF as the fallback. Between now and then, the work happens on the mailing list: refining the charter, gathering implementation reports, and addressing reviewer comments on the draft. If the BOF goes well, a Working Group gets chartered, the draft becomes a WG document, and the path to an RFC opens up.&lt;/p&gt;
&lt;p&gt;If it goes really well, the next time we write a blog post about MTA Hooks, we will be linking to an RFC number rather than a draft number. That is the goal. We would like as many of you as possible to be part of getting there.&lt;/p&gt;
&lt;p&gt;See you on the list.&lt;/p&gt;</content:encoded><category>mta-hooks</category><category>ietf</category><category>standards</category><category>milter</category><category>smtp</category><category>mail</category><category>server</category></item><item><title>Introducing the Stalwart Support Portal</title><link>https://stalw.art/blog/support-portal/</link><guid isPermaLink="true">https://stalw.art/blog/support-portal/</guid><description>Today we are launching support.stalw.art, the new home for Stalwart community and Enterprise support. The portal consolidates the conversations that until now were scattered across GitHub Discussions, Discord, Matrix, and Reddit into a single, searchable place, so that questions can be found, answered, and revisited without depending on any one third-party platform.

</description><pubDate>Thu, 07 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;For most of the project’s life, support has happened wherever the community already was: GitHub Discussions for users following the repository, Discord and Matrix for real-time chat, and Reddit for the wider conversation. That worked well when the project was small. It does not scale.&lt;/p&gt;
&lt;p&gt;As Stalwart has grown, we have started receiving hundreds of questions per day across these channels combined. A meaningful share of them have already been answered, sometimes more than once, on a different platform. Tracking four parallel inboxes, deduplicating threads, and making sure no one is left waiting has become a job we can no longer do reliably. The result is the opposite of what a support channel should produce: slower answers, repeated work for the people helping out, and good information buried in chat scrollback where the next person with the same question will never find it.&lt;/p&gt;
&lt;p&gt;There is a second reason, raised by users themselves. Several community members have told us they would rather not open a GitHub or Discord account just to ask a question. That is a fair concern, and we agree that asking for help should not require signing up to a third-party platform that the user otherwise has no use for.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;what-the-support-portal-is&quot;&gt;What the support portal is&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://support.stalw.art&quot;&gt;support.stalw.art&lt;/a&gt; is a Discourse instance that we operate ourselves. It is hosted at Hetzner in their Germany datacenters and is GDPR-compliant, so the data stays in the EU and under European data protection law.&lt;/p&gt;
&lt;p&gt;Discourse is open source, it indexes well, and it is built around the idea that a question and its answer should be permanent and findable. Threads are easy to link to, replies have stable URLs, and the search is good enough that the next user with the same problem has a real chance of finding the existing answer before opening a new topic. Over time, this should turn the portal into a knowledge base that the project actually owns, rather than one scattered across platforms we do not control.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;how-to-sign-in&quot;&gt;How to sign in&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Registration is open. You can sign in with the account you already use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;Google&lt;/li&gt;
&lt;li&gt;Discord&lt;/li&gt;
&lt;li&gt;LinkedIn&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Or, if you would rather not link an external account, you can register with any valid email address and a password. The choice is yours, and the experience inside the portal is the same either way.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;what-happens-to-the-existing-channels&quot;&gt;What happens to the existing channels&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;GitHub Discussions, Discord, Matrix, and Reddit are not going away. They remain useful for casual chat, announcements, and community conversation, and we will continue to read them. What is changing is where support questions are answered: from now on, the canonical place to ask is &lt;a href=&quot;https://support.stalw.art&quot;&gt;support.stalw.art&lt;/a&gt;, and that is where our team’s attention will be focused. If you ask a support question on one of the chat channels, expect to be pointed at the portal so that the answer ends up somewhere durable.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;enterprise-support&quot;&gt;Enterprise support&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Enterprise customers with priority support will shortly receive an email with instructions for accessing the Priority Support area on the portal. Priority Support tickets stay private to your organization and to our team, with the response-time commitments that come with your subscription. Nothing changes about the support entitlement itself; the portal is simply where it now lives.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;looking-forward&quot;&gt;Looking forward&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Thank you to everyone who has helped one another across the old channels over the years. The portal is built on top of that work, and we are looking forward to seeing the conversation continue in a place where it can finally accumulate.&lt;/p&gt;</content:encoded><category>community</category><category>support</category><category>announcement</category></item><item><title>Stalwart v0.16: A New Foundation</title><link>https://stalw.art/blog/stalwart-0-16/</link><guid isPermaLink="true">https://stalw.art/blog/stalwart-0-16/</guid><description>After more than three months of focused work, we are thrilled to announce the release of Stalwart v0.16. This is easily the most ambitious release we have ever shipped, with literally hundreds of new features, improvements, and fixes across every corner of the server.

We will be upfront about something: v0.16 will feel like a new product on first contact. Several long-standing concepts have been reworked, a few have been removed, and many new ones have been introduced. This was a deliberate choice. Stalwart has been under continuous development for nearly five years, and both the feature set and the user base have grown far beyond what the original configuration and management layer was designed for. Rather than keep patching around those limits, we took the opportunity to rebuild the foundation. The payoff is a much cleaner architecture and a long list of features that were simply not implementable before, many of which had been sitting on the community wishlist for years.

Let&apos;s walk through the highlights.

</description><pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;a-brand-new-webui&quot;&gt;A Brand-New WebUI&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/stalwartlabs/webui&quot;&gt;WebUI&lt;/a&gt; has been rewritten from the ground up. It has a refreshed, modern look, and it resolves a backlog of 76 enhancement requests and bug fixes that had accumulated over the years. If there was something you had been missing, there is a very good chance it is now there.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://stalw.art/img/demo.gif&quot; alt=&quot;Stalwart v0.16 WebUI&quot;&gt;&lt;/p&gt;
&lt;p&gt;The most requested addition is also the most consequential: the new WebUI can authenticate against external OIDC providers. Signing in with Keycloak, Authentik, Authelia, Zitadel, or any other standards-compliant identity provider is now a first-class flow, with full support for audience and scope validation, group claims, and PKCE (RFC 7636) for public clients. This has been one of the most frequent community asks, and it is finally here.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;unified-management-via-jmap-and-a-new-cli&quot;&gt;Unified Management via JMAP and a New CLI&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In previous releases, Stalwart was managed through a REST API that lived alongside its native JMAP interface. In v0.16, the REST API is gone. Every configuration and management action is now a JMAP object, reachable through the same &lt;code dir=&quot;auto&quot;&gt;/jmap&lt;/code&gt; endpoint that already serves email, calendars, contacts, and files.&lt;/p&gt;
&lt;p&gt;The benefits of this change are hard to overstate. JMAP (RFC 8620) is a well-specified, transport-efficient protocol with first-class support for batch operations, push notifications, and fine-grained change tracking. In practice, this means dozens of configuration changes can be applied in a single round-trip, any JMAP client library can drive the management surface, and a single authentication flow covers both mail access and administration. Centralizing configuration inside the datastore as JMAP objects also removes an entire category of operator confusion: there is no longer a split between “settings in a file” and “settings in the database”, and in clustered deployments the configuration is consistent across every node by definition.&lt;/p&gt;
&lt;p&gt;Alongside the WebUI, we also shipped a &lt;a href=&quot;https://github.com/stalwartlabs/cli&quot;&gt;brand-new CLI&lt;/a&gt;. The new &lt;code dir=&quot;auto&quot;&gt;stalwart-cli&lt;/code&gt; is built on top of the same JMAP management API and can configure and administer every aspect of Stalwart. It is designed for day-to-day administration, scripted deployments, and infrastructure-as-code workflows. The &lt;code dir=&quot;auto&quot;&gt;stalwart-cli apply&lt;/code&gt; subcommand takes a declarative plan file and idempotently reconciles the live server state to match it, creating what is missing, updating what has changed, and removing what the plan no longer declares. This fits naturally with Ansible, Terraform, NixOS, and similar tooling, and follows the same pattern used by projects like CockroachDB, Consul, Elasticsearch, and HashiCorp Vault, where infrastructure-as-code tools target an API rather than a configuration file.&lt;/p&gt;
&lt;p&gt;The new CLI is also a very pleasant surface for AI agents. Because every operation maps to a well-defined JMAP object with a clear schema, agents can discover capabilities, plan changes, and apply them idempotently without any bespoke integration work.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;automated-dns-management&quot;&gt;Automated DNS Management&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In previous releases, Stalwart only managed the &lt;code dir=&quot;auto&quot;&gt;TXT&lt;/code&gt; records required for the ACME DNS-01 challenge. In v0.16, it can take care of every DNS record a modern mail and collaboration server needs: &lt;code dir=&quot;auto&quot;&gt;MX&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;TXT&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;CNAME&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;SRV&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;CAA&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;TLSA&lt;/code&gt;. The server computes the records your deployment should be publishing and keeps them in sync with your DNS provider automatically.&lt;/p&gt;
&lt;p&gt;This covers most of the authentication and discovery story out of the box. SPF, DKIM, and DMARC records are managed alongside autoconfig and autodiscover &lt;code dir=&quot;auto&quot;&gt;SRV&lt;/code&gt; records, &lt;code dir=&quot;auto&quot;&gt;CAA&lt;/code&gt; records for certificate issuance authorization (including the &lt;code dir=&quot;auto&quot;&gt;accounturi&lt;/code&gt; parameter for account-scoped issuance), and &lt;code dir=&quot;auto&quot;&gt;TLSA&lt;/code&gt; records for DANE. The &lt;code dir=&quot;auto&quot;&gt;TLSA&lt;/code&gt; records are automatically refreshed when ACME certificates are renewed, so DANE-enabled domains no longer risk a validation gap during certificate rotation.&lt;/p&gt;
&lt;p&gt;On the provider side, v0.16 ships support for Route53, Google Cloud DNS, Bunny, Porkbun, DNSimple, and Spaceship, and also supports RFC 2136 dynamic updates signed with &lt;code dir=&quot;auto&quot;&gt;SIG(0)&lt;/code&gt; for operators running their own authoritative DNS.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;automated-dkim-rotation&quot;&gt;Automated DKIM Rotation&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;DKIM key rotation is one of those tasks that everyone knows they should be doing, and almost nobody actually does, because it is tedious and easy to get wrong. In v0.16, Stalwart takes over the entire workflow. It can generate DKIM keys automatically, rotate them on a schedule, and publish the matching &lt;code dir=&quot;auto&quot;&gt;TXT&lt;/code&gt; records through the new DNS management layer so that the published keys always match the keys the server is signing with. DKIM keys are now stored in the database alongside the rest of the configuration, which means rotation works naturally in clustered deployments without any manual coordination.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;masked-emails&quot;&gt;Masked Emails&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Masked emails are disposable, per-service email addresses that route to a user’s real inbox. Instead of handing out a primary address to every newsletter, shop, or forum, a user can generate a unique masked address for each one. If a service leaks its database or starts sending unwanted mail, the corresponding masked address can be disabled individually, without affecting anything else and without touching the user’s real address. It is one of the most effective privacy tools available today, and it integrates cleanly with the rest of the directory in Stalwart.&lt;/p&gt;
&lt;p&gt;This feature is part of the Enterprise edition.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;security-enhancements&quot;&gt;Security Enhancements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Security gets a substantial upgrade in v0.16. User passwords can now be checked against the &lt;code dir=&quot;auto&quot;&gt;zxcvbn&lt;/code&gt; strength estimator at set-time, so weak credentials never make it into the system in the first place. Passwords can also be given explicit expiration and rotation policies, and user accounts can be restricted to specific IP ranges so that an account is only usable from expected networks.&lt;/p&gt;
&lt;p&gt;App passwords and API keys receive the same treatment, and then some. Both can now be scoped to a specific set of permissions rather than inheriting the full privileges of the owning account, which means a token used by a single IMAP client or a single automation script can be limited to exactly what it needs. Both also support human-readable labels, expiration dates, and IP address restrictions, so long-lived credentials can be audited, rotated, and confined without having to revoke them entirely.&lt;/p&gt;
&lt;p&gt;Taken together, these features make the credentials surface of a Stalwart deployment dramatically easier to reason about and lock down.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;other-highlights&quot;&gt;Other Highlights&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;There are many other additions worth calling out. On the account configuration front, v0.16 implements the new &lt;a href=&quot;https://datatracker.ietf.org/doc/html/draft-eggert-mailmaint-uaautoconf-04&quot;&gt;Automatic Configuration of Email, Calendar, and Contact Server Settings draft&lt;/a&gt;, which is shaping up to replace the fragmented autoconfig and autodiscover mechanisms clients use today, and adds MS Autodiscover V2 support for environments that still rely on it.&lt;/p&gt;
&lt;p&gt;The directory layer gains domain aliases, alias descriptions, the ability to disable aliases without deleting them, and, for the Enterprise edition, account archiving and un-deletion and per-domain directory backends. The ACME layer picks up the new &lt;code dir=&quot;auto&quot;&gt;DNS-PERSIST-01&lt;/code&gt; challenge, on-demand certificate renewal, and a certificate detail view. Sieve scripts can now be deactivated without being deleted. Clustering is cleaner, with automatic node ID generation, unified cluster management, and a new outbound MTA role for dedicated queue nodes.&lt;/p&gt;
&lt;p&gt;On top of all of this, dozens of bug fixes land across the directory, MTA, JMAP, IMAP, WebDAV, CalDAV, OIDC, and storage backends. If you have been tracking an issue, there is a good chance it is resolved in v0.16.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;upgrading&quot;&gt;Upgrading&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Because of the scope of the architectural changes, v0.16 is a &lt;strong&gt;major upgrade with multiple breaking changes&lt;/strong&gt;. Please do not upgrade a production deployment without first reading the &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/blob/main/UPGRADING/v0_16.md&quot;&gt;upgrading documentation&lt;/a&gt; in full. We also strongly recommend spinning up a fresh v0.16 instance in a container or throwaway VM first, getting comfortable with the new WebUI and CLI, and exporting any settings you build there as an &lt;code dir=&quot;auto&quot;&gt;apply&lt;/code&gt; plan to replay against production after the migration.&lt;/p&gt;
&lt;p&gt;If any questions come up along the way, a dedicated discussion thread for the v0.16 upgrade is open at &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/discussions/3004&quot;&gt;https://github.com/stalwartlabs/stalwart/discussions/3004&lt;/a&gt;. We will be following it closely.&lt;/p&gt;
&lt;p&gt;This release has been in the making for over three months, and it represents one of the largest single steps forward in Stalwart’s history. Thank you to everyone who filed bugs, contributed code, tested pre-releases, and kept the conversation going in issues and discussions: v0.16 is very much your release too. We cannot wait to hear what you build with it.&lt;/p&gt;</content:encoded><category>release</category><category>webui</category><category>jmap</category><category>cli</category><category>dns</category><category>dkim</category><category>oidc</category><category>security</category></item><item><title>Marginal Gains: Major Impact</title><link>https://stalw.art/blog/marginal-gains/</link><guid isPermaLink="true">https://stalw.art/blog/marginal-gains/</guid><description>In professional cycling, the concept of marginal gains became famous through Team Sky. Rather than chasing dramatic breakthroughs, they focused on making hundreds of small improvements: slightly better bike fit, marginally lighter components, improved sleep, cleaner nutrition. None of these changes mattered much on their own, but together they reshaped performance—and helped dominate the sport for years.

Software systems, especially large distributed ones, work much the same way. Rarely does a single feature transform everything overnight. More often, real progress comes from careful attention to small details: shaving latency here, reducing contention there, simplifying a hot path, rethinking a data structure.

Stalwart v0.15 is very much a release in this spirit. It does not introduce a long list of headline features. Instead, it is the result of revisiting core subsystems—spam filtering, search, storage, and data access—and making many targeted improvements that, together, have a significant impact on performance, reliability, and usability.

</description><pubDate>Tue, 16 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;rethinking-spam-classification&quot;&gt;Rethinking Spam Classification&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Stalwart v0.14 (and earlier) included a spam classifier which was a direct port of the classifier used by Rspamd. This classifier is grounded in Bayesian theory and uses more advanced methods to combine probabilities, including sparse bigrams (OSB) and the inverse chi-square distribution. This approach is well understood and robust, particularly when training data is limited. It produces reasonable results quickly and has a long track record in production systems.&lt;/p&gt;
&lt;p&gt;However, it comes with a significant cost in distributed environments. Both Rspamd and Stalwart v0.14 relied on OSB-5, which generates a very large number of features per message. Each of these features was stored in Redis. Even with aggressive caching, training or classifying a single message could involve hundreds or even thousands of round trips to Redis. At scale, this becomes a bottleneck: latency increases, throughput drops, and horizontal scaling becomes inefficient.&lt;/p&gt;
&lt;p&gt;For v0.15, we went back to first principles and redesigned the spam classifier from scratch, guided by more recent research. We evaluated several models and ultimately settled on a logistic regression classifier trained using the FTRL-Proximal (&lt;a href=&quot;https://dl.acm.org/doi/10.1145/2487575.2488200&quot;&gt;Follow the Regularized Leader&lt;/a&gt;) algorithm. This algorithm—famously used by Google for large-scale online learning—is particularly well suited to spam classification workloads where models must be updated continuously and efficiently.&lt;/p&gt;
&lt;p&gt;One immediate benefit of this approach is that Stalwart can now support collaborative filtering out of the box. Multiple users can benefit from a single shared classifier trained on aggregated data, dramatically improving accuracy in environments with many accounts. At the same time, individual users can still maintain their own personal classifiers trained solely on their own messages.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://stalw.art/docs/spamfilter/classifier/&quot;&gt;new classifier&lt;/a&gt; also adopts feature hashing (often called the &lt;em&gt;hashing trick&lt;/em&gt;) to keep the feature space compact and predictable. This significantly reduces memory usage and improves cache locality. For very large deployments, cuckoo feature hashing is available to further reduce hash collisions. If you are interested in the theoretical background, the original feature hashing paper is available at &lt;a href=&quot;https://arxiv.org/pdf/0902.2206&quot;&gt;Feature Hashing for Large Scale Multitask Learning&lt;/a&gt; and the cuckoo feature hashing paper at &lt;a href=&quot;https://www.ijcai.org/proceedings/2018/0295.pdf&quot;&gt;Cuckoo Feature Hashing: Dynamic Weight Sharing for Sparse Analytics&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With the default configuration of 2²⁰ features, the entire model fits in approximately 4 MB of memory and is loaded only once after each training cycle. The result is a classifier that is both faster and more accurate than the previous version, particularly in distributed deployments where network overhead matters.&lt;/p&gt;
&lt;p&gt;We also evaluated RetVec (&lt;a href=&quot;https://arxiv.org/abs/2302.09207&quot;&gt;Resilient and Efficient Text Vectorizer&lt;/a&gt;), the embedding technique used by Gmail. RetVec excels at generating compact semantic representations of email content, but it is primarily designed to feed neural networks and deep learning models. For now, logistic regression offers a better balance of simplicity, performance, and operational transparency. That said, we plan to ship a pre-trained RetVec model alongside BERT in a future release.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;a-faster-simpler-search-layer&quot;&gt;A Faster, Simpler Search Layer&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Search is another area where small architectural choices have outsized effects. In Stalwart v0.15, the search layer has been substantially rewritten.&lt;/p&gt;
&lt;p&gt;For deployments using PostgreSQL or MySQL, Stalwart now leverages the built-in full-text search capabilities of the database instead of relying on a custom implementation. This reduces complexity, improves query planning, and allows the database to do what it already does well.&lt;/p&gt;
&lt;p&gt;We have also added support for &lt;a href=&quot;https://stalw.art/docs/storage/backends/meilisearch&quot;&gt;Meilisearch&lt;/a&gt;, a lightweight, fast search engine with excellent performance characteristics and simple operational semantics. Meilisearch offers low-latency full-text search, typo tolerance, and efficient indexing, making it a good fit for many Stalwart deployments.&lt;/p&gt;
&lt;p&gt;For large installations backed by FoundationDB, we plan to significantly improve the built-in search functionality by embedding Seekstorm. Until that work is complete, we recommend pairing FoundationDB with an external search engine such as OpenSearch or Meilisearch to achieve the best performance.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;faster-database-access-and-leaner-storage&quot;&gt;Faster Database Access and Leaner Storage&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Stalwart v0.15 includes a number of optimizations to the database access layer. We have reduced the number of reads and writes required to store and retrieve messages, particularly along hot paths such as IMAP and JMAP access. The result is noticeably faster message retrieval and improved overall responsiveness under load.&lt;/p&gt;
&lt;p&gt;In parallel, we revisited how email metadata is stored and reduced some serialization overhead. This lowers disk usage and improves cache efficiency, which again compounds into better performance at scale.&lt;/p&gt;
&lt;p&gt;Individually, these changes are modest. Collectively, they make the system feel tighter and more predictable under real-world workloads.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;meet-us-at-fosdem-2026&quot;&gt;Meet Us at FOSDEM 2026&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We are excited to announce that Stalwart will be present at FOSDEM 2026 in Brussels, Belgium.&lt;/p&gt;
&lt;p&gt;Our talk, &lt;a href=&quot;https://fosdem.org/2026/schedule/event/scaling-email/&quot;&gt;Stalwart: Can Open Source do Gmail-scale Email?&lt;/a&gt;, builds naturally on the marginal gains theme. While v0.15 focuses on incremental improvements, the talk zooms out to the other end of the spectrum: what it takes to design and operate a truly large-scale email system.&lt;/p&gt;
&lt;p&gt;Using a 1,024-node cluster as a concrete example, we will explore how modern providers store and index petabytes of messages, survive hardware failures without data loss, and run spam and phishing filtering across billions of daily deliveries. We will walk through the architectural patterns behind distributed storage, large-scale spam filtering, MTA queue management, and load balancing for IMAP, JMAP, and SMTP.&lt;/p&gt;
&lt;p&gt;We will also discuss cluster coordination, orchestration, autoscaling, and how to reason about failure before it happens. The goal is to give attendees a practical understanding of how planet-scale email systems are built, and how those same principles can be applied using open-source technology.&lt;/p&gt;
&lt;p&gt;If you are attending FOSDEM, we would love to meet you, answer questions, and talk about where Stalwart is heading next.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;looking-ahead&quot;&gt;Looking Ahead&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Stalwart v0.15 is a release shaped by the philosophy of marginal gains. There are no new flashy features, but there are dozens of small improvements that add up to something meaningful: faster spam classification, better scalability, simpler search, leaner storage, and more predictable performance.&lt;/p&gt;
&lt;p&gt;If you are already running Stalwart, we encourage you to &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/blob/main/UPGRADING/v0_15.md&quot;&gt;try v0.15&lt;/a&gt; and let us know how it performs in your environment. Your feedback continues to guide where we focus next.&lt;/p&gt;
&lt;p&gt;The team is already working on future releases that build on this foundation. With the core systems now leaner and more robust, we can continue to add new capabilities without compromising performance or reliability.&lt;/p&gt;
&lt;p&gt;As with cycling, progress comes from steady, thoughtful refinement. Stalwart v0.15 is one more step in that direction.&lt;/p&gt;</content:encoded><category>performance</category><category>spam</category><category>search</category><category>storage</category><category>marginal</category><category>gains</category></item><item><title>JMAP for Calendars, Contacts and Files now in Stalwart</title><link>https://stalw.art/blog/jmap-collaboration/</link><guid isPermaLink="true">https://stalw.art/blog/jmap-collaboration/</guid><description>After four years of development, we’re thrilled to announce a major milestone in the evolution of Stalwart — the full implementation of JMAP for Calendars, Contacts, File Storage, and Sharing. With this release, Stalwart becomes the first JMAP server to fully support the entire family of JMAP collaboration protocols, marking a new era for open, efficient, and elegant groupware.

</description><pubDate>Wed, 22 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;a-new-generation-of-protocols&quot;&gt;A New Generation of Protocols&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Over the past few years, the IETF has been redefining how email, calendars, and contacts are synchronized and shared. Building upon the success of JMAP for Mail, several new protocol extensions have been introduced:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://datatracker.ietf.org/doc/draft-ietf-jmap-calendars&quot;&gt;JMAP for Calendars&lt;/a&gt; - A modern replacement for CalDAV and CalDAV Scheduling.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://datatracker.ietf.org/doc/rfc9610/&quot;&gt;JMAP for Contacts&lt;/a&gt; – A powerful alternative to CardDAV.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://datatracker.ietf.org/doc/draft-ietf-jmap-filenode/&quot;&gt;JMAP for File Storage&lt;/a&gt; – A replacement for WebDAV-based file storage.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://datatracker.ietf.org/doc/rfc9670/&quot;&gt;JMAP Sharing&lt;/a&gt; – A modern successor to WebDAV ACL.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://datatracker.ietf.org/doc/draft-ietf-calext-jscalendarbis/&quot;&gt;JSCalendar&lt;/a&gt; - A clean, JSON-based evolution of iCalendar.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://datatracker.ietf.org/doc/rfc9553/&quot;&gt;JSContact&lt;/a&gt; – A modernized, JSON-native successor to vCard.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Together, these standards offer a cohesive and elegant ecosystem that replaces decades of fragmented WebDAV-based technologies.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;limitations-of-yesterdays-technology&quot;&gt;Limitations of Yesterday’s Technology&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;WebDAV and its descendants — CalDAV, CardDAV, and related extensions — have served the Internet well. They are robust, widely adopted, and battle-tested. Yet, their &lt;strong&gt;XML-based&lt;/strong&gt; design is notoriously verbose, inconsistent, and difficult to implement correctly. Information is scattered across HTTP headers, XML payloads, and even embedded iCalendar data, creating endless compatibility and interoperability challenges between clients and servers.&lt;/p&gt;
&lt;p&gt;Similarly, &lt;strong&gt;iCalendar&lt;/strong&gt; and &lt;strong&gt;vCard&lt;/strong&gt;, while expressive and versatile, have accumulated decades of technical debt. They contain countless properties and parameters—many rarely used, some obsolete, and others inconsistently implemented across versions. This clutter has made both formats unwieldy and error-prone, often requiring complex parsing logic to handle edge cases.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;jmap-a-modern-solution-for-modern-needs&quot;&gt;JMAP: A Modern Solution for Modern Needs&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The &lt;strong&gt;JMAP protocol&lt;/strong&gt; was originally developed as a more efficient, modern replacement for IMAP and SMTP submissions. Its strengths lie in simplicity, clarity, and network efficiency — all built on top of JSON over HTTPS.&lt;/p&gt;
&lt;p&gt;Now, with the introduction of &lt;strong&gt;JMAP for Calendars&lt;/strong&gt;, &lt;strong&gt;Contacts&lt;/strong&gt;, &lt;strong&gt;Files&lt;/strong&gt;, and &lt;strong&gt;Sharing&lt;/strong&gt;, the same design philosophy extends beyond email to the entire collaboration stack. These protocols deliver what DAV always aimed for but never quite achieved: a clean, uniform, and easily implementable API for all personal and group data — mail, calendars, contacts, files, and shared resources.&lt;/p&gt;
&lt;p&gt;Meanwhile, &lt;strong&gt;JSCalendar&lt;/strong&gt; and &lt;strong&gt;JSContact&lt;/strong&gt; reimagine iCalendar and vCard as elegant JSON-based formats. They strip away decades of accumulated cruft, unify representations, and offer a clear, unambiguous, and expressive data model. Both are human-readable, developer-friendly, and efficient to parse — a perfect fit for modern applications.&lt;/p&gt;
&lt;p&gt;Together, JMAP and these new data models make calendaring, contact management, and file sharing not only easier to implement but also faster and more reliable.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;why-this-matters&quot;&gt;Why This Matters&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release represents more than new features — it marks a shift in how groupware protocols are designed and implemented. For the first time, developers and organizations can build on &lt;strong&gt;a single, coherent, JSON-based framework&lt;/strong&gt; for mail, contacts, calendars, and shared resources.&lt;/p&gt;
&lt;p&gt;We believe this will &lt;strong&gt;revolutionize calendaring and collaboration&lt;/strong&gt;. Implementations will become easier, interoperability issues will decrease, and innovation will accelerate. The simplicity and predictability of JMAP empower both clients and servers to focus on features and user experience, not protocol gymnastics.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;client-support-and-ecosystem&quot;&gt;Client Support and Ecosystem&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;As Stalwart is the first complete JMAP server to support these new protocols, client support is still emerging. However, we’re excited to share that several projects are already working to adopt these new standards. &lt;a href=&quot;https://mailtemi.com/&quot;&gt;Mailtemi&lt;/a&gt; and &lt;a href=&quot;https://opencloud.eu/en&quot;&gt;OpenCloud&lt;/a&gt; are actively developing client-side implementations for &lt;strong&gt;JMAP Calendars&lt;/strong&gt;, &lt;strong&gt;Contacts&lt;/strong&gt;, and &lt;strong&gt;File Storage&lt;/strong&gt;. The ecosystem is growing, and we expect rapid adoption as developers experience the elegance and power of JMAP firsthand.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;a-word-of-thanks&quot;&gt;A Word of Thanks&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We would like to express our sincere gratitude to &lt;a href=&quot;https://nlnet.nl/&quot;&gt;NLNet&lt;/a&gt; for supporting the development of these features through the &lt;a href=&quot;https://nlnet.nl/commonsfund/&quot;&gt;NGI Zero grant program&lt;/a&gt;. Their commitment to open standards and privacy-respecting technology continues to make projects like Stalwart possible.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;looking-ahead-to-100&quot;&gt;Looking Ahead to 1.0.0&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;After four years of dedicated development, we’re proud to announce that &lt;strong&gt;Stalwart is now feature complete&lt;/strong&gt;. With this milestone, all the core capabilities of a modern mail and collaboration server are fully implemented.&lt;/p&gt;
&lt;p&gt;That said, our work is far from over. We are now focusing on &lt;strong&gt;finalizing the database schema&lt;/strong&gt;, &lt;strong&gt;improving performance&lt;/strong&gt;, and addressing the &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement&quot;&gt;hundreds of enhancement requests&lt;/a&gt; on GitHub. Our goal is to deliver a stable &lt;code dir=&quot;auto&quot;&gt;1.0.0&lt;/code&gt; release within the next few months — one that sets a new standard for open, efficient, and modern communication servers.&lt;/p&gt;
&lt;p&gt;Stalwart is now the most complete, elegant, and forward-looking JMAP collaboration platform available.&lt;/p&gt;
&lt;p&gt;And this is only the beginning.&lt;/p&gt;</content:encoded><category>jmap</category><category>calendar</category><category>contacts</category><category>files</category><category>collaboration</category><category>groupware</category></item><item><title>Security at the Core: Stalwart completes Second Security Audit</title><link>https://stalw.art/blog/security-audit-2025/</link><guid isPermaLink="true">https://stalw.art/blog/security-audit-2025/</guid><description>At Stalwart Labs, security is at the heart of everything we build. As part of our ongoing commitment to delivering a trustworthy email and collaboration server, we recently completed our second independent security audit, conducted by Radically Open Security. Our previous audit took place exactly two years ago, in 2023 — and with significant changes to our codebase since then, a fresh and thorough assessment was essential.

</description><pubDate>Tue, 07 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;comprehensive-assessment&quot;&gt;Comprehensive Assessment&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The audit, conducted between &lt;strong&gt;September 9 and September 25, 2025&lt;/strong&gt;, focused on version &lt;strong&gt;v0.13.2&lt;/strong&gt; of Stalwart mail and collaboration server. The goal was clear: rigorously evaluate the security posture of the platform, identify potential vulnerabilities, and ensure our defenses are as strong as possible.&lt;/p&gt;
&lt;p&gt;The penetration test followed a “crystal-box” methodology, combining source code review with targeted exploitation attempts. This included testing against the latest &lt;a href=&quot;https://owasp.org/&quot;&gt;OWASP Top 10&lt;/a&gt; risks, analyzing protocol implementations, and probing external interfaces — the most exposed and therefore most critical components of the system.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;findings&quot;&gt;Findings&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The audit uncovered a total of &lt;strong&gt;seven security issues&lt;/strong&gt;: &lt;strong&gt;two high-severity vulnerabilities&lt;/strong&gt; and &lt;strong&gt;five low-severity issues&lt;/strong&gt;. All but one minor issue were promptly addressed.&lt;/p&gt;
&lt;p&gt;The most significant findings involved &lt;strong&gt;Denial-of-Service (DoS) vulnerabilities&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CVE-2025-59045 — Memory Exhaustion via CalDAV REPORT&lt;/strong&gt;: A crafted CalDAV request could trigger unbounded memory usage, potentially crashing the server.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CVE-2025-61600 — Unbounded Buffer Growth in IMAP Parser&lt;/strong&gt;: A flaw in the IMAP protocol parser could allow an attacker — even without authentication — to cause memory exhaustion.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both of these high-severity vulnerabilities were resolved &lt;strong&gt;within four hours of disclosure&lt;/strong&gt;, underscoring our team’s rapid response capability and deep focus on platform resilience. Patches were released in versions &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/releases/tag/v0.13.3&quot;&gt;v0.13.3&lt;/a&gt; and &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/releases/tag/v0.13.4&quot;&gt;v0.13.4&lt;/a&gt;, and the issues have been assigned &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/security/advisories/GHSA-xv4r-q6gr-6pfg&quot;&gt;CVE-2025-59045&lt;/a&gt; and &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/security/advisories/GHSA-8jqj-qj5p-v5rr&quot;&gt;CVE-2025-61600&lt;/a&gt;, respectively.&lt;/p&gt;
&lt;p&gt;Among the lower-severity findings were issues related to RFC compliance in email parsing, permission checks, and quota enforcement. These were addressed swiftly as well, with most fixes included in &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/releases/tag/v0.13.4&quot;&gt;v0.13.4&lt;/a&gt;. One low-severity race condition related to disk quotas (TOCTOU) remains partially mitigated; however, its practical impact is limited due to built-in concurrency controls.&lt;/p&gt;
&lt;p&gt;For those who would like a deep dive into the audit’s findings, the full report is accessible &lt;a href=&quot;./ros-report.pdf&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;our-commitment-to-security&quot;&gt;Our Commitment to Security&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The final report praised Stalwart’s codebase as &lt;strong&gt;robust, well-architected, and cleanly compartmentalized&lt;/strong&gt;, with memory safety ensured by Rust and attacker-aware design principles evident throughout. At the same time, the audit highlighted that our “build everything in-house” philosophy — while a strength — requires careful attention to detail, particularly in protocol parsing and input handling.&lt;/p&gt;
&lt;p&gt;Security is never a one-time checkbox — it’s an ongoing process. That’s why regular audits like this one are an integral part of how we develop Stalwart. As our platform evolves, so does our approach to safeguarding it.&lt;/p&gt;
&lt;p&gt;We’re proud of how quickly and effectively our team responded to the findings of this audit, and we remain committed to maintaining transparency and trust with our users and the broader open-source community.&lt;/p&gt;</content:encoded><category>security</category><category>audit</category><category>penetration</category><category>test</category></item><item><title>Stalwart Joins GitHub&apos;s Open Source Secure Fund</title><link>https://stalw.art/blog/github-ossf/</link><guid isPermaLink="true">https://stalw.art/blog/github-ossf/</guid><description>We&apos;re excited to announce that Stalwart has been selected to participate in Session 2 of GitHub&apos;s Open Source Secure Fund (OSSF), a prestigious program designed to enhance security across the open source ecosystem. This recognition represents not only an acknowledgment of Stalwart&apos;s growing importance in the email infrastructure space but also our commitment to maintaining the highest security standards.

</description><pubDate>Mon, 11 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;about-githubs-ossf&quot;&gt;About GitHub’s OSSF&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;GitHub launched the &lt;a href=&quot;https://resources.github.com/github-secure-open-source-fund/&quot;&gt;Open Source Secure Fund&lt;/a&gt; in November 2024 as a comprehensive initiative to strengthen security across the software supply chain. The program represents a strategic approach to open source security that goes far beyond simple financial support. Instead of merely providing funding, the initiative creates a structured pathway for maintainers to develop deep security expertise while building lasting connections within a community of security-focused developers.&lt;/p&gt;
&lt;p&gt;The fund operates on a model that combines immediate intensive training with long-term support and accountability. Each session consists of a three-week sprint, delivered by security experts from GitHub and their partners through the GitHub Security Lab. However, the relationship extends far beyond these initial weeks, with participants receiving ongoing support and resources throughout a full twelve-month engagement period.&lt;/p&gt;
&lt;p&gt;What makes this program particularly valuable is its emphasis on community building and ongoing support. Participants gain access to a specialized security-focused community and regular office hours with the GitHub Security Lab throughout the entire twelve-month period. This extended engagement ensures that the security improvements initiated during the sprint continue to evolve and mature over time.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;our-experience&quot;&gt;Our Experience&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The training component of our participation concluded six weeks ago, and we can confidently say it provided valuable insights that have already begun to shape Stalwart’s security posture. The comprehensive nature of the program allowed us to step back and evaluate our security practices from multiple perspectives, leading to concrete improvements in our security infrastructure.&lt;/p&gt;
&lt;p&gt;One of the most significant outcomes of our participation has been the development of a comprehensive &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/blob/main/SECURITY_PROCESS.md&quot;&gt;Incident Response Plan&lt;/a&gt; specifically tailored to Stalwart’s architecture and user base. This plan establishes clear protocols for identifying, containing, and resolving security incidents while maintaining transparency with our community. Having a well-defined incident response strategy is crucial for any mail server software, given the sensitive nature of email communications and the potential impact of security breaches.&lt;/p&gt;
&lt;p&gt;Additionally, we’ve substantially enhanced our existing &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/blob/main/SECURITY.md&quot;&gt;Security Policy&lt;/a&gt;, incorporating lessons learned from the GitHub training and feedback from security experts. This updated policy provides clearer guidelines for security researchers, establishes more robust vulnerability disclosure procedures, and outlines our commitment to maintaining security standards throughout Stalwart’s development lifecycle.&lt;/p&gt;
&lt;p&gt;The training also introduced us to various security concepts and tools, including an introduction to fuzzing techniques for discovering potential vulnerabilities. However, the Rust programming language’s memory safety guarantees and the security-conscious culture of the Rust community mean that many of the security recommendations from the GitHub program were already implemented in Stalwart’s codebase. This validation from security experts reinforced our choice of Rust as the foundation for Stalwart and highlighted the proactive security feedback we’ve received from the broader Rust ecosystem.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;leveraging-azure-credits&quot;&gt;Leveraging Azure Credits&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;While the GitHub funding provides important financial support for the project, we’re particularly excited about the $100,000 in Azure credits that accompany our participation in the program. These credits represent an unprecedented opportunity to conduct large-scale testing and optimization of Stalwart’s performance and security characteristics.&lt;/p&gt;
&lt;p&gt;We plan to use these Azure credits to deploy Stalwart across a massive cluster configuration, enabling us to generate millions of concurrent connections and simulate real-world load scenarios that would be impossible to replicate in smaller testing environments. This extensive testing will focus on three critical areas that are essential for any mail server infrastructure.&lt;/p&gt;
&lt;p&gt;First, we’ll conduct comprehensive performance testing to identify and resolve bottlenecks that might emerge under extreme load conditions. Email servers must handle varying loads gracefully, from quiet periods to sudden spikes in activity, and this testing will help us optimize Stalwart’s resource utilization and response times across all scenarios.&lt;/p&gt;
&lt;p&gt;Second, we’ll focus extensively on scalability improvements, ensuring that Stalwart can grow seamlessly from small deployments to enterprise-scale installations. Understanding how different components interact and potentially conflict under high-load conditions will enable us to make architectural improvements that benefit all users, regardless of their deployment size.&lt;/p&gt;
&lt;p&gt;Finally, and perhaps most importantly for security, we’ll conduct thorough resilience testing against various types of Denial of Service (DoS) attacks. Mail servers are frequent targets for such attacks, and having the ability to simulate these scenarios in a controlled environment will allow us to implement and verify defensive mechanisms that protect real deployments. The insights gained from this testing will be invaluable for administrators who need to deploy Stalwart in security-conscious environments.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;ongoing-security-audit&quot;&gt;Ongoing Security Audit&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Our commitment to security extends beyond the GitHub program, as evidenced by our current engagement with &lt;a href=&quot;https://www.radicallyopensecurity.com/&quot;&gt;Radically Open Security&lt;/a&gt; for a comprehensive second security audit of Stalwart. This audit represents a significant milestone in our security journey, coming approximately two years after our &lt;a href=&quot;https://stalw.art/blog/security-audit/&quot;&gt;first security audit&lt;/a&gt; conducted on October 7, 2023.&lt;/p&gt;
&lt;p&gt;The timing of this second audit is particularly important because Stalwart has evolved considerably since that initial security review. New features have been added, performance optimizations have been implemented, and the overall architecture has matured significantly. A fresh security perspective is essential to ensure that these improvements haven’t introduced new vulnerabilities and that our security posture has kept pace with the software’s development.&lt;/p&gt;
&lt;p&gt;Radically Open Security brings extensive experience in open source security auditing, and their thorough approach will provide valuable insights into Stalwart’s current security status. This audit is being financed through a &lt;a href=&quot;https://stalw.art/blog/nlnet-grant-collaboration&quot;&gt;grant from NLNet&lt;/a&gt;, demonstrating the broader open source community’s investment in Stalwart’s security and reliability.&lt;/p&gt;
&lt;p&gt;We expect to release the complete results of this security audit soon, continuing our commitment to transparency and community trust. The combination of the GitHub security training, the ongoing Azure-powered testing, and this comprehensive security audit represents a multi-faceted approach to security that reflects the importance we place on protecting our users’ communications and data.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We want to take a moment to express our sincere thanks to &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; for selecting Stalwart to participate in the Open Source Secure Fund and for providing us with the training and resources that will help strengthen the security of our project. We also want to extend our gratitude to &lt;a href=&quot;https://zerodha.com/&quot;&gt;Zerodha&lt;/a&gt; for referring Stalwart to be part of GitHub’s OSSF Session 2. Their support has been invaluable, and we look forward to continuing this journey of growth and improvement with their help.&lt;/p&gt;
&lt;p&gt;Stalwart is committed to providing secure and reliable mail and collaboration services, and with the backing of the GitHub OSSF and the ongoing work of our team, we are confident that we can continue to meet and exceed the expectations of our users.&lt;/p&gt;
&lt;p&gt;Thank you for your continued support!&lt;/p&gt;</content:encoded><category>ossf</category><category>open-source</category><category>security</category><category>stalwart</category></item><item><title>Introducing Virtual Queues and Strategy-Driven Delivery in Stalwart MTA</title><link>https://stalw.art/blog/virtual-queues/</link><guid isPermaLink="true">https://stalw.art/blog/virtual-queues/</guid><description>At Stalwart Labs, we&apos;re constantly working to evolve and improve our software based on real-world feedback. Today, we&apos;re excited to announce a major enhancement to the queueing system in Stalwart MTA, designed to meet the needs of some of our busiest users—those delivering millions of messages per day.

This update is the result of valuable input from operators managing large-scale mail infrastructure. Many reported a recurring issue: when message volumes spiked, low-priority traffic, such as DMARC aggregate reports and Delivery Status Notifications (DSNs), would often compete with or delay the delivery of legitimate user mail. Since all messages were processed through a single delivery queue, these traffic types were treated equally, regardless of urgency or purpose.

</description><pubDate>Tue, 15 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;smarter-queueing-with-virtual-queues&quot;&gt;Smarter Queueing with Virtual Queues&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;To solve this, we’ve introduced &lt;a href=&quot;https://stalw.art/docs/mta/outbound/queue&quot;&gt;virtual queues&lt;/a&gt;—a powerful feature that allows administrators to define &lt;strong&gt;separate, independently managed delivery queues&lt;/strong&gt; for different categories of mail.&lt;/p&gt;
&lt;p&gt;Each virtual queue operates with its own set of &lt;strong&gt;delivery threads&lt;/strong&gt;, giving you control over how system resources are allocated. Messages can now be segmented by &lt;strong&gt;message type&lt;/strong&gt;, &lt;strong&gt;source&lt;/strong&gt;, &lt;strong&gt;priority&lt;/strong&gt;, &lt;strong&gt;recipient domain&lt;/strong&gt;, or any other attribute, and assigned to different queues with tailored delivery policies.&lt;/p&gt;
&lt;p&gt;For example, you can isolate system-generated messages such as DSNs or reports into low-concurrency queues, while prioritizing user-facing transactional mail in high-capacity queues—ensuring the latter is never blocked or delayed by the former.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;strategy-driven-delivery&quot;&gt;Strategy-Driven Delivery&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;At the core of this system is a &lt;a href=&quot;https://stalw.art/docs/mta/outbound/strategy&quot;&gt;strategy-based architecture&lt;/a&gt; that governs how messages are handled from the moment they’re queued to the point of delivery. These strategies are dynamically evaluated per recipient and control four key aspects of delivery:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scheduling Strategy&lt;/strong&gt;: Determines which virtual queue to use, how frequently to retry failed deliveries, when to notify the sender of delays, and when to give up and bounce a message.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Routing Strategy&lt;/strong&gt;: Controls whether a message should be delivered locally, via MX resolution, or relayed through a smart host.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connection Strategy&lt;/strong&gt;: Defines connection parameters such as the source IP address, EHLO hostname, and SMTP timeouts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TLS Strategy&lt;/strong&gt;: Enforces transport-layer security policies, including STARTTLS behavior and support for MTA-STS and DANE.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of these strategies are defined through &lt;strong&gt;expressions&lt;/strong&gt; that can evaluate runtime variables like the sender, recipient, message size, source classification, and more. This enables extremely granular control over delivery logic, with different strategies dynamically assigned to different recipients within the same message.&lt;/p&gt;
&lt;p&gt;With this enhancement, Stalwart now gives you the tools to build highly customized delivery workflows. You can throttle or isolate problematic traffic, prioritize VIP clients, set domain-specific retry policies, and fine-tune your system for performance, reliability, and security—all with a simple and transparent configuration model.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;mta-hooks-moving-toward-standardization&quot;&gt;MTA Hooks: Moving Toward Standardization&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For those not already familiar, &lt;a href=&quot;https://stalw.art/docs/mta/filter/mtahooks&quot;&gt;MTA Hooks&lt;/a&gt; is a modern alternative to the legacy &lt;a href=&quot;https://stalw.art/docs/mta/filter/milter&quot;&gt;Milter&lt;/a&gt; protocol originally developed for Sendmail. Milter has long served as a way to inspect, modify, or reject messages during the SMTP transaction, but its binary format and low-level implementation have made it difficult to work with and integrate into modern systems.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MTA Hooks&lt;/strong&gt;, introduced by &lt;strong&gt;Stalwart Labs&lt;/strong&gt; some years ago, was designed to solve these problems with a cleaner, more accessible approach. Instead of relying on obscure binary protocols, MTA Hooks uses &lt;strong&gt;HTTP&lt;/strong&gt; and a &lt;strong&gt;human-readable JSON schema&lt;/strong&gt;, making it easy for administrators and developers to write filters in any language, debug behavior transparently, and integrate with modern infrastructure.&lt;/p&gt;
&lt;p&gt;Using MTA Hooks, it’s possible to &lt;strong&gt;intercept, inspect, and alter&lt;/strong&gt; any part of the SMTP transaction—whether that’s rejecting mail during &lt;code dir=&quot;auto&quot;&gt;RCPT TO&lt;/code&gt;, modifying headers after &lt;code dir=&quot;auto&quot;&gt;DATA&lt;/code&gt;, or applying policy logic during message queuing. Many users are already using MTA Hooks in production for a wide range of use cases, from spam filtering and data leak prevention to routing logic and outbound content policy enforcement.&lt;/p&gt;
&lt;p&gt;Now, we’re excited to share that &lt;strong&gt;Stalwart Labs will begin the process of standardizing MTA Hooks&lt;/strong&gt; with the broader email community.&lt;/p&gt;
&lt;p&gt;We’ll be presenting the protocol at &lt;a href=&quot;https://www.ietf.org/meeting/123/&quot;&gt;IETF 123&lt;/a&gt; in &lt;strong&gt;Madrid&lt;/strong&gt;, where we plan to engage with the &lt;a href=&quot;https://datatracker.ietf.org/wg/mailmaint/about/&quot;&gt;mailmaint working group&lt;/a&gt; to start formal discussions around standardization. Our goal is to make MTA Hooks an open, community-driven specification—so it can serve as a modern, interoperable alternative to Milter for the entire mail ecosystem.&lt;/p&gt;
&lt;p&gt;If you’re attending IETF 123 and would like to connect with us about this effort, we welcome your input. Please reach out through any of our official channels or come speak with us during the event. Whether you’re an MTA developer, operator, or interested party, we’d love to hear your perspective.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;looking-ahead&quot;&gt;Looking Ahead&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Stalwart is evolving rapidly, and this release represents a major step forward in performance, flexibility, and modern protocol design. As always, we’re grateful to our community for your feedback and support. We look forward to seeing what you build with these new capabilities.&lt;/p&gt;
&lt;p&gt;Stay tuned for more updates—and see you in Madrid!&lt;/p&gt;</content:encoded><category>mta</category><category>smtp</category><category>queue</category><category>mta-hooks</category><category>ietf123</category><category>stalwart</category></item><item><title>The Future of Stalwart: Webmail, Roadmap, and Beyond</title><link>https://stalw.art/blog/roadmap/</link><guid isPermaLink="true">https://stalw.art/blog/roadmap/</guid><description>Since we officially started developing Stalwart on September 4th, 2021, we&apos;ve come a long way in establishing a powerful and versatile open-source mail and collaboration server. The very first commit, made on October 3rd, 2021, was to the mail-parser Rust crate, a fundamental component upon which Stalwart was built. It set the tone for our relentless pursuit of secure, reliable, and performant software.

</description><pubDate>Fri, 20 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Almost exactly one year later, on &lt;a href=&quot;https://github.com/stalwartlabs/jmap-server/releases/tag/v0.1.0&quot;&gt;September 17th, 2022&lt;/a&gt;, we proudly released version 0.1, initially known as the &lt;a href=&quot;https://github.com/stalwartlabs/jmap-server&quot;&gt;Stalwart JMAP server&lt;/a&gt;. From that initial launch, we’ve continuously expanded Stalwart’s capabilities, consistently introducing valuable new features. Just last month, we &lt;a href=&quot;https://stalw.art/blog/collaboration&quot;&gt;celebrated a major milestone&lt;/a&gt; by transforming Stalwart from solely a mail server into a comprehensive mail and collaboration server. This significant update brought CalDAV, CardDAV, and WebDAV support, positioning Stalwart as the open-source mail and collaboration server with the most extensive feature set available today—even compared to many commercial solutions.&lt;/p&gt;
&lt;p&gt;Despite these significant advancements and the existing web-based administration interface that includes essential self-service capabilities, we’ve noticed one prominent request from our community: a built-in webmail client. Many of you have been eagerly asking whether we plan to offer this feature. Today, we’re excited to share with you that yes, a dedicated Stalwart Webmail is indeed in our plans—but it’s not currently our immediate priority.&lt;/p&gt;
&lt;p&gt;Our roadmap for the remainder of 2025 is already well-defined. We will first release JMAP support for Calendars, Contacts, and File Storage, which will further strengthen Stalwart’s position as a powerful collaborative tool. Immediately following these updates, our main focus will shift to preparing for our much-anticipated version 1.0 release.&lt;/p&gt;
&lt;p&gt;Although Stalwart is already being confidently used in production environments globally, version 1.0 marks an essential milestone. It signifies that we’ve finalized our database schema—no more daunting database migrations!—ensuring stability for long-term users. Unless an entirely new protocol surpassing email emerges (who knows?), our database schema will remain stable and optimized. Moreover, this version will involve a comprehensive performance optimization initiative. Every line of our code was initially written with speed and efficiency in mind, yet there are still critical areas we believe can be further improved. By systematically benchmarking critical code paths, we’re confident we’ll find opportunities to make Stalwart even faster and more efficient.&lt;/p&gt;
&lt;p&gt;Post version 1.0, our commitment remains firm: Stalwart will remain lean and specialized. While our GitHub issue tracker proudly showcases &lt;a href=&quot;https://github.com/stalwartlabs/stalwart/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement&quot;&gt;numerous exciting enhancement requests&lt;/a&gt;, rest assured we won’t lose sight of our core mission. Our primary goal is to continue being the absolute best in JMAP, IMAP, POP3, SMTP, and WebDAV protocols—nothing more, nothing less. We strive to avoid becoming a proverbial jack-of-all-trades, instead remaining focused and exceptional at our core competencies.&lt;/p&gt;
&lt;p&gt;As for the much-requested Webmail, once we’ve achieved the critical milestone of version 1.0, we plan to start its development—most likely sometime in 2026. We’ll be building a Single Page Application (SPA) using Rust and the &lt;a href=&quot;https://github.com/DioxusLabs/dioxus&quot;&gt;Dioxus&lt;/a&gt; framework. Dioxus is quite distinct from more popular frameworks like React, meaning many necessary UI components still don’t exist. Consequently, we’ll likely spend considerable time contributing directly to the Dioxus ecosystem, expanding available components and features.&lt;/p&gt;
&lt;p&gt;Now, you might ask, “Why not simply use React or another established framework?” Well, humorously and earnestly, at Stalwart, we operate by an unofficial motto: “&lt;strong&gt;Aut Rust aut nihil&lt;/strong&gt;,” meaning “Either Rust or nothing.” We’re committed to Rust because we truly believe it’s the best language for creating secure, reliable, and performant software—even if this approach means occasionally delaying releases by a few months.&lt;/p&gt;
&lt;p&gt;In the meantime, while our webmail is in development, we highly recommend using alternative webmail solutions that integrate smoothly with Stalwart. Some choices include &lt;a href=&quot;https://github.com/roundcube/roundcubemail&quot;&gt;Roundcube&lt;/a&gt;, &lt;a href=&quot;https://github.com/the-djmaze/snappymail&quot;&gt;SnappyMail&lt;/a&gt;, &lt;a href=&quot;https://github.com/Alinto/sogo&quot;&gt;SoGo&lt;/a&gt;, or &lt;a href=&quot;https://github.com/linagora/tmail-flutter&quot;&gt;TMail Web&lt;/a&gt;—which notably supports the JMAP protocol.&lt;/p&gt;
&lt;p&gt;We’re grateful for your continued support and patience as we steadily build toward a fully integrated Stalwart experience. Stay tuned, and thank you for being part of this exciting journey!&lt;/p&gt;</content:encoded><category>webmail</category><category>roadmap</category><category>stalwart</category><category>jmap</category><category>imap</category><category>pop3</category><category>smtp</category><category>webdav</category><category>dioxus</category></item><item><title>Introducing Calendars, Contacts and Files in Stalwart</title><link>https://stalw.art/blog/collaboration/</link><guid isPermaLink="true">https://stalw.art/blog/collaboration/</guid><description>We’re excited to announce the release of Stalwart v0.12, a significant milestone that evolves Stalwart from a powerful mail server into a complete, integrated communication and collaboration platform. This release delivers one of the most anticipated features from our community: native support for calendars, contacts, and file storage—all built directly into the server, with no need for third-party integrations.

</description><pubDate>Mon, 26 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;calendars-contacts--files--all-in-one-place&quot;&gt;Calendars, Contacts &amp;#x26; Files – All in One Place&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;With v0.12, you no longer need to integrate third-party groupware solutions or run parallel systems to support collaboration. Stalwart now includes first-class support for &lt;a href=&quot;https://stalw.art/docs/collaboration/calendar&quot;&gt;CalDAV calendars&lt;/a&gt;, &lt;a href=&quot;https://stalw.art/docs/collaboration/contact&quot;&gt;CardDAV contacts&lt;/a&gt;, and &lt;a href=&quot;https://stalw.art/docs/collaboration/file-storage&quot;&gt;WebDAV-based file storage&lt;/a&gt;. This means users can manage their events, address books, and documents through any standards-compliant client, seamlessly connected to the same backend that handles their email.&lt;/p&gt;
&lt;p&gt;Shared resources such as &lt;strong&gt;group calendars&lt;/strong&gt;, &lt;strong&gt;shared address books&lt;/strong&gt;, and &lt;strong&gt;team-accessible file folders&lt;/strong&gt; are also fully supported, providing a robust foundation for collaboration without the need for external software or services. And, to support flexible collaboration, Stalwart includes full support for the &lt;strong&gt;WebDAV Access Control List (ACL) extension&lt;/strong&gt;, enabling detailed, per-user and per-group permission management.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;improved-spam-filtering&quot;&gt;Improved Spam Filtering&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Another thoughtful addition in this release is the integration of the spam filter with users’ personal address books. Messages from known or trusted contacts are now far less likely to be incorrectly flagged as spam. And if a legitimate message does get misclassified, the system automatically trains the &lt;strong&gt;Bayesian classifier&lt;/strong&gt; to treat future similar messages as legitimate, improving accuracy over time without additional user intervention.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;performance-enhancements&quot;&gt;Performance Enhancements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Under the hood, Stalwart v0.12 introduces several key performance optimizations designed especially for &lt;a href=&quot;https://stalw.art/docs/cluster/&quot;&gt;large, multi-node environments&lt;/a&gt;. One of the most impactful changes is the introduction of &lt;a href=&quot;https://stalw.art/docs/server/cache&quot;&gt;incremental caching&lt;/a&gt;: Stalwart now keeps account metadata in memory and only fetches updates when something changes in the database. This significantly reduces load and speeds up response times.&lt;/p&gt;
&lt;p&gt;Another major enhancement is the use of &lt;strong&gt;zero-copy deserialization&lt;/strong&gt;. This means Stalwart can read data directly from memory buffers without copying it into new structures, lowering CPU usage and improving throughput. Combined with optimizations that reduce the number of required &lt;strong&gt;database queries&lt;/strong&gt; for common operations, these changes result in a leaner, faster backend that scales much more efficiently.&lt;/p&gt;
&lt;p&gt;While these gains may not be noticeable in smaller setups, &lt;strong&gt;larger clusters and high-volume deployments will see noticeable performance improvements&lt;/strong&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;smarter-and-faster-clustering&quot;&gt;Smarter and Faster Clustering&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We’ve also made big strides in &lt;a href=&quot;https://stalw.art/docs/cluster/coordination/&quot;&gt;cluster coordination&lt;/a&gt;. Previously, Stalwart relied on a UDP-based gossip protocol that performed well but didn’t scale ideally under heavy workloads. With v0.12, cluster behavior is now adaptable based on deployment size.&lt;/p&gt;
&lt;p&gt;In &lt;strong&gt;small deployments&lt;/strong&gt;, Stalwart uses &lt;a href=&quot;https://stalw.art/docs/cluster/coordination/peer-to-peer&quot;&gt;Eclipse Zenoh&lt;/a&gt;, a lightweight and efficient peer-to-peer pub/sub protocol. For &lt;strong&gt;larger infrastructures&lt;/strong&gt;, you can now choose from robust, scalable backends like &lt;a href=&quot;https://stalw.art/docs/cluster/coordination/kafka&quot;&gt;Apache Kafka&lt;/a&gt;, &lt;a href=&quot;https://stalw.art/docs/cluster/coordination/kafka&quot;&gt;Redpanda&lt;/a&gt;, &lt;a href=&quot;https://stalw.art/docs/cluster/coordination/nats&quot;&gt;NATS&lt;/a&gt;, or &lt;a href=&quot;https://stalw.art/docs/cluster/coordination/redis&quot;&gt;Redis&lt;/a&gt; for handling inter-node coordination, state synchronization, and workload distribution.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;looking-ahead-whats-next&quot;&gt;Looking Ahead: What’s Next?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;With Stalwart v0.12, we’re delivering more than just features—we’re delivering &lt;strong&gt;freedom from fragmented infrastructure&lt;/strong&gt;. No more patching together third-party services to get the basics of collaboration working. Now, everything—&lt;strong&gt;email, calendars, contacts, files, and sharing&lt;/strong&gt;—lives in a single, efficient, and secure system.&lt;/p&gt;
&lt;p&gt;While v0.12 is a major leap forward, we’re already preparing additional enhancements for the next point release. In &lt;strong&gt;v0.12.1&lt;/strong&gt;, you can expect support for &lt;strong&gt;CalDAV Scheduling (RFC 6638)&lt;/strong&gt;, enabling automatic meeting invitations and attendee responses. We’re also adding support for &lt;strong&gt;event notification alerts via email&lt;/strong&gt;, so users are always aware of upcoming events, even if they’re not logged into their calendars.&lt;/p&gt;
&lt;p&gt;Additionally, in the coming months, we will be releasing support for the &lt;strong&gt;JMAP for Calendars&lt;/strong&gt;, &lt;strong&gt;JMAP for Contacts&lt;/strong&gt;, and &lt;strong&gt;JMAP for File Storage&lt;/strong&gt; extensions. JMAP offers a modern, efficient, and JSON-based alternative to legacy protocols, making it faster and easier to develop responsive, real-time collaboration tools. These additions will further streamline the user experience and reduce bandwidth and processing overhead across client-server interactions.&lt;/p&gt;
&lt;p&gt;Thank you to everyone who contributed feedback, suggestions, and encouragement. We can’t wait to hear what you build with this release—and we’re just getting started.&lt;/p&gt;</content:encoded><category>calendars</category><category>contact</category><category>files</category><category>collaboration</category><category>caldav</category><category>carddav</category><category>webdav</category></item><item><title>Stalwart Receives NLNet Grant to Build Collaboration Server</title><link>https://stalw.art/blog/nlnet-grant-collaboration/</link><guid isPermaLink="true">https://stalw.art/blog/nlnet-grant-collaboration/</guid><description>We’re happy to announce that Stalwart Labs has been awarded a new grant from the NGI0 Core Fund, established by NLnet with financial support from the European Commission’s Next Generation Internet programme. This funding will support the development of essential collaboration features, marking a major milestone in Stalwart’s evolution from a modern email server into a complete, self-hosted collaboration platform.

This is the second grant Stalwart has received from NLnet, following the initial support we received in March 2023 from the NGI0 Entrust Fund. We are deeply grateful to the NLnet Foundation for their continued trust in our mission to modernize and decentralize communication infrastructure.

</description><pubDate>Fri, 21 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;expanding-the-vision-from-email-to-collaboration&quot;&gt;Expanding the Vision: From Email to Collaboration&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Stalwart Mail Server was created to address the challenges of self-hosting email by offering a secure, easy-to-maintain, and high-performance solution. With native support for JMAP, IMAP4, POP3, and SMTP, it already serves as a powerful alternative to traditional email solutions, giving individuals and organizations full control over their email systems.&lt;/p&gt;
&lt;p&gt;With the help of this new grant, we are now expanding the Stalwart platform beyond email. Development is officially underway on the &lt;strong&gt;Stalwart Collaboration Server&lt;/strong&gt;, a new component that will integrate seamlessly with Stalwart Mail Server. This addition will provide support for calendaring through CalDAV and JMAP for Calendars, contact management using CardDAV and JMAP for Contacts, and file storage and sharing using WebDAV and JMAP for File Management. Together, these features will form the foundation of a fully integrated, open-source collaboration suite.&lt;/p&gt;
&lt;p&gt;Our goal is to offer a privacy-focused, vendor-neutral alternative to platforms like Microsoft Exchange. By consolidating email, calendar, contacts, and file sharing into one unified system, Stalwart will give users the ability to self-host their entire collaboration stack without sacrificing modern functionality, scalability, or security.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-the-grant-will-fund&quot;&gt;What the Grant Will Fund&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new funding will support a series of developments that will be released gradually throughout the year under the AGPL-3.0 license:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A full-featured CalDAV and CardDAV server will be implemented, allowing users to manage their calendars and contacts directly within Stalwart. This means there will be no need to rely on external software to provide these functions. Users will be able to keep all of their collaboration data in one place, within a single, tightly integrated platform.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In addition, we will extend Stalwart’s existing JMAP implementation to support JMAP for Calendars and JMAP for Contacts. This will involve developing parsers for JSCalendar and JSContact, as well as creating bidirectional converters between JSCalendar and iCalendar, and JSContact and vCard.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;File storage and management will also become a first-class feature of the platform. A WebDAV-based file storage system will be built on top of Stalwart’s internal blob store. Alongside this, we will implement support for JMAP for File Management, allowing users to upload, organize, and share files using either standard WebDAV clients or JMAP-based applications. The JMAP support will align with the ongoing efforts to standardize file management within the JMAP ecosystem.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finally, the grant will fund the implementation of the three most requested features by the Stalwart community. These include support for the IMAP XAPPLEPUSHSERVICE extension, which enables push notifications on iOS devices; automatic DKIM record updates via RFC2136, making it easier to manage DNS records dynamically; and support for exporting Maildir mailboxes with nested folders, improving compatibility and backup workflows.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We would like to express our sincere thanks to the &lt;a href=&quot;https://nlnet.nl&quot;&gt;NLnet Foundation&lt;/a&gt; and the &lt;strong&gt;European Commission&lt;/strong&gt; for making this work possible. The project is funded through the &lt;a href=&quot;https://nlnet.nl/core/&quot;&gt;NGI0 Core Fund&lt;/a&gt;, a fund established by NLnet with financial support from the &lt;strong&gt;European Commission’s Next Generation Internet programme&lt;/strong&gt;, under the aegis of &lt;strong&gt;DG Communications Networks, Content and Technology&lt;/strong&gt;, as part of &lt;strong&gt;grant agreement No. 101092990&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This support plays a vital role in advancing open-source infrastructure and helps ensure that secure, decentralized alternatives remain viable and accessible to everyone.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;looking-ahead&quot;&gt;Looking Ahead&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;As we roll out these new features throughout the year, we remain committed to the core values that drive Stalwart’s development: privacy, performance, transparency, and user empowerment. The Stalwart Collaboration Server will transform the platform into a comprehensive, modern collaboration suite — one that is open, scalable, and fully self-hosted.&lt;/p&gt;
&lt;p&gt;We look forward to sharing more progress soon. In the meantime, we invite developers, testers, and curious users to follow our work, contribute ideas, and help shape the future of self-hosted collaboration.&lt;/p&gt;
&lt;p&gt;Stay tuned, and thank you for your continued support.&lt;/p&gt;</content:encoded><category>nlnet</category><category>ngi0</category><category>grant</category><category>collaboration</category><category>caldav</category><category>carddav</category><category>webdav</category><category>jmap</category></item><item><title>OpenID Connect Integration is now Open Source</title><link>https://stalw.art/blog/oidc-open-source/</link><guid isPermaLink="true">https://stalw.art/blog/oidc-open-source/</guid><description>We are happy to announce that third-party OpenID Connect (OIDC) authentication support has now been open-sourced under the AGPL-3.0 license in Stalwart Mail Server version 0.11.5. This means that users can now configure Stalwart Mail Server to authenticate against external OIDC providers, such as Keycloak, without requiring an Enterprise subscription.

Stalwart Mail Server has supported OIDC authentication for several months, allowing it to function as either an OIDC provider or an OIDC client authenticating against an external provider. Until now, only the ability to act as an OIDC provider was included in the Open Source edition, while authentication via external OIDC providers was reserved for Enterprise users. By making this functionality freely available, we are reinforcing our commitment to openness and ensuring that more users can take advantage of modern, federated authentication without barriers.

With this change, organizations that rely on external OIDC identity providers can seamlessly integrate Stalwart Mail Server into their existing authentication workflows at no cost. Whether you are using Keycloak, Auth0, or another OIDC-compliant solution, Stalwart Mail Server now offers complete flexibility in how you manage authentication.

</description><pubDate>Fri, 31 Jan 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;why-is-stalwart-not-100-free&quot;&gt;Why is Stalwart Not 100% Free?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;At Stalwart Labs, our goal is to provide a robust and feature-rich mail server solution. However, sustaining long-term development for a project of this scale requires significant financial resources. At present, open-source sponsorships alone do not generate sufficient funding to cover these costs entirely.&lt;/p&gt;
&lt;p&gt;To ensure that Stalwart Mail Server continues to evolve and improve, we offer a paid Enterprise version. Revenue from Enterprise subscriptions allows our team to dedicate full-time efforts to development, ensuring the continuous enhancement of both the open-source and paid versions. This funding model allows us to introduce new features while maintaining the high standards that make Stalwart Mail Server a leading solution in the industry.&lt;/p&gt;
&lt;p&gt;Furthermore, the existence of an Enterprise edition directly benefits the open-source community. By sustaining active development, we can periodically release new features into the open-source version, as we have done with third-party OIDC support. It is worth noting that even the community edition of Stalwart Mail Server already provides more features than any other open-source or commercial mail server available today. We are dedicated to maintaining and expanding this competitive edge.&lt;/p&gt;
&lt;p&gt;If you would like to support open-source development and help accelerate the release of additional features as open-source, we invite you to become a sponsor. Your sponsorship plays a vital role in the project’s sustainability and future growth. Thank you for your support and understanding.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;join-us-at-fosdem-2025&quot;&gt;Join Us at FOSDEM 2025&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;To learn more about Stalwart Mail Server and its latest developments, we invite you to watch our talk at FOSDEM 2025. The session will take place tomorrow, Saturday, February 1st, at 12:00 PM Central European Time in Brussels. If you cannot attend in person, you can follow the presentation online at &lt;a href=&quot;https://fosdem.org/2025/schedule/event/fosdem-2025-4571-stalwart-mail-server/&quot;&gt;fosdem.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We look forward to sharing more about the project and engaging with the community at this exciting event!&lt;/p&gt;</content:encoded><category>oidc</category><category>openid</category><category>stalwart</category><category>mail</category><category>server</category></item><item><title>Goodbye Spam: Introducing Faster, Smarter Spam Filtering</title><link>https://stalw.art/blog/next-gen-spam-filter/</link><guid isPermaLink="true">https://stalw.art/blog/next-gen-spam-filter/</guid><description>As we step into 2025, we&apos;re excited to share some significant enhancements to Stalwart Mail Server version 0.11.0, starting with a complete overhaul of its built-in spam filter. These changes bring dramatic improvements in speed, ease of use, and flexibility while addressing feedback from our community. Here’s a closer look at what’s new.

</description><pubDate>Mon, 06 Jan 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;a-faster-smarter-spam-filter&quot;&gt;A Faster, Smarter Spam Filter&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In earlier versions of Stalwart Mail Server, the spam filter was implemented as a Sieve script. This design choice was inspired by platforms like Rspamd, which use scripting languages like Lua to allow customizations. However, over time, we identified two key challenges with this approach. First, because it was an interpreted script, the spam filter’s performance was slightly slower than we’d like. Second, many users found it complicated to update the script when adding custom rules or configuring custom DNSBL (Domain Name System Blocklist) servers.&lt;/p&gt;
&lt;p&gt;To address these issues, we rewrote the spam filter entirely in Rust. The result is a system that is five times faster than before, delivering superior performance while keeping resource usage minimal. Moreover, defining new rules or adding DNSBL servers is now as simple as editing the configuration file—no scripting expertise required. This shift eliminates complexity while maintaining the high level of customization our users expect. For those who still need advanced control, Stalwart continues to support custom Sieve scripts and expressions, ensuring maximum flexibility.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;enhanced-training&quot;&gt;Enhanced Training&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;One of the most requested features we’ve added is the ability for end users to train their own spam filter Bayesian model. Now, users can customize their spam filtering by simply moving messages to and from the “Junk Mail” folder or by adding and removing the &lt;code dir=&quot;auto&quot;&gt;$Junk&lt;/code&gt; flag. This personalized approach allows each account to maintain its own tailored spam filter, providing greater accuracy and user satisfaction.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;improved-performance&quot;&gt;Improved Performance&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This update isn’t just about the spam filter. We’ve also made broader performance enhancements to Stalwart Mail Server. Previously, we relied on LRU (Least Recently Used) caches. With this release, we’ve switched to scan-resistant S3-FIFO caches, offering better performance under heavy workloads. Additionally, we’ve optimized Stalwart’s handling of large distributed SMTP queues, ensuring smoother operation in clustered environments. These changes make Stalwart even more capable of handling demanding enterprise setups.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;meet-us-at-fosdem25&quot;&gt;Meet Us at FOSDEM’25&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We’re thrilled to announce that Stalwart Mail Server will be featured at &lt;a href=&quot;https://fosdem.org/2025/schedule/event/fosdem-2025-4571-stalwart-mail-server/&quot;&gt;FOSDEM’25&lt;/a&gt;! Join us on February 1st at 12:00 PM in Brussels, where we’ll showcase these new features and share insights into what’s coming next for Stalwart. This is a fantastic opportunity to connect with our team, ask questions, and explore how Stalwart can power your email infrastructure.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;upgrade-today&quot;&gt;Upgrade Today&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;These improvements are available now, and we’re confident they’ll make a big difference for administrators and users alike. Whether you’re drawn to the speed of the new spam filter, the enhanced training capabilities, or the overall performance boosts, this update is designed to help you get the most out of Stalwart Mail Server.&lt;/p&gt;
&lt;p&gt;As always, thank you for choosing Stalwart. We’re committed to delivering a reliable, feature-rich email server that evolves with your needs. Here’s to a productive and spam-free 2025!&lt;/p&gt;</content:encoded><category>spam</category><category>filter</category><category>email</category><category>security</category><category>stalwart</category><category>mail</category><category>server</category></item><item><title>Diagnose and Resolve Email Issues Faster</title><link>https://stalw.art/blog/troubleshooting/</link><guid isPermaLink="true">https://stalw.art/blog/troubleshooting/</guid><description>Today we are announcing the release of Stalwart Mail Server version 0.10.7, an update that brings two of the most requested features from our users: robust troubleshooting tools and support for external recipients on mailing lists. This update also introduces the ability to store emails and blobs on Azure Blob Storage, alongside several minor fixes and improvements. As always, this release reflects our commitment to implementing the features most requested by our community.

</description><pubDate>Wed, 04 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;advanced-troubleshooting&quot;&gt;Advanced Troubleshooting&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;One of the key highlights of version 0.10.7 is the addition of comprehensive troubleshooting tools designed to help administrators diagnose and resolve email delivery and DMARC-related issues more efficiently.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;email delivery troubleshooting tool&lt;/strong&gt; provides a step-by-step simulation of the email delivery process. Accessible through the Webadmin interface under &lt;code dir=&quot;auto&quot;&gt;Manage -&gt; Troubleshoot -&gt; Email Delivery&lt;/code&gt;, this tool allows administrators to test delivery paths for any email address or domain. It performs critical tasks like resolving MX records, retrieving IP addresses, validating MTA-STS and DANE policies, upgrading the connection to TLS, and verifying recipient availability. Importantly, this tool does not send actual emails but offers a detailed analysis of the delivery pipeline, displaying each step in real-time and flagging any issues that arise. This ensures that administrators can identify and address problems before they impact actual email traffic.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;DMARC troubleshooting tool&lt;/strong&gt; is another powerful addition. Located under &lt;code dir=&quot;auto&quot;&gt;Manage -&gt; Troubleshoot -&gt; DMARC&lt;/code&gt;, it enables administrators to verify the DMARC setup for both local and remote domains. By simulating the server’s authentication process, this tool checks SPF, DKIM, ARC, and DMARC policies while also verifying that the reverse PTR matches the SPF EHLO hostname. Administrators can input details such as the sender address, server IP, EHLO hostname, and optionally, the message body for detailed DKIM and ARC testing. This comprehensive tool mirrors the checks Stalwart performs when receiving emails, making it easier to identify and resolve policy compliance issues.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;external-recipients&quot;&gt;External Recipients&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Another significant enhancement in version 0.10.7 is the ability to add &lt;strong&gt;external recipients to mailing lists&lt;/strong&gt;. In previous versions, mailing lists were restricted to local recipients, limiting their flexibility. With this update, administrators can now include recipients from external domains in mailing lists, enabling broader collaboration and more versatile email distribution. This change reflects our commitment to making Stalwart Mail Server more adaptable to the diverse needs of our users.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;azure-blob-storage&quot;&gt;Azure Blob Storage&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In addition to the major feature updates, Stalwart Mail Server 0.10.7 introduces support for storing emails and blobs on &lt;strong&gt;Azure Blob Storage&lt;/strong&gt;. This new capability provides users with greater flexibility in managing their data storage, especially for organizations already leveraging Azure’s robust cloud infrastructure. The release also includes a range of minor fixes to improve overall stability and performance.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;looking-ahead&quot;&gt;Looking Ahead&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;As we celebrate the release of version 0.10.7, we are already working on the next major feature: &lt;strong&gt;faster and improved spam filtering&lt;/strong&gt;. This enhancement, another highly requested feature, will bring more effective tools to combat unwanted emails while ensuring legitimate messages are processed efficiently. We are eager to share more details in the coming weeks.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;shape-the-future&quot;&gt;Shape the Future&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Stalwart Mail Server continues to evolve based on feedback from our community. New features and improvements are implemented in the order of the votes they receive, ensuring that development aligns with the needs of our users. We invite you to visit our GitHub page to review the current list of enhancement requests and vote for the features you would like to see implemented next. You can find the list at &lt;a href=&quot;https://github.com/stalwartlabs/mail-server/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement&quot;&gt;GitHub Enhancement Requests&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Thank you for your ongoing support and feedback, which are instrumental in shaping Stalwart Mail Server into the reliable, user-focused solution it is today. We look forward to hearing your thoughts on version 0.10.7 and what you’d like to see in future releases!&lt;/p&gt;</content:encoded><category>troubleshoot</category><category>delivery</category><category>dmarc</category><category>stalwart</category><category>mail</category><category>server</category></item><item><title>Revolutionize Your Email Workflow with AI</title><link>https://stalw.art/blog/llm-ai-models/</link><guid isPermaLink="true">https://stalw.art/blog/llm-ai-models/</guid><description>We are happy to announce the release of Stalwart Mail Server v0.10.3, which introduces support for AI models —a powerful new feature now available to Enterprise Edition users as well as our GitHub and OpenCollective sponsors. With this feature, Stalwart Mail Server can be integrated with both self-hosted and cloud-based Large Language Models (LLMs), bringing advanced email processing capabilities like never before.

This integration allows you to use AI models for a variety of tasks, including enhanced spam filtering, threat detection, and intelligent email classification. Whether you choose to host your own models with LocalAI or leverage cloud-based services like OpenAI or Anthropic, this release provides the flexibility to incorporate cutting-edge AI into your email infrastructure.

</description><pubDate>Mon, 07 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;unlocking-the-power-of-ai&quot;&gt;Unlocking the Power of AI&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;With the introduction of AI model integration, Stalwart Mail Server can now analyze email content more deeply than traditional filters ever could. For instance, in the realm of spam filtering and threat detection, AI models are highly effective at identifying patterns and detecting malicious or unsolicited content. The system works by analyzing both the subject and body of incoming emails through the lens of an LLM, providing more accurate detection and filtering.&lt;/p&gt;
&lt;p&gt;In addition to bolstering security, AI integration enhances email classification. By configuring customized prompts, administrators can instruct AI models to categorize emails based on their content, leading to more precise filtering and organization. This is particularly useful for enterprises managing a high volume of messages that span various topics and departments, as AI-driven filters can quickly and intelligently sort messages into categories like marketing, personal correspondence, or work-related discussions.&lt;/p&gt;
&lt;p&gt;The flexibility of using either self-hosted or cloud-based AI models means that Stalwart can be tailored to your infrastructure and performance needs. Self-hosting AI models ensures full control over data and privacy, while cloud-based models offer ease of setup and access to highly optimized, continuously updated language models.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;llms-in-sieve-scripts&quot;&gt;LLMs in Sieve Scripts&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;One of the most exciting features of this release is the ability for users and administrators to access AI models directly from &lt;a href=&quot;https://stalw.art/docs/sieve/llm&quot;&gt;Sieve scripts&lt;/a&gt;. Stalwart extends the Sieve scripting language by introducing the &lt;code dir=&quot;auto&quot;&gt;llm_prompt&lt;/code&gt; function, which allows users to send prompts and email content to the AI model for advanced processing.&lt;/p&gt;
&lt;p&gt;For example, the following Sieve script demonstrates how an AI model can be used to classify emails into specific folders based on the content:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;require [&quot;fileinto&quot;, &quot;vnd.stalwart.expressions&quot;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Base prompt for email classification&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let &quot;prompt&quot; &apos;&apos;&apos;You are an AI assistant tasked with classifying personal emails into specific folders.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Your job is to analyze the email&apos;s subject and body, then determine the most appropriate folder for filing.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Use only the folder names provided in your response.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;If the category is not clear, respond with &quot;Inbox&quot;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Classification Rules:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;- Family:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* File here if the message is signed by a Doe family member&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* The recipient&apos;s name is John Doe&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;- Cycling:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* File here if the message is related to cycling&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* File here if the message mentions the term &quot;MAMIL&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;- Work:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* File here if the message mentions &quot;Dunder Mifflin Paper Company, Inc.&quot; or any part of this name&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* File here if the message is related to paper supplies&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Only classify as Work if it seems to be part of an existing sales thread or directly related to the company&apos;s operations&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;- Junk Mail:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* File here if the message is trying to sell something and is not work-related&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Remember that John lives a minimalistic lifestyle and is not interested in purchasing items&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;- Inbox:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Use this if the message doesn&apos;t clearly fit into any of the above categories&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Analyze the following email and respond with only one of these folder names: Family, Cycling, Work, Junk Mail, or Inbox.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;&apos;&apos;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Prepare the base Subject and Body&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let &quot;subject&quot; &quot;thread_name(header.subject)&quot;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let &quot;body&quot; &quot;body.to_text&quot;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Send the prompt, subject, and body to the AI model&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let &quot;llm_response&quot; &quot;llm_prompt(&apos;gpt-4&apos;, prompt + &apos;\n\nSubject: &apos; + subject + &apos;\n\n&apos; + body, 0.6)&quot;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Set the folder name&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if eval &quot;contains([&apos;Family&apos;, &apos;Cycling&apos;, &apos;Work&apos;, &apos;Junk Mail&apos;], llm_response)&quot; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;fileinto &quot;${llm_response}&quot;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This example demonstrates how the &lt;code dir=&quot;auto&quot;&gt;llm_prompt&lt;/code&gt; function can be used to classify emails into different categories such as &lt;strong&gt;Family&lt;/strong&gt;, &lt;strong&gt;Cycling&lt;/strong&gt;, &lt;strong&gt;Work&lt;/strong&gt;, or &lt;strong&gt;Junk Mail&lt;/strong&gt; based on the content. The AI model analyzes the message’s subject and body according to the classification rules defined in the prompt and returns the most appropriate folder name. The email is then automatically filed into the correct folder, making it easier to organize incoming messages based on their content.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;self-hosted-or-cloud-based&quot;&gt;Self-Hosted or Cloud-Based&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;With this new feature, Stalwart Mail Server allows for seamless integration with both &lt;strong&gt;self-hosted&lt;/strong&gt; and &lt;strong&gt;cloud-based AI models&lt;/strong&gt;. If you prefer full control over your infrastructure, you can opt to deploy models on your own hardware using solutions like &lt;strong&gt;LocalAI&lt;/strong&gt;. Self-hosting gives you complete ownership over your data and ensures compliance with privacy policies, but it may require significant computational resources, such as GPU acceleration, to maintain high performance.&lt;/p&gt;
&lt;p&gt;Alternatively, you can integrate with &lt;strong&gt;cloud-based AI providers&lt;/strong&gt; like &lt;strong&gt;OpenAI&lt;/strong&gt; or &lt;strong&gt;Anthropic&lt;/strong&gt;, which offer access to powerful, pretrained models with minimal setup. Cloud-based models provide cutting-edge language processing capabilities, but you should be aware of potential costs, as these providers typically charge based on the number of tokens processed. Whether you choose self-hosted or cloud-based models, Stalwart gives you the flexibility to tailor the AI integration to your specific needs.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;available-for-enterprise-users-and-sponsors&quot;&gt;Available for Enterprise Users and Sponsors&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This exciting AI integration feature is exclusively available for &lt;a href=&quot;https://stalw.art/enterprise/&quot;&gt;Enterprise Edition&lt;/a&gt; users as well as GitHub and &lt;a href=&quot;https://opencollective.com/stalwart&quot;&gt;OpenCollective monthly sponsors&lt;/a&gt;. If you want to harness the full potential of AI-powered email processing in Stalwart Mail Server, upgrading to the Enterprise Edition or becoming a sponsor is a great way to access this feature and other advanced capabilities.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;try-it-out-today&quot;&gt;Try It Out Today!&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The release of Stalwart Mail Server v0.10.3 marks a major milestone in our journey toward building intelligent, highly customizable email management solutions. By combining traditional email filtering with the power of LLMs, Stalwart gives you the tools to take your email infrastructure to the next level, enhancing security, organization, and automation in ways that were previously impossible. We’re excited to see how you’ll use this new feature to optimize your email workflows!&lt;/p&gt;</content:encoded><category>llm</category><category>ai</category><category>openai</category><category>spam</category><category>stalwart</category><category>mail</category><category>server</category></item><item><title>OpenID Connect - Secure Authentication Just Got Easier</title><link>https://stalw.art/blog/openid-connect/</link><guid isPermaLink="true">https://stalw.art/blog/openid-connect/</guid><description>Today we announce the release of Stalwart Mail Server v0.10.2, and it’s a big one! This version brings full OpenID Connect (OIDC) support, empowering admins and developers to integrate secure authentication and single sign-on (SSO) with modern identity providers. In addition to OIDC, this release introduces OpenID Connect Dynamic Client Registration, OpenID Connect Discovery, and OAuth 2.0 Token Introspection. Let’s dive into what these features are and why they matter.

</description><pubDate>Wed, 02 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;what-is-openid-connect&quot;&gt;What is OpenID Connect?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://stalw.art/docs/auth/openid/&quot;&gt;OpenID Connect&lt;/a&gt; (OIDC) is an identity layer built on top of &lt;a href=&quot;https://stalw.art/docs/auth/oauth/&quot;&gt;OAuth&lt;/a&gt; 2.0 that allows clients to verify the identity of users. With OIDC, instead of just authorizing an app to access a resource, the system can also &lt;strong&gt;authenticate&lt;/strong&gt; the user securely. This means users can log in to multiple applications with a single set of credentials, making OIDC ideal for &lt;strong&gt;Single Sign-On (SSO)&lt;/strong&gt; across services.&lt;/p&gt;
&lt;p&gt;Why is this important? Because it saves users from password fatigue, reduces login complexity, and centralizes authentication in a secure manner. Stalwart Mail Server’s new OIDC support allows you to authenticate your users either directly through Stalwart as an OpenID Provider or by integrating with &lt;strong&gt;third-party OIDC providers&lt;/strong&gt; like Authentik, Keycloak, or any compliant identity system.&lt;/p&gt;
&lt;p&gt;Alongside full OIDC support, Stalwart Mail Server v0.10.2 also introduces several important new features that expand its capabilities:&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;openid-connect-dynamic-client-registration&quot;&gt;OpenID Connect Dynamic Client Registration&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Dynamic Client Registration allows clients (applications) to automatically register with the OIDC provider without requiring manual intervention. This feature makes it easier to integrate multiple applications, as clients can dynamically obtain credentials (like client IDs) directly from Stalwart Mail Server. This adds flexibility and reduces administrative overhead.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;openid-connect-discovery&quot;&gt;OpenID Connect Discovery&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;With the OpenID Connect Discovery feature, clients can automatically discover the relevant OIDC endpoints and supported capabilities via the &lt;code dir=&quot;auto&quot;&gt;/.well-known/openid-configuration&lt;/code&gt; endpoint. This simplifies the configuration of OIDC clients, as they don’t need to be manually configured with URLs for token, authorization, and userinfo endpoints — they just query the discovery endpoint and set themselves up!&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;oauth-20-token-introspection&quot;&gt;OAuth 2.0 Token Introspection&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;OAuth 2.0 Token Introspection allows resource servers (like APIs or mail servers) to validate access tokens provided by clients. This ensures that the token being used is still active, hasn’t expired, and has the right permissions attached. This is particularly useful for securing interactions between various services while verifying that tokens are still valid.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;openid-provider-or-third-party-oidc-support&quot;&gt;OpenID Provider or Third-Party OIDC Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Stalwart Mail Server v0.10.2 can now act as an &lt;a href=&quot;https://stalw.art/docs/auth/openid/provider&quot;&gt;OpenID Provider&lt;/a&gt; (issuing ID tokens and managing authentication), which means your organization can use it to handle authentication for all your internal applications and services. Alternatively, Stalwart can also integrate with &lt;a href=&quot;https://stalw.art/docs/auth/backend/oidc&quot;&gt;third-party OIDC providers&lt;/a&gt;, so you can delegate authentication to systems like &lt;strong&gt;Authentik&lt;/strong&gt; or &lt;strong&gt;Auth0&lt;/strong&gt;, while still using Stalwart to manage your email infrastructure.&lt;/p&gt;
&lt;p&gt;This dual functionality gives you the flexibility to choose how you want to manage authentication while taking full advantage of OIDC’s security features.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;about-oauthbearer&quot;&gt;About OAUTHBEARER…&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Now, let’s talk about mail clients and the &lt;a href=&quot;https://stalw.art/docs/auth/oauth/interoperability&quot;&gt;OAUTHBEARER SASL mechanism&lt;/a&gt;. While Stalwart fully supports OIDC, the majority of mainstream mail clients (looking at you, Outlook, Thunderbird, and Apple Mail) still don’t support OAUTHBEARER for OAuth-based authentication. Sure, we’ve done our part by adding OpenID support to Stalwart — now it’s up to the mail clients to follow suit and add proper support for OIDC authentication. Maybe one day, we’ll see these clients finally catch up, and we can all enjoy the seamless authentication experience that OIDC offers.&lt;/p&gt;
&lt;p&gt;In the meantime, users of these clients will need to continue using &lt;a href=&quot;https://stalw.art/docs/auth/authentication/app-password&quot;&gt;App Passwords&lt;/a&gt; to access their email accounts. But hey, maybe this is the gentle nudge the developers of these clients need to jump on the OpenID bandwagon!&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;try-it-out&quot;&gt;Try It Out&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Stalwart Mail Server v0.10.2 is available now, so download it, upgrade your server, and start taking advantage of these new features! Whether you’re setting up Stalwart as your OpenID Provider or integrating with a third-party provider, this release gives you the tools to secure authentication with modern standards like OpenID Connect.&lt;/p&gt;
&lt;p&gt;Happy mailing and happy authenticating!&lt;/p&gt;</content:encoded><category>oidc</category><category>openid</category><category>stalwart</category><category>mail</category><category>server</category></item></channel></rss>