Skip to content

hMailServer 6.2.28

Choose a tag to compare

@chrisholloway5 chrisholloway5 released this 08 Sep 07:31
· 126 commits to master since this release
Immutable release. Only release title and notes can be modified.

hMailServer 6.2.28

The largest release of this fork so far, and three of its four headline features are things hMailServer has never had: the server can update itself, an account can use its own mailbox in a browser, and the Control Panel speaks seventeen languages. Underneath them is a real HTTP/1.1 server, which is what made the other two possible. Everything new here is off until it is turned on.


The server can update itself

A release is noticed, verified and applied - by a click, or inside a window you choose. UpdateCheckEnabled=0 is the default and nothing happens at all until it is set: no request, no identifier, no configuration, no counts. Turned on, a scheduled task reads this project's release feed every UpdateCheckHours (24 by default) and the Status page reports what it found. Fetching an installer and applying it are two further, equally opt-in steps.

What is applied is what this project signed. The installer is downloaded with the release's Sigstore bundle and verified before it is run: the certificate chains to Fulcio, the identity and issuer are this project's release workflow, the signature covers the file, and the entry is in the public transparency log. UpdateTrustRootsFile, UpdateSigningIdentity, UpdateSigningIssuer, UpdateSourceRepository and UpdateLogPublicKeyFile point that at a private Sigstore instance instead. This project's releases are not Authenticode-signed, so UpdateRequireAuthenticode=1 refuses every one of them; the Sigstore check is not optional and cannot be turned off.

The apply survives its own failure. hMailServer.Updater.exe runs the installer with the service stopped, waits UpdateServiceWaitSeconds (180) for it to come back, and reinstalls the previous version if it does not; the outcome is reported at the next start. The database upgrade authenticates with a single-use token, revoked at every service start, rather than with the administrator password. UpdateBackupBeforeApply=1 means an unattended apply does not happen at all without a configured backup destination and a backup that succeeded.

It works from behind a proxy. HttpProxy=host:port sends every web request this server makes as a client - the feed, its downloads, JWKS, token introspection - through a forward proxy: CONNECT for https with the TLS handshake inside the tunnel and the same certificate verification as a direct connection, the absolute URL for plain http. A proxy that refuses is reported by its own name and status line. No proxy credentials.

Only from 6.2.28 onwards. The version you are reading about is the first to carry any of this, so the upgrade to it is manual for everybody, as every upgrade has been. Its own Updates card in the Control Panel is where the next one is turned on.

An account can use its mailbox in a browser

/portal on the REST listener, and /api/v1/me behind it. It answers to an account's own credentials and to nothing else: no administrator password, no API key. Signing in exchanges the password for a session cookie the server keeps, so the password is sent once. A second factor is asked for where the account has one.

The page reads and writes the mailbox it belongs to: folders with their counts, a folder's messages with a cursor the keyboard moves, a message shown as it was sent - an HTML message inside a frame with an origin of its own, where nothing can reach the page around it - threads, flags, move, delete, marking in bulk, search over the account's own mail, attachments downloaded decoded under a type a browser will not execute, and shared and public folders alongside its own. It sends: a text or HTML message with attachments added the way the COM API adds one, every address put through the same checks a submitted message meets, drafts kept in the Drafts folder and replaced rather than duplicated, reply, reply-all, forward and Bcc.

It also carries what a person would otherwise ask an administrator for: the account's own quarantine, with release and delete; its name, forwarding, signature and vacation reply; its active Sieve script; and a password change - which is why the Control Panel's password-expiry text now says an expired password is renewed by an administrator or by the person themselves if they hold an app password.

A real HTTP server underneath

The REST API and the web services (autoconfiguration, autodiscover, the mobileconfig profile, CalDAV and CardDAV redirects) ran on a single-threaded HTTP/1.0 loop written for a handful of administrative requests. They now run on HttpServer: HTTP/1.1 on Boost.Asio with its own io_context and four workers, keep-alive, chunked bodies, header and body limits, and separate header and body deadlines. Every API answer carries Cache-Control: no-store. This is what a browser talking to the portal actually needs, and it is why the portal exists.

IMAP COMPRESS=DEFLATE (RFC 4978)

