hMailServer 6.3.3

Latest

Signed 15 September 2026 6.3 series

Downloads for 6.3.3

Windows

Windows 10 (version 1607 or later) and Windows 11, or Windows Server 2016 and newer; 64-bit only. Run the installer as an administrator: it upgrades an existing 5.x or 6.2.x installation in place. The installer is Authenticode-signed by Progressive Robot Ltd.

  • hMailServer-6.3.3-x64.exex64 · 76.2 MB
    Download
    SHA-2563188be2fa16a…9610a057 Verified against release notesSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)

Debian and Ubuntu

A .deb for Debian, Ubuntu and their derivatives on x86-64 and AArch64, built on Ubuntu 24.04 with Boost linked statically, so it installs on later releases too. It sets up the service, its systemd unit and the configuration under /etc/hmailserver.

  • hmailserver_6.3.3_amd64.debx86-64 · 4.3 MB
    Download
    SHA-2568fc110d1dd06…3c26e4b2 Verified against SHA256SUMSSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)
  • hmailserver_6.3.3_arm64.debAArch64 · 4.2 MB
    Download
    SHA-256f435491e7b90…6714f6fb Verified against SHA256SUMSSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)

Installsudo apt install ./hmailserver_6.3.3_amd64.debthen the three first-run commands

Fedora, RHEL and openSUSE

An .rpm for Fedora, Red Hat Enterprise Linux, RHEL-compatible distributions and openSUSE on x86-64 and AArch64. dnf resolves its dependencies from your own repositories; Boost is linked statically from 6.3.2.

  • hmailserver-6.3.3-1.x86_64.rpmx86-64 · 4.4 MB
    Download
    SHA-2566209a8ff6e32…86ea1c25 Verified against SHA256SUMSSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)
  • hmailserver-6.3.3-1.aarch64.rpmAArch64 · 4.3 MB
    Download
    SHA-25661a10e5d9481…e3de269b Verified against SHA256SUMSSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)

Installsudo dnf install ./hmailserver-6.3.3-1.x86_64.rpmthen the three first-run commands

AppImage (try it out)

For seeing hMailServer run on a laptop, not for running mail: it runs as whoever starts it, with no service user, no systemd unit and no hardening, and it cannot bind port 25. Install the .deb or the .rpm to run mail.

  • hMailServer-6.3.3-x86_64.AppImagex86-64 · 9.8 MB
    Download
    SHA-256b65ac41c9393…5a608907 Verified against SHA256SUMSSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)
  • hMailServer-6.3.3-aarch64.AppImageAArch64 · 9.5 MB
    Download
    SHA-2565b17694df13b…42c6aa00 Verified against SHA256SUMSSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)

Installchmod +x hMailServer-6.3.3-x86_64.AppImage

What’s new in 6.3.3

A message larger than 60,000 bytes sent with CHUNKING to Gmail, iCloud, Outlook.com or Postfix stalled after its first buffer and the remote timed out - every such message since outbound BDAT arrived - and does not now; the webmail was rebuilt to the shape of Gmail and Outlook.com and gained tabs, mute, pop-out windows, search history and fourteen more search operators; the account's address book is served over CardDAV to phones and desktop clients; the browser Control Deck is measured against the desktop Control Panel and moved a long way toward it; the Linux regression suite's route backlog is largely lifted; and a live update started from an open Control Panel no longer fails on its own files.

Read this first

