Skip to content

Pre-release: hMailServer 6.2.23 Alpha 2

Pre-release
Pre-release

Choose a tag to compare

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

Re-published on GitHub on 18 October 2026 from the GitLab release v6.2.23-alpha2 of 2026-09-04. 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 4 September 2026 (2026-09-04 17:46:40 UTC). Issue, pull request and discussion numbers below are GitHub's.

hMailServer 6.2.23 Alpha 2

Pre-release. Not for production. 30 commits since v6.2.23-alpha1; 1,873 files touched, of which 1,825 are the licence-header pass from 22 August and 72 are the formatting commit, leaving roughly 80 files of actual change (+1,600 / −200 lines). The database schema is unchanged at 6025, the COM interfaces are unchanged, and no checked-in binary changed. Everything in Alpha 1's notes - the schema move from 6.2.21, the one-way upgrade, the known limitations - still applies to an installation coming from 6.2.21 or earlier.


What this release is

A small, deliberate release: one reported defect fixed, seven fixes taken from the original project - which has become active again after years - and the hardening that was written down as missing. It exists because a Thunderbird user could not save a single Sent copy, and because the upstream comparison turned up two ways a sender could steer the anti-spam tests. Alpha rather than beta because the STARTTLS change below alters what a non-conforming client sees, and that deserves a cycle in the open before it is called stable.


Fixed: Thunderbird's Sent copies were refused (GitHub issue 53)

Once a client enables UTF8=ACCEPT, RFC 6855 lets it send an APPEND's message as UTF8 (~{n} with the closing ) following the octets. Thunderbird 128 and later does this for every Sent copy. The server's command parser counts parentheses across the whole line before it tokenizes anything, saw one ( too many, and refused the line with BAD APPEND Command requires at least 2 parameter before reading a byte - so mail went out over SMTP and no Sent copy was ever stored, on every message, with only a per-machine client setting as a workaround.

The wrapper is now recognised and stripped ahead of the parser, and the ) is taken from the text that follows the octets. It works for the non-synchronizing ~{n+} form and for later messages of a MULTIAPPEND. A wrapper that is never closed is refused and nothing is stored - the ) is protocol, not message, and a server that guessed where the message ended would be worse than one that refused. Five fixtures, including the exact line from the report; six of their assertions fail against the previous binary.


Two anti-spam bypasses, ported from upstream

The original project has resumed development (seventy-one commits since this fork last compared itself against it). Every one was read against the function that does the same job here; the full record, verdict by verdict, is in .github/upstream-sync. Two of the ports matter for security:

The sender could choose which address the IP-based spam tests ran against

For mail arriving through an incoming relay or fetched from an external account, the server parses the topmost Received header to find the originating address. It took the first bracketed value after from - which is the HELO literal the client chose to present - rather than the address the receiving server actually observed, which comes last. And a header whose host name was not a valid domain name (my_pc, say) was skipped entirely, so parsing fell through into headers the sender wrote, or found no address at all and quietly skipped DNSBL, SPF and the HELO-host test.

The parser now takes the last observed address before by, ignores values marked as HELO-supplied, and keeps a header without a usable host name. Two assert(0) on sender-reachable input are gone with it. Upstream's own test vectors were taken along.

This changes which address is tested for relayed and fetched mail. If you run behind an incoming relay and have tuned scores around the old behaviour, expect verdicts to move - towards the address that actually connected.

RSET before EHLO, or STARTTLS without a fresh EHLO, opened a transaction with no greeting

RSET is valid before EHLO and used to move the session into the transaction state on its own; and the TLS handshake discarded the greeting as RFC 3207 requires but left the state machine where it was. Either way MAIL FROM was accepted with the HELO host empty, which skipped the HELO-host spam test and the OnHELO/OnEHLO script events for that session.

The greeting state is now only left by an actual EHLO or HELO. A client that sends MAIL FROM straight after the TLS handshake without saying EHLO again now receives 503 Bad sequence of commands - which is what RFC 3207 section 4.2 has required of it all along, and what every mainstream client does. If you have a home-grown submission script that skips the second EHLO, this is the release that tells you.


Hardening

  • Control Flow Guard is on (GitHub issue 45). hMailServer.exe is compiled and linked with /guard:cf in both configurations, so an indirect call through a corrupted function pointer or vtable - the natural target of a memory-safety defect in the SMTP, IMAP, POP3 or MIME parsers - terminates the process instead of transferring control. dumpbin /headers shows Guard in the DLL characteristics. The full regression gate on the CFG build ran in 31 minutes against about 55 for the previous release's gates on the same machine - a faster run, not a slower one, so the cost is below the suite's run-to-run variance.
  • The release tag is signed (GitHub issue 46). v6.2.23-alpha2 is the first annotated, SSH-signed tag; every earlier one was a lightweight ref with nothing to verify. The signing workflow now refuses to sign a single asset for a tag that is lightweight or does not verify against the allow list in the repository. Verification is in the last section.
  • An unattended install that fails its database step now fails. The installer discarded the result of the post-install tasks, so a failed database create or upgrade showed a suppressible message box and setup still exited 0. It raises now; scripted deployments can tell.
  • COM IMAPFolder.Delete reports a refused deletion instead of answering S_OK while the row stayed behind.