A session compresses both directions on request, so headers, bodies and the FETCH traffic of a large mailbox go over the wire deflated. It is advertised until compression is on and refused afterwards, as the RFC requires, and STARTTLS is refused once a session is compressed.

The Control Panel in seventeen languages

Czech, Danish, German, Spanish, Finnish, French, Italian, Japanese, Norwegian bokmål, Dutch, Polish, Brazilian Portuguese, Russian, Swedish, Turkish, Ukrainian and Simplified Chinese, beside English: every page, dialog, message, hint and verdict sentence - 3,376 texts, not a subset. The language is chosen in the connect card and remembered per user. Three checkers keep it honest in CI: a new English caption fails the build until it is marked and translated in all seventeen, the catalogues are checked against each other for the server's own words, numbers and page names, and every [Settings] key the server reads is checked to have an editor.

Administration in the browser

The Control Deck - the page the REST listener serves at / - reads the server's settings, the log files with any file's last 200 or 2,000 lines, the certificates by name and file, and the global rules with their criteria and actions in evaluation order. Writing is still the desktop Control Panel's and COM's; the roadmap row says so. The page is served as the bytes on disk with a Content-Security-Policy that allows its own inline script and style and nothing else, nosniff and no-referrer.

Fixed

A masked password was typed backwards from the second character (#156). In the Control Panel with the password hidden, 12345678 became 18765432; revealed text was fine. The masked box rebuilt its mask on every change and then restored the caret to the index it had read before the keystroke - correct on the ordinary keyboard path, wrong on an IME commit and on some layouts, which is what the reporter had. Every password box in the Control Panel now places the caret from the change itself.

Saving the SSL/TLS page dropped the post-quantum key exchange groups; saving the Scripting page took every COM object from every script. Two of the settings editors added for this release shipped without the server's absent-key default, and saving a page writes every field, so a blank was written where the server's own list belonged. Both now carry it, and both captions say what an empty value really does.

Five defects in the live update, found by reading it back against the tree before it had ever shipped: an unvalidated release tag and installer name from the feed, the apply token readable by any account on the machine, old downloads never swept, and the token not revoked at start.

The certificate renewal arithmetic that makes a 47-day certificate lifetime a non-event is pinned by tests rather than assumed.

Ten defects in the portal page, found the same way: attachments carried on forward and edit-draft, reply-all addressing, Bcc, thread indentation, the message list's cursor after a refresh, and a sign-in prompt instead of silence when a session expires.

Also in it

  • The four open code-scanning alerts closed on their merits, and the C# tree's LINQ notes rewritten rather than dismissed.
  • The repository's own documents and all 51 wiki pages read against the tree and corrected: routes, settings keys, schema and release stamps, two false paragraphs about the listeners, and two pages that did not render.
  • A roadmap section for Linux and AArch64, written from a measurement of the tree - 603 translation units through one ATL precompiled header, no CMake anywhere, but 466 of 1,237 server sources with no Windows token at all - rather than from hope.

Upgrading

No schema change: 6031, as 6.2.27. The installer's database upgrade runs as usual and has nothing to do on a 6.2.27 database.

Everything this release adds is off by default. UpdateCheckEnabled, RestApiPort (which the portal and the Control Deck need), IMAPCompressionEnabled and HttpProxy are all opt-in, and a server upgraded to 6.2.28 without touching its settings behaves exactly as it did on 6.2.27.

Verification

The full regression suite ran on the stamped binary: 2,127 tests, 2,119 passed, 0 failed, 8 skipped (7 explicit stress tests, 1 ignored where STARTTLS is not offered on the plain IMAP port of this bench). hMailServer.exe 6.2.28.38, SHA-256 9E89C1E3ABF4DD36560B0B5F3515BDA3DAB8B96F00EF35DA5376A9B60176BD15; installer hMailServer-6.2.28-x64.exe, SHA-256 FCC791855E9C1C4F3B2D3B8592B4D9CCBAC000DA866BBF8617561415078D5054. The database scripts build a 6031 database from the create script with all 65 schema probes passing, and the upgrade chain is contiguous and forward-only.

Known and unfixed

  • The Control Deck reads but does not write; a browser session for the administrator is still owed, so it holds the administrator password in sessionStorage while it is open.
  • The regression suite runs on Windows only. The Linux and AArch64 section of the roadmap says what that would take.