Read this first if you are upgrading from anything older than 6.3.1 (issue #263). 6.3.2 could not upgrade a database whose schema was older than its own: the guard added in 6.3.2, which makes a database the server has refused answer COM with the refusal instead of crashing, covered the whole Settings object, and DBUpdater reads the script directory from it before it runs the first script - so every upgrade from 5.x or 6.2.x stopped with "The server has not loaded its configuration" and left the database untouched. 6.3.3 upgrades such a database in one go; nothing in the database was changed by the failed attempt. The settings object answers its directories on a refused database again, everything that lives in the configuration is refused with the reason, DBUpdater derives the script directory from its own location if the server cannot answer, and a regression test walks DBUpdater's path over COM against a database the server has refused.

Read this first

Read this too if you run 6.3.1 or 6.3.2 and use the Control Panel's live update. The first real update, 6.3.1 to 6.3.2, failed with the installer's exit code 5 because the Control Panel that started it kept its own files open. That is fixed here - but the helper that runs a live update is the one already installed, so an installation on 6.3.1 or 6.3.2 has to be updated by hand once: close the Control Panel, run this installer. Live updates work from then on.

Full release notes for 6.3.3 10 sections

Delivery

An outbound BDAT chunk larger than one send buffer no longer stalls (issue #261). The connection sends a message 60,000 bytes at a time; the SMTP client armed the read for the reply as soon as the BDAT command - or, with PIPELINING, the envelope - had been queued, and the second buffer of the chunk was then queued behind that read in the connection's operation queue, which starts only the operation at its head. The read could not complete while the remote waited for the bytes behind it, so nothing sent them, and the remote gave up after its own timeout (iCloud's 421 after five minutes, in the report). Every message over 60,000 bytes to a server advertising CHUNKING has stalled this way since outbound BDAT arrived in 6.2.28; a message that fit one buffer went, which is why short ones did; DATA never met it, because its body streams only after the 354. The operation queue runs once more after a read has started, so a write behind it goes at once. Two regression tests relay a 222 KB message over BDAT, with the envelope pipelined and without. Until you upgrade, OutboundChunking=0 in hMailServer.ini is the workaround.

The full-text indexer no longer reports an error for a message deleted before its terms were saved. On PostgreSQL the foreign key refuses the terms of a row that is gone (SQL Server Compact accepted them); the message is logged at debug level and skipped, since there is nothing left to index.

The webmail

Rebuilt to the shape of Gmail and Outlook.com. The page is real files now (Portal.html, Portal.js), embedded into the binary at build time. A top bar with one search box and its options panel; a navigation column with the system folders by their designation, then the account's folders, labels, Held mail, Contacts, Scheduled and the storage meter; a list whose row is a checkbox, a star, an avatar, the sender's name, the subject and the first line of the text, an attachment mark and a time, with archive, delete and mark-read under the pointer; a reading pane on the right, below, or off; a toast with Undo after every move; the keys a mail client has (c, r, a, f, s, o, u, /); settings behind the gear; the same page on a phone; light and dark.

Writing. The compose window docks at the bottom right, minimises to its bar or opens full; a reply, reply to all or forward is written under the message it answers, with the earlier messages of the conversation above it as cards. An attachment reminder asks once before a send whose text speaks of an attachment and carries none. A message, or the message being written, pops out into a window of its own.

The list. A row dragged onto a folder, with undo. A right-click menu on a row (open, archive, junk, delete, read, star, pin, block, sweep). A pin keeps a message at the top of its list (the $Pinned keyword, the way every mail program sees it). Block this sender writes a rule that files the sender into Junk; Delete all from this sender sweeps the folder. Shift-click selects a range and ctrl-click one row, as every desktop client has them. A selection can take in every message of the folder, or of the open tab.

Mute, and the inbox in tabs. A muted conversation leaves the inbox, its messages carry $Muted, and a rule the page writes files whatever answers any of them into the archive; Undo takes all of it back. The inbox comes in tabs - Primary, Social, Promotions, Updates and Forums the way Gmail sorts them, or Focused and Other the way Outlook does, or one list - the server saying which from the headers alone (the sender's domain, List-Post, List-Unsubscribe, Precedence, Auto-Submitted), the reader overruling it per sender from the row's menu.

Search. The last ten searches are offered under the empty box (kept in this browser, forgotten at sign-out), and a contact's name typed there completes to from:<address> from the address book. Fourteen more operators, parsed by the server beside the ones it had: cc:, bcc:, filename:, larger:, smaller:, older_than:, newer_than:, is:muted, is:pinned, category:, has:link, in_reply_to:, a -word to exclude, and OR. The reference is hmailserver/docs/WebmailShortcuts.md.

Follow-up, nudges, quick steps, clean-up. A flag can carry a due date - today, tomorrow, next week or a date - kept as $FollowUp and a $Due-YYYY-MM-DD keyword on the message itself, so other clients still see a flag and a move keeps the date; the row shows it, the Starred view sorts by it, and a reminder comes once a day. Nudges say "Received N days ago. Reply?" on a message that asked and "Sent N days ago. Follow up?" on one nothing answered; a preference turns them off. Quick steps are buttons a reader defines - move, mark read, label, forward, in one press, on the digit keys. Clean up conversation deletes the messages whose every line a later message quotes, keeping the newest, the unread, the starred and those with attachments, with Undo.

Everything above is in the twenty languages the page speaks, and the harness that executes the page's script runs 224 checks on it in CI.

CardDAV

The account's address book, on phones and desktop clients (RFC 6352). On the web services listener: /.well-known/carddav redirects to /dav/, a PROPFIND there answers the principal, the principal the address-book home, and the home holds one book, Contacts - the address book the webmail keeps and completes recipients from. The card a client sends is the card it reads back: the card itself is stored beside the contact (schema 6040), vCard 3.0 or 4.0, both advertised, and an edit made in the webmail is written into the stored card with the UID and the telephone number the phone gave it left alone. HTTP Basic as the account or an application password, over HTTPS only, with the IMAP logon's lockout and auto-ban; addressbook-query, addressbook-multiget and sync-collection reports; ETags with If-Match and If-None-Match. iOS, macOS Contacts, DAVx5 and Thunderbird speak it. The web services HTTPS listener has to be on (WebServicesHttpsPort).

The Linux control panel

Measured. build/check-deck-parity.py counts every field the desktop Control Panel writes against the REST API and the browser Control Deck, from the sources; hmailserver/docs/DeckParity.md is its report. Of 330 properties, 240 were writable over REST and 153 reachable from a Deck view at the start of 14 September; 328 and 322 by its end, the two not writable being groups and their members.

Moved. New write routes: the anti-virus settings as a group (/api/v1/settings/antivirus), sixteen more account fields and nine more domain fields on their PUTs, the distribution list's settings and a PUT for it, DNS blacklists, SURBL servers, white-list addresses, blocked senders, incoming relays, blocked attachments and the greylisting white list as resources, the cache group's eight ceilings and lives, an IP range's expiry, abort_spam_flagged on a rule's forward and reply, user_interface_language, and - under an account's address, for the administrator - its application passwords, its folders' permissions and its messages. The Deck gained a harness of its own (build/check-deck-script.py, 292 checks, in CI), full domain editing, an IP-ranges view with expiry, fetch-account and backup views, the account editor in full, distribution lists and aliases under their domain, the seven small collections, server messages, and the scripting, cache and indexing groups with their verbs.

The Linux regression suite

The route backlog, waves A to H. A REST route for every family the Linux fixtures had skipped: the directories and the ini section of the settings, the logon-failure list, domain aliases, a domain read whole and renamed, an IP range updated in place, the server messages, Sieve evaluation, fetch accounts, scripting, the backup settings, an account read whole, the caches, the message index and the relayer's password - and a build object on /api/v1/status. Then, in the day's last batch, the three families that stood behind most of what was left: application passwords administered under /api/v1/accounts/{address}/app-passwords, folder permissions under .../folders/{id}/permissions with the rights by the names the COM interface gives them and the letters SETACL takes, and the message object - a folder's whole live collection, a message read as a row with every header, a raw .eml added on APPEND's path, the flags changed on STORE's, a delete on EXPUNGE's - with the shims rewritten so that a fixture skips only against an older server whose OpenAPI lacks the route. The hosted Linux run on this release's tree: 1520 tests, 1289 passed, 0 failed, 231 skipped. Three server defects found on the way: a vacation save PostgreSQL refused, ncsa refused as a log format, a negative thread id on Linux. And one on every Windows installation, found by the first honest Windows gate of the branch: a domain's relay password could not be saved - the column was 255 characters and a DPAPI envelope is 314. Schema 6039 widens it.

The Control Panel

The live update from an open Control Panel. The helper ends whatever runs from under the installation before each installer run, the Control Panel closes itself once the helper has started, and a failed run's outcome quotes what the installer's own log says went wrong. See the note at the top.

Two defects the tidy branch's own gates found. generate-com-wrapper.ps1 died under Windows PowerShell the first time its MIDL path ran (MIDL's stderr became a terminating error); a COM error out of a recordset walk ended a scheduled task with a minidump and no description - ADORecordset::MoveNext catches it now (HM5037) and the exception handler names COM errors. The fetch-account editor's connection-security captions no longer carry POP3's port numbers into an IMAP account.

Security, from the release's own review

An adversarial review of everything the server gained since 6.3.2 ran before this release was cut, and what it confirmed is fixed here. The [Settings] section of hMailServer.ini over REST answered to any api key: a read-only key could read every secret the section holds (the OAuth2 HMAC secret, the password pepper, the service account's password), and a write key could set AutoBanCommand, which the firewall reconciliation runs as the service. The four ini routes answer to the administrator password only now, as the api-key routes do; a key of any scope gets the same 401. A key restricted to a domain could lift that domain's limits through PUT /api/v1/domains/{domain} - the eleven fields the COM interface gates on the server administrator - and is refused them with 403 now. In CardDAV, a REPORT body of a million ampersands cost a worker thread tens of seconds (the entity scan is bounded), a multiget answered the same href as often as it was asked, five thousand times at most (a repeated href is answered once, and a multistatus over 64 MiB is refused), and on MySQL the card column could not hold the megabyte the collection advertises (it can). Smaller: a refused save on a collection update no longer leaves the in-memory item changed; one restart thread at a time; the escaper's PostgreSQL flag is re-read per statement; the packaged fail2ban filter matches a logon failure whose name carries a double quote; an XML name may not carry an ampersand, a semicolon or a control byte. Two tests hold the two key-scope findings.

Build and supply chain

One header on every source file, the project's, in one form, put there and checked by build/add-license-headers.py.

The container image job of a tag run asks docker for the image by a lower-case name. At 6.3.2 the image was pushed and the smoke test that starts it was refused the capital letter in the owner's name; the image itself was fine.

The Linux suite's shims learned the anti-virus group and the nine domain properties the new fixtures read.

Database

On PostgreSQL, a backslash is stored as one backslash. Every value with a backslash in it - a Windows path in a DKIM key-file setting, a backslash in a signature, a vacation message or a rule - was stored with the backslash doubled, because the escaper doubled it for PostgreSQL unconditionally, which is right only while standard_conforming_strings is off, and it has been on by default since PostgreSQL 9.1. The connection now reads the server's own answer when it comes up and doubles only where the server would otherwise read the backslash as an escape. Found by the hosted Linux run reading a domain's key-file path back as C:\\keys\\next.pem. Values already stored doubled stay as they are; edit and save them once.

Schema 6039: a domain's relay-password column widened for a DPAPI envelope. Schema 6040: the CardDAV tables. Both upgrade in place.

Verification

The full regression suite ran on the stamped binary: 2,302 tests, 2,294 passed, 0 failed, 8 skipped. hMailServer.exe 6.3.3.42, SHA-256 2c57f78050ecc43ee6d69ac3a2dc42b1dd802cc35ec369c09457d8119d53510a.

The installer has two hashes, and both are given deliberately. hMailServer-6.3.3-x64.exe as built, 79,926,537 bytes: SHA-256 45a9d7f1a78bb31031dde27849fa21828a60aff178f32cbc2b0d9cd93f6b33f2. As published, after Authenticode signing: SHA-256 3188BE2FA16A4C43D3B43DDBD7274E4CFE878C082343EF25FFBD00489610A057.

The assertion build, first. A separate build with HM_ASSERT on - every internal invariant checked and any failure fatal - ran the whole suite before the shipping binary was built: 2,302 tests, 2,294 passed, 0 failed, 8 skipped. Nothing asserted.

Reproducible. Three clean Release builds of the stamped tree - the first two compared for the purpose, the third the one that ships - produced the same hMailServer.exe.

On the way here. Every batch that landed on master went through the full Windows suite on its exact tree before it was pushed, and the hosted Linux run on the last of them: the numbers are in the wiki's "Changes since 6.2.10" page, section 4d. The hosted Linux run on the release tree itself: 1520 tests, 1289 passed, 0 failed, 231 skipped (run 34904809203).

Release facts

Version
6.3.3
Signed
15 September 2026Sigstore transparency log
Packages
7Windows and Linux, x86-64 and AArch64
Database schema
6040upgrades in place
Regression suite
2,302 tests2,294 passed · 0 failed · 8 skipped
Windows build
6.3.3.42reproducible
Installer SHA-256
3188be2fa16a…9610a057hMailServer-6.3.3-x64.exe

Every file in 6.3.3

Full SHA-256 of each file as recomputed on this server, with its Sigstore bundle beside it. The SBOM and the provenance are not needed to install: the SBOM lists every component in the build, and the provenance records how and where it was built.

FileWhat it isSizeSHA-256Signature
hMailServer-6.3.3-x64.exeWindows installer · x6476.2 MB3188be2fa16a4c43d3b43ddbd7274e4cfe878c082343ef25ffbd00489610a057 release notesSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)
hmailserver_6.3.3_amd64.debDebian package · x86-644.3 MB8fc110d1dd0669868a5cdabad14bdc1e7c50df141210c883453dbe5b3c26e4b2 SHA256SUMSSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)
hmailserver_6.3.3_arm64.debDebian package · AArch644.2 MBf435491e7b9036c23ac7a39d1431bbfc391215087b78ae855dc524146714f6fb SHA256SUMSSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)
hmailserver-6.3.3-1.x86_64.rpmRPM package · x86-644.4 MB6209a8ff6e3212d87a71b1b815f466841eb91005f50e5788f7244e0986ea1c25 SHA256SUMSSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)
hmailserver-6.3.3-1.aarch64.rpmRPM package · AArch644.3 MB61a10e5d94811cb9326e85579ba0bcc796c82d2a5f7b1ab683281a70e3de269b SHA256SUMSSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)
hMailServer-6.3.3-x86_64.AppImageAppImage · x86-649.8 MBb65ac41c9393922fbb00b676313a3c55cfb7256aeebc23904701148c5a608907 SHA256SUMSSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)
hMailServer-6.3.3-aarch64.AppImageAppImage · AArch649.5 MB5b17694df13b0c68cb147fb68210ceccae050e51cb93961221d572fb42c6aa00 SHA256SUMSSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)
hmailserver-linux-6.3.3-SHA256SUMS.txtSHA-256 checksumsOne line per Linux package; feed it to sha256sum -c.584 bytes020c3a28ccf333ab98b680e296781647edcbb8d96c36d0bffcc089375204b904Sigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)
hmailserver.spdx.jsonSBOM (SPDX)Every component in the build, in SPDX JSON.279 KBfb37a474bc445f85f78000836ed3e325c4369006d6a60bdc9adf73cfd46764deSigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)
hmailserver.cyclonedx.jsonSBOM (CycloneDX)The same inventory in CycloneDX JSON.176 KBf4ad84f2db639d71682776a74d5df15244bce27bba8834e2b6c3e3b745327ac7Sigstore bundle: .cosign.bundle / .sigstore.json (same bundle, two names)
hmailserver-v6.3.3.intoto.jsonlSLSA build provenancein-toto attestation of how and where the release was built.24 KB039d5b3d9ac4d4c658ce9bf659283ca94214d33d28a06f5c82ca4d98af29833d
Progressiverobot-hmailserver-attestation-47493826.sigstore.jsonBuild attestationGitHub artifact attestation for the release, as a Sigstore bundle.8 KB37f7204ebcf54239283dce575d5e3dfd260acdc175bd80ba39ca9e64db4cd77a