Skip to content

hMailServer 6.3.3

Choose a tag to compare

@RainbowWizard-coder RainbowWizard-coder released this 18 Oct 05:23
· 2630 commits to master since this release

Re-published on GitHub on 18 October 2026 from the GitLab release v6.3.3 of 2026-09-15. Each file below was checked against the SHA-256 that GitLab's package registry records for it before it was uploaded here.

Re-published on GitLab on 24 September 2026 from the GitHub release of 15 September 2026 (2026-09-15 01:02:52 UTC). Issue, pull request and discussion numbers below are GitHub's.

hMailServer 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 twelve 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 if you are upgrading from anything older than 6.3.1 (GitHub 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 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.

Delivery

An outbound BDAT chunk larger than one send buffer no longer stalls (GitHub 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: LINUX_RUN. 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).


Assets

File Size SHA-256
Progressiverobot-hmailserver-attestation-47493826.sigstore.json 8,633 37f7204ebcf54239283dce575d5e3dfd260acdc175bd80ba39ca9e64db4cd77a
hMailServer-6.3.3-aarch64.AppImage 9,927,176 5b17694df13b0c68cb147fb68210ceccae050e51cb93961221d572fb42c6aa00
hMailServer-6.3.3-aarch64.AppImage.cosign.bundle 10,759 09352a3fcbfa7e8938eb974d1074aaa86433be68181f704c2d06eaffc124a7e5
hMailServer-6.3.3-aarch64.AppImage.sigstore.json 10,759 09352a3fcbfa7e8938eb974d1074aaa86433be68181f704c2d06eaffc124a7e5
hMailServer-6.3.3-x64.exe 79,942,248 3188be2fa16a4c43d3b43ddbd7274e4cfe878c082343ef25ffbd00489610a057
hMailServer-6.3.3-x64.exe.cosign.bundle 10,811 654b658b9ce70396f76ff158247de4018e1021296d15fd0643e6f43b0b4a064e
hMailServer-6.3.3-x64.exe.sigstore.json 10,811 654b658b9ce70396f76ff158247de4018e1021296d15fd0643e6f43b0b4a064e
hMailServer-6.3.3-x86_64.AppImage 10,238,456 b65ac41c9393922fbb00b676313a3c55cfb7256aeebc23904701148c5a608907
hMailServer-6.3.3-x86_64.AppImage.cosign.bundle 10,863 623e491aaa7e0b55387624c12905fc54e15456765caca6e0cf4320efda5db648
hMailServer-6.3.3-x86_64.AppImage.sigstore.json 10,863 623e491aaa7e0b55387624c12905fc54e15456765caca6e0cf4320efda5db648
hmailserver-6.3.3-1.aarch64.rpm 4,482,990 61a10e5d94811cb9326e85579ba0bcc796c82d2a5f7b1ab683281a70e3de269b
hmailserver-6.3.3-1.aarch64.rpm.cosign.bundle 10,807 fcd802f6d85ce688c904682ebfa71af19fd94876efe3c52448f2574670117f3d
hmailserver-6.3.3-1.aarch64.rpm.sigstore.json 10,807 fcd802f6d85ce688c904682ebfa71af19fd94876efe3c52448f2574670117f3d
hmailserver-6.3.3-1.x86_64.rpm 4,566,829 6209a8ff6e3212d87a71b1b815f466841eb91005f50e5788f7244e0986ea1c25
hmailserver-6.3.3-1.x86_64.rpm.cosign.bundle 10,807 826cff34407b3ce547cdae8c34b896dc6287dab03326c94d17d59ef81fa74807
hmailserver-6.3.3-1.x86_64.rpm.sigstore.json 10,807 826cff34407b3ce547cdae8c34b896dc6287dab03326c94d17d59ef81fa74807
hmailserver-linux-6.3.3-SHA256SUMS.txt 584 020c3a28ccf333ab98b680e296781647edcbb8d96c36d0bffcc089375204b904
hmailserver-linux-6.3.3-SHA256SUMS.txt.cosign.bundle 10,759 c42cd1768981e4601fb45d1becedb640ae513f7461f152157eecedc1d5327ba1
hmailserver-linux-6.3.3-SHA256SUMS.txt.sigstore.json 10,759 c42cd1768981e4601fb45d1becedb640ae513f7461f152157eecedc1d5327ba1
hmailserver-v6.3.3.intoto.jsonl 24,351 039d5b3d9ac4d4c658ce9bf659283ca94214d33d28a06f5c82ca4d98af29833d
hmailserver.cyclonedx.json 179,723 f4ad84f2db639d71682776a74d5df15244bce27bba8834e2b6c3e3b745327ac7
hmailserver.cyclonedx.json.cosign.bundle 10,759 9b2ca5253b21cf4d8cac113abd9260acd894c4384a1104e5bc9a67241b5f7b41
hmailserver.cyclonedx.json.sigstore.json 10,759 9b2ca5253b21cf4d8cac113abd9260acd894c4384a1104e5bc9a67241b5f7b41
hmailserver.spdx.json 285,386 fb37a474bc445f85f78000836ed3e325c4369006d6a60bdc9adf73cfd46764de
hmailserver.spdx.json.cosign.bundle 10,815 bf0ed633be7f1ac380b512939f74b68178fe352de006939bc6217c893ef32601
hmailserver.spdx.json.sigstore.json 10,815 bf0ed633be7f1ac380b512939f74b68178fe352de006939bc6217c893ef32601
hmailserver_6.3.3_amd64.deb 4,551,484 8fc110d1dd0669868a5cdabad14bdc1e7c50df141210c883453dbe5b3c26e4b2
hmailserver_6.3.3_amd64.deb.cosign.bundle 10,907 cb4d4eeaac0c309fd110b796dd1e14507991cf1f1d39ca2affc49a9cb09cbf7a
hmailserver_6.3.3_amd64.deb.sigstore.json 10,907 cb4d4eeaac0c309fd110b796dd1e14507991cf1f1d39ca2affc49a9cb09cbf7a
hmailserver_6.3.3_arm64.deb 4,456,356 f435491e7b9036c23ac7a39d1431bbfc391215087b78ae855dc524146714f6fb
hmailserver_6.3.3_arm64.deb.cosign.bundle 10,907 d06ba5df78af971628f52d02bc3a96cae7ccd764afd95030011dbc7ad1a337bf
hmailserver_6.3.3_arm64.deb.sigstore.json 10,907 d06ba5df78af971628f52d02bc3a96cae7ccd764afd95030011dbc7ad1a337bf

These are the files published with the GitHub release, byte for byte, re-hosted in this project's package registry. The hashes above were computed from them on 24 September 2026. Each .cosign.bundle / .sigstore.json is the Sigstore bundle GitHub Actions made when the release was signed; all of them were verified again before re-publishing, against the former GitHub repository's workflow identity (https://github.com/Progressiverobot/hmailserver/..., issuer https://token.actions.githubusercontent.com), which is the identity to give cosign verify-blob for these files. The Windows installer carries a valid Authenticode signature (CN=Progressive Robot Ltd).