Other fixes

  • A reverse-DNS answer whose owner name carries the trailing dot (1.0.0.127.in-addr.arpa.) no longer fails the resolver's equality filter and empties the PTR result, which had been failing open in the HELO and reverse-DNS spam tests on affected hosts.
  • The script host dereferenced a null engine when engine creation had failed (a missing or policy-blocked VBScript engine) and a script reload asked whether a procedure existed.
  • The IMAP notification client dereferenced the current folder on the notifying session's thread while the owning session could be closing it.
  • Two CodeQL alerts on the mbox importer's buffer handling, and the warning-level findings the managed quality scan raised in the test suite and the header script.

Dependencies

Ten NuGet updates (Azure.Core 1.62, MSAL 4.88, NLog 6.2, OpenTelemetry 1.18, NUnit3TestAdapter 6.3, xunit.runner.visualstudio 4.0) and three CodeQL action updates, both from Dependabot. GitHub's automatic dependency submission - red on every push since it was enabled, because it restores Windows-targeting projects on a Linux runner - now completes, so the dependency graph carries the transitive packages. Getting it there also meant bumping the headers of ten Visual Studio 2005/2008-era solutions (legacy tools and test harnesses) that the .NET 10 solution parser refuses outright. The native dependencies are unchanged: OpenSSL 4.0.1, Boost 1.91, PostgreSQL 18.3, MariaDB Connector/C 3.4.9.

Repository and process

  • hmailserver/docs/RegressionEnvironment.md - how to set a machine up so the 1,800-test suite runs, which CONTRIBUTING.md had admitted was unpublished (GitHub issue 48).
  • A Developer Certificate of Origin check on pull requests (GitHub issue 47), and the C# tree brought to dotnet format clean with the verify job restored (GitHub issue 44).
  • Two CI-only changes landed after the regression gate had run and are the only things in this range that did: the editorconfig-checker version pinned beside its action (the checker's 4.0.0 release renamed its download and every run since 3 September had failed before checking a file), and the ten solution headers above. Neither is compiled into anything shipped, which is why the gate stands.
  • GitHub issue 49 (SCRAM-SHA-1) is closed as not planned, with the reason: the stored PBKDF2-SHA256 output is the SCRAM-SHA-256 salted password, and SHA-1 would need a second stored verifier per account - a change to what is stored, not to the transport.
  • Ten further upstream changes are recorded as roadmap rows with their size and what they wait for, the largest being upstream's way of building the C++ server on GitHub-hosted runners, which this fork lacks.

Known limitations

Everything listed under Alpha 1 still stands. New or newly written down:

  1. The weekly C++ CodeQL analysis has not run since late August. It targets a self-hosted runner that is no longer registered, and is cancelled after 24 hours in the queue each Monday. The C# analysis runs on every push. Restoring the runner, or porting the hosted build, is the roadmap's top build item.
  2. SCRAM-SHA-1 is not offered, for the reason above; clients without SCRAM-SHA-256 use PLAIN or LOGIN over TLS.
  3. Received-header parsing is stricter about host names but not about brackets. An address given without brackets ((HELO host) (203.0.113.99)) is still not recognised, as before.

Downloads and verification

Asset What it is
hMailServer-6.2.23-alpha2-x64.exe The installer (Inno Setup). Not Authenticode-signed.
*.spdx.json, *.cdx.json SBOMs, SPDX and CycloneDX, covering the .NET and native dependencies.
*.cosign.bundle A Sigstore bundle per asset, keyless, bound to this repository's workflow identity.

Verify the tag, from any clone:

git -c gpg.ssh.allowedSignersFile=.github/allowed_signers verify-tag v6.2.23-alpha2

Verify an asset with cosign:

cosign verify-blob --bundle hMailServer-6.2.23-alpha2-x64.exe.cosign.bundle \
  --certificate-identity-regexp '^https://github\.com/Progressiverobot/hmailserver/' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  hMailServer-6.2.23-alpha2-x64.exe

The server binary is reproducible: two clean Release builds of this tag produce a byte-identical hMailServer.exe, SHA-256 cff066d39af42dac3532cbc091b6294a69a73b7d323666c16bfa0fc045c8fe23, with the v145 toolset (MSVC 14.51), Windows SDK 10.0.26100 and the library layout in README.md. The regression suite on that binary: 1838/1838, nothing skipped, 31 minutes. Control Panel unit suite: 645/645.


Assets

File Size SHA-256
Progressiverobot-hmailserver-attestation-45313040.sigstore.json 3,985 5b3a5e266c4c75fd1fc99edfa0288ce7a0f93c2d579a49f34bc7cbb4e6a09ed9
hMailServer-6.2.23-alpha2-x64.exe 77,032,342 c680ac6c61be8ec5c2f1e3fafb16a747c444e41ddeb6fec9a85efa5c8a23d74b
hMailServer-6.2.23-alpha2-x64.exe.cosign.bundle 10,719 333f7e2b43ddfd455a5f50e1502e62913aefe01ac5632d99de393ac58e04d37a
hmailserver.cyclonedx.json 100,574 c2ccd6b9ab3ff2eaa904533d765134e8ed22c8439317adaedb1853aedc504893
hmailserver.cyclonedx.json.cosign.bundle 10,763 8a9a5023bf9a13f4ffcbd9b3ea49fa15f382604cdebeb25bc91b557b385ea8ce
hmailserver.spdx.json 168,670 134dacbddada704851da404638c70d641af180b925f4cb7a97f67a0fe33adda5
hmailserver.spdx.json.cosign.bundle 10,715 1b9b2be30dee0ab16f33e50148a0542a85714dfd7366b2b41014dbb6a844e626

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 of this release was not Authenticode-signed (Authenticode signing began with 6.3.1).