Repository navigation
Installing hMailServer
This page began as a chapter of the 6.2.10 manual and has been corrected against the 6.2.28 source tree. The Control Panel's pages are grouped differently now, so the paths below use today's groups; the TLS ports 465, 993 and 995 exist only after you create them on the TCP/IP ports page (a fresh install seeds 25, 587, 110 and 143); and everything added since 6.2.10 is in Changes Since 6.2.10. Where a value here disagrees with the Settings Reference, which is generated from the code, the reference is right. The profile page, the service-account page, the secure defaults of a new installation, the stored-secrets key, the first-hour checklist and the upgrade notes were checked against 6.3.4 (27 September 2026, schema 6104) - and on 5 October 2026 against 6.3.6 (6 October 2026, schema 6108), for what 6.3.6 changes on this page: the folders made private, the exit codes, the grant through a junction, the SQL Server login, a new installation with no window - in 6.3.4's installer script at master 92b8f9f63, and the administrator password's hand-off, the download links and the checks of a download against the tag v6.3.4 (51e2dbda0), the release. Brought up on 18 October 2026 to 6.3.7, the latest release (17 October 2026, schema 6108), from the tag v6.3.7 (
31d656c0c) and its release: the download, its check and the program folder/ProtectFoldersnow hardens as well; what else 6.3.7 changes for an installation is in Upgrading hMailServer 18.4f.
Everything on this page is drawn from the installer script itself — hmailserver/installation/,
an Inno Setup project whose logic lives in hMailServerInnoExtension.iss. Where a claim
here matters, the file and function are named so you can check it.
Work through Before You Install first.
Get hMailServer-6.3.7-x64.exe from the
latest release - 6.3.7, published on
17 October 2026 - or by the link that always fetches the latest installer:
https://gitlab.com/hmailserver/hmailserver/-/releases/permalink/latest/downloads/hMailServer-x64.exe.
GitLab picks that release by date and has no pre-release flag, so the project's own download link,
https://updates.progressiverobot.com/download/hMailServer-x64.exe, always leads to the newest stable
release, never a pre-release, and /download/ to that release's page; the site has had its certificate
since 26 September 2026.
The releases up to 6.3.3 were first published on GitHub. Since GitHub suspended the project's account on
18 September 2026, they are re-published on GitLab under their original dates, each file the same, byte for
byte, but for 6.2.0 and 6.0.0-B4, which are notes-only there; 6.3.4 is the first release published on GitLab first. Since 18 October 2026 every release from 6.0.0-B1
to 6.3.7 is also at https://github.com/RainbowWizard-coder/hMailServer/releases, copied there from GitLab
with the same files byte for byte (GitHub writes . where a file name has ~, so the per-distribution
.deb files are renamed there), and each later release is copied there once GitLab has published it.
The releases from 6.2.19 to 6.3.3 also carry (the two SBOMs from 6.2.3; the five earlier releases that carry an installer have a CycloneDX SBOM of it alone, made afterwards - Security Policy, Supply chain):
| Asset | What it is | Do you need it? |
|---|---|---|
hMailServer-<version>-x64.exe |
The installer | Yes |
hmailserver.spdx.json |
SBOM in SPDX format | Only if you audit your supply chain |
hmailserver.cyclonedx.json |
SBOM in CycloneDX format | Only if you audit your supply chain |
<asset>.cosign.bundle |
A Sigstore signature and certificate bundle for every asset but the two SBOMs of 6.2.22-pre3 | Recommended — it is how you prove the file came from this repository's build |
6.3.4 carries:
| Asset | What it is | Do you need it? |
|---|---|---|
hMailServer-6.3.4-x64.exe |
The installer | Yes |
hMailServer-6.3.4-x64.exe.cdx.json |
The installer's own SBOM, CycloneDX 1.6, whose subject is the installer by its SHA-256 and SHA-512 | Only if you audit your supply chain |
hmailserver.spdx.json, hmailserver.cyclonedx.json
|
The source tree's SBOMs | Only if you audit your supply chain |
hmailserver-6.3.4-SHA256SUMS.txt |
The SHA-256 of every file of the release but itself and its signature | Recommended |
hmailserver-6.3.4-SHA256SUMS.txt.sig |
An SSH signature of the sums, made with the key that signs the release tags | Recommended — it is how you prove the files are the project's |
beside the Linux packages and their SBOMs (Installing on Linux).
6.3.4 carries no .cosign.bundle. It was built and Authenticode-signed by hand, after
GitHub's suspension and before the project's GitLab CI signing job existed, so there is no
Sigstore signature to check. Check the signed sums instead, with OpenSSH 8.1 or later, in a
clone of the repository (for .gitlab/allowed_signers) and with the downloads beside you:
ssh-keygen -Y verify -f .gitlab/allowed_signers -I christopher.j.holloway@outlook.com -n file -s hmailserver-6.3.4-SHA256SUMS.txt.sig < hmailserver-6.3.4-SHA256SUMS.txt
sha256sum -c --ignore-missing hmailserver-6.3.4-SHA256SUMS.txtThe first must say Good "file" signature for christopher.j.holloway@outlook.com, and the
second OK for each file you downloaded (Security Policy, Verifying a release; the same
page says how to check that an SBOM describes its file). Then the installer's Authenticode
signature (below). For the same
reason no server's live update installs 6.3.4 - a server offered it says it cannot be
verified and downloads nothing - so every server is upgraded to it by hand, by running the
installer (Upgrading hMailServer). The releases after it are signed by the project's
GitLab CI, a signer every server from 6.3.4 on has compiled in; Upgrading hMailServer
18.4f says which servers install 6.3.7 by their live update.
Get-AuthenticodeSignature .\hMailServer-6.3.4-x64.exe | Format-List Status, SignerCertificateStatus must be Valid, and the signer's subject names Progressive Robot Ltd.
Checking 6.3.7. 6.3.7 was made, as every release since 6.3.5 has been, by its tag's GitLab
pipeline. Each of its sixty-two files - among them the two Windows installers,
hMailServer-6.3.7-x64.exe and the ARM64 preview hMailServer-6.3.7-arm64.exe, each with its
own CycloneDX SBOM (<installer>.cdx.json), and the source tree's two SBOMs - is signed with
Sigstore, its bundle beside it as <file>.cosign.bundle, and hmailserver-6.3.7.intoto.sigstore.json is the
release's SLSA build provenance. It carries no .sig: the pipeline cannot hold the release
tags' SSH key. Check the installer against the SHA-256 that the Download table at the head of
the release's notes gives it - dcae96bd75d6cae8e5a910d15940567067539ed99db5aeed40a815added4d85f
for hMailServer-6.3.7-x64.exe - or against its bundle, with the identity the notes'
Verification names:
cosign verify-blob \
--bundle hMailServer-6.3.7-x64.exe.cosign.bundle \
--certificate-identity https://gitlab.com/hmailserver/hmailserver//.gitlab-ci.yml@refs/tags/v6.3.7 \
--certificate-oidc-issuer https://gitlab.com \
hMailServer-6.3.7-x64.exeIt must say Verified OK, and the certificate must carry the project's id, 86730559
(Security Policy, Verifying a release, reads it with OpenSSL). Then the installer's
Authenticode signature, as above: Get-AuthenticodeSignature .\hMailServer-6.3.7-x64.exe must
answer Valid, signed by Progressive Robot Ltd.
Verifying a release up to 6.3.3. Signing was keyless Sigstore: the signature is bound to this repository's GitHub Actions identity through OIDC and recorded in the public Rekor transparency log, so there is no key for anyone to leak. Every release from 6.2.19 to 6.3.3 was signed there, so the identity and issuer below are facts about those files wherever they are hosted, and the check contacts nothing at GitHub. With cosign installed:
cosign verify-blob \
--bundle hMailServer-6.3.3-x64.exe.cosign.bundle \
--certificate-identity-regexp '^https://github\.com/Progressiverobot/hmailserver/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
hMailServer-6.3.3-x64.exeVerified OK
What a server's own update check trusts. A server from 6.2.28 to 6.3.3 pins that one
GitHub identity and issuer (SigstoreVerifier.cpp), and reads by default the Releases API
of the suspended account's repository, github.com/Progressiverobot/hmailserver, which has
answered 404 since 18 September 2026 and still does - the releases copied to GitHub since
18 October 2026 are under another account, where such a server does not look: point it at
UpdateFeedUrl=https://updates.progressiverobot.com/releases.json (Upgrading hMailServer
§18.7, UpdateFeed.md). 6.3.4 reads
https://updates.progressiverobot.com, which GitLab Pages serves from the project's releases,
without being told, and trusts two signers: the GitHub workflow, for a certificate issued
before the suspension and a release no later than 6.3.3, and the project's GitLab CI
pipeline for the v* tag of the release being installed, which has signed every release
since 6.3.5 - at the path the project began at, where it signed 6.3.5, and at the path of
the group hmailserver, which the project moved to on 29 September 2026 and where it has
signed every release from 6.3.6, there only with the project's id, 86730559, in the
certificate - so that a server kept updating after the move.
Signed from 6.3.1. The installer carries an Authenticode signature from Azure Artifact Signing, countersigned with an RFC 3161 timestamp, so the UAC prompt names Progressive Robot Ltd rather than Unknown publisher, and a policy that refuses unsigned binaries no longer refuses this one. SmartScreen still warns: it judges a file by reputation, and a new installer every few weeks never accumulates any, so expect Windows protected your PC with the publisher's real name on it. Releases before 6.3.1 are unsigned and stay so: every release up to 6.3.3 whose files GitLab has is re-published there, and since 18 October 2026 copied to GitHub, with its original files and signatures, byte for byte (6.2.0 and 6.0.0-B4 are notes-only). From 6.2.19 to 6.3.3, Sigstore is the check that proves provenance for every asset but the two SBOMs of 6.2.22-pre3, Linux packages included:
cosign verify-blobagainst the.cosign.bundlebeside each file (the GitHub workflowsign-release.yml, in the git history atv6.3.3). 6.3.4 has the Authenticode signature on the Windows installer, and its files - the Linux packages included - are covered by its SHA-256 sums file, signed with the release tags' SSH key (above).
choco since 23 October 2026; winget not yet. The repository renders a winget manifest set
(ProgressiveRobot.hMailServer) and a Chocolatey package (hmailserver-progressiverobot)
for a release, from templates, by build/make-package-manifests.ps1, hashed from the
asset the release actually published — downloaded, its Authenticode signature required,
and the SHA-256 taken from those bytes, because signing changes the bytes and a hash copied
by hand between two windows is eventually wrong. Each package says in its title or name and
in its description that it is Progressive Robot's fork of hMailServer, and never takes an
identifier that is the original's. Chocolatey: the chocolatey-publish job pushed
hmailserver-progressiverobot 6.3.7 on 20 October 2026; on 21 October 2026 a moderator
returned it, asking that its authors also credit the original hMailServer's author, Martin
Knafve, and on 22 October 2026 the job sent 6.3.7 again in its place, saying that it is the
fork but not yet crediting him. On 23 October 2026 the job sent 6.3.7 a third time, with the
credit, and a moderator approved it at 11:56 UTC that day: the community repository's feed lists
it as Approved, and choco install hmailserver-progressiverobot installs 6.3.7 from the
release's signed installer. Every new version waits for a moderator the same way. The id hmailserver is the original's, an unlisted package of its
5.6.8: choco install hmailserver finds nothing, and does not install this project.
winget: not submitted. Its community repository takes pull requests on GitHub alone, and
the project's submissions there are paused, so winget install ProgressiveRobot.hMailServer
does not work yet; and a community packager's pull request adds the original as
hMailServer.hMailServer, so once it is merged winget install hMailServer installs the
original hMailServer, not this project. Until then, download the installer, or install it with
Chocolatey. The manifests
name the installer by its file in the project's package registry on GitLab
(build/make-package-manifests.ps1), and the winget manifests are rendered and submitted by
hand. Both installers register under the same uninstall entry, hMailServer_is1, so a
Windows machine holds one of the two (ForkAndOriginal.md). From the release after
6.3.7 the installer refuses an installation of the original's 5.7 before it changes anything
(What it checks before it shows you anything, below); the installers of 6.3.7 and earlier do not look, and must not be run over one. The Chocolatey
package passes /LOG, and Chocolatey's CLI makes setup's TEMP its cache folder, by default the
chocolatey folder in the temporary folder of the account that ran choco, so that is where the
log is, and the file with the refusal's words that setup from the release after 6.3.7 writes.
The full account is in
PackageManagers.md;
note that an unattended install through either deliberately leaves the administrator
password unset, and you must set one before the server is reachable from anywhere but the
machine itself.
Right-click the installer and choose Run as administrator. PrivilegesRequired=admin
means it will ask anyway; starting elevated avoids a second prompt.
InitializeSetup() runs first, and can refuse to start. Knowing what it looks at saves a
puzzled five minutes:
| Check | What you see when it fires | Result |
|---|---|---|
/adminpassword, or HM_ADMIN_PASSWORD (since 6.3.4), shorter than 5 characters |
"The password given with /adminpassword or HM_ADMIN_PASSWORD must be at least 5 characters long." | Setup stops |
| A window titled hMailServer Control Panel is open | "…You must close down this application before starting the installation." | Setup stops |
| A window titled hMailServer Administrator is open (a legacy version's GUI) | the same message | Setup stops |
| A window titled hMailServer Database Setup, hMailServer Database Upgrader or DBSetup is open | the same message | Setup stops |
| Ports 25, 110 or 143 already in use while the hMailServer service is not running | "…one or several of the TCP/IP ports 25, 110 and 143 are already in use. This indicates that there already is an email server running on this computer." | Warning only — setup continues, and you will have two servers fighting over port 25 |
| Windows older than build 14393, or 32-bit | "hMailServer requires Windows 10 version 1607 (build 14393) / Windows Server 2016 or later, 64-bit." | Setup stops |
From the release after 6.3.7: an installation of the original hMailServer's 5.7 - the earlier installation's hMailServer.exe before 6, and either a database past schema 5708 and before 6001, as the running service answers it, or, where the service is not running or does not answer, the original's own upgrade scripts past 5708 (Upgrade5708to5709*.sql) in its DBScripts folder, unless the settings file the installed server reads keeps the database's password as only this fork does (PasswordEncryption 6): such a database is this fork's own, and setup does not refuse it (Upgrading Guide, Where you can upgrade from) |
what it found, and that nothing has been changed; refused by the scripts, also that the database's version could not be read, and that a database at 5708 or older, or this fork's own, is upgraded once the service runs and setup is run again; a silent setup's log (/LOG) has it on a line that begins Refused:, and with or without a log it is written to hMailServer-setup-refused.txt in %TEMP%
|
Setup stops before it changes anything, with exit code 1. The installers of 6.3.7 and earlier do not look, and must not be run over one |
Every one of those dialogs is a SuppressibleMsgBox, so under /SUPPRESSMSGBOXES they take
their default button instead of waiting for a keyboard that is not there. That is deliberate:
in 6.2.19 a plain MsgBox on this path made a /VERYSILENT install wait ninety minutes in CI
for an answer nobody could give.
Screenshots on this page are from a 6.2.11-era build. The wording is current except where a caption says otherwise.
1. Licence agreement. hMailServer is AGPL-3.0-or-later. In short: you may use it freely,
including commercially; if you modify it and offer it to others over a network, you must
publish your changes. License.rtf is also copied to {app}\Bin so it is on the machine
afterwards.

The body text visible in this 6.2.11-era shot is the pre-AGPL preamble. The heading is
unchanged, but current releases show the GNU Affero General Public License v3 text beneath
it — verified in installation/License.rtf.
2. Destination folder. The default C:\Program Files\hMailServer is fine.

On a machine where hMailServer has been installed before,
OverrideInstallationFolder()readsHKLM32\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\hMailServer_is1\InstallLocationand puts that path in the box, so an upgrade returns to wherever the original install went. This is what makes an x86-to-x64 upgrade find the existing installation, which Inno does not do on its own.
3. Components. This page matters, so read it:
| Component | Internal name | Take it? | What it does |
|---|---|---|---|
| Server | server |
Yes | The mail server itself, the database tools, the add-ons, the DB scripts. Everything else is optional |
| Remote administration support | admintools |
Only if scripting from another machine | Registers the hMailServer COM type library on a machine that is not the server, so scripts and COM clients can administer a remote instance |
| Control Panel | controlpanel |
Yes | The administration application. Without it you have no GUI |

The component sizes shown are from a 6.2.11 build; the Control Panel line now reads ".NET 10 Desktop Runtime".
The Control Panel does not need "Remote administration support". It binds late, through
IDispatch, and connects to a remote host by itself. The component is only for other COM clients — your own scripts, monitoring tools — running on a machine that is not this one. Seesection_components.iss.
Note for upgraders: "Administrative tools" in older versions bundled the classic Administrator GUI and a PHP web interface. Both are gone. The component now does only what it always really did — register the COM type library.
4. Database type. Choose Use the built-in database engine unless you decided otherwise in Before You Install §3.5.

This page is skipped when [Database] Type is already set in an existing
hMailServer.ini — an upgrade never re-asks — or when the server component is not
selected (ShouldSkipPage).
5. Start menu folder. hMailServer, and you can suppress the group entirely.

6. Administrator password. hMailServer asks you to set a password for the administration interface. This is not an email password — it is the master password for the whole server. Minimum five characters, and the two boxes must match.

This page is skipped when the server component is not selected, when a password is
already present in the ini (you cannot change it here — use the Control Panel), or when one
arrived on the command line with /adminpassword or, since 6.3.4, in the environment variable
HM_ADMIN_PASSWORD. Since 6.3.4 a space, a double quote or a backslash in the password reaches
the database step as it was typed: the installer has the server store it as PBKDF2 and hands it
to the database tools in HM_ADMIN_PASSWORD, never on a command line (step 4 below).
Set one. Use a long, unique password and store it in a password manager. Anyone with it owns every mailbox on the server. And an installation with no administrator password is not merely unprotected —
COMAuthentication::AttempAnonymousAuthenticationgrants server-administrator rights to any COM caller while the value is empty, andRestApiServer::Startrefuses to start the REST API at all. Leaving it unset is the installer's safest available state, not a good one.

7. Server profile (since 6.3.4). On a new installation, the kind of server this is - below, under The setting profile page.
8. Service account (since 6.3.4). Which account the Windows service runs as. The page says which case applies (ServiceAccount.md):
| The machine | The page offers | The default |
|---|---|---|
| No hMailServer service yet - a new installation |
NT SERVICE\hMailServer, or LocalSystem as earlier versions ran it |
NT SERVICE\hMailServer |
| A service running as LocalSystem - an upgrade | keep LocalSystem, or move it to NT SERVICE\hMailServer
|
keep LocalSystem |
| A service running as any other account - an upgrade | keep that account, or move it back to LocalSystem | keep the account |
NT SERVICE\hMailServer is the service's own virtual account: no password, no account to
create, and it reaches only the folders it is granted. An upgrade never changes the account
unless this page is answered to. What the virtual account cannot do that LocalSystem could is
in §4.6 below.
9. Ready to install. This is the last page at which anything can still be stopped.

Pressing Install here does one thing before any file is touched: it stops the hMailServer service and waits for it to actually stop, with a bound. If it will not stop, setup refuses to go past this page:
The hMailServer service did not stop within 30 seconds.
Setup cannot continue: replacing the program files while the service is running
would leave the old server binary installed alongside an upgraded database, and
hMailServer would then refuse to start at all.
Stop the hMailServer service manually (services.msc), then run this installation
again.
The budget is ShutdownDrainSeconds + 30 seconds, read from the existing ini — so an
installation that deliberately holds its shutdown open to let sessions finish gets the time
it asked for. (StopHMailServerService.)
10. Install. Files are copied, then the post-install steps below run.
flowchart TD
START(["Setup starts"]) --> IS["InitializeSetup: password length, running GUIs, ports 25/110/143"]
IS -->|refused| STOP(["Setup exits"])
IS -->|ok| IW["InitializeWizard: read /useinternaldbms, OverrideInstallationFolder from HKLM32"]
IW --> SILENT{"Silent install?"}
SILENT -->|Yes| READY
SILENT -->|No| PAGES["Licence, Destination, Components"]
PAGES --> DBPAGE{"Database Type already in the INI, or server component not selected?"}
DBPAGE -->|Yes| SKIP1["Database page skipped"]
DBPAGE -->|No| ASKDB["Ask: built-in or external"]
SKIP1 --> GROUP
ASKDB --> GROUP["Start menu folder"]
GROUP --> PWPAGE{"Password already set, given by /adminpassword, or server not selected?"}
PWPAGE -->|Yes| SKIP2["Password page skipped"]
PWPAGE -->|No| ASKPW["Ask for the administrator password, minimum 5 characters"]
SKIP2 --> PROF
ASKPW --> PROF["Server profile page, a new installation only (6.3.4)"]
PROF --> SVCACC["Service account page: the virtual account or LocalSystem for a new installation, keep or move for an upgrade (6.3.4)"]
SVCACC --> READY["Ready page"]
READY --> STOPSVC{"Stop the hMailServer service. Did it reach STOPPED within ShutdownDrainSeconds plus 30?"}
STOPSVC -->|No| REFUSE["Refuse to continue. Stop it by hand and run setup again"]
STOPSVC -->|Yes| INSTALL["ssInstall: MoveIni, copy files, write INI keys, write HKLM32 InstallLocation, create folders"]
INSTALL --> POST["ssPostInstall"]
POST --> SERVERSEL{"Is the server component selected?"}
SERVERSEL -->|No| ADMINONLY{"admintools selected?"}
ADMINONLY -->|Yes| REGTLB["RegisterTypeLib only"]
ADMINONLY -->|No| DONE
SERVERSEL -->|Yes| TASKS["RunPostInstallTasks: runtime, backend, service, password, database, secure defaults, profile, stored-secrets key, account move, start"]
TASKS --> RESULT{"Every step succeeded?"}
RESULT -->|No| RAISE["RaiseException: the install FAILS with a non-zero exit code"]
RESULT -->|Yes| RUNSEC["Run section: install the .NET runtime if still missing, offer to launch the Control Panel"]
REGTLB --> DONE
RUNSEC --> DONE(["Completed"])
RunPostInstallTasks() shows a progress page and runs these in order. Each one's failure is
checked — this is the part of the installer that used to report success regardless, and no
longer does. The progress bar still counts six; 6.3.4 added the steps marked below between
them.
| # | Step | What runs | If it fails |
|---|---|---|---|
| 1 | Install the .NET 10 Desktop Runtime |
windowsdesktop-runtime-10.0-win-x64.exe /install /quiet /norestart, only when DotNetDesktopMissing() says the shared framework has no Microsoft.WindowsDesktop.App\10.* directory. Since 6.3.4 the runtime the installer carries is pinned to 10.0.12 by version and SHA-512 |
Error dialog naming the exit code, and pointing at the download page and DBSetupQuick.exe. Exit codes 0, 3010 (reboot required) and 1638 (a newer build already present) are all treated as success |
| 2 | Initialise the database backend |
msiexec /I "{tmp}\SSCERuntime_x64-ENU.msi" /quiet /norestart, only for a fresh built-in install or an upgrade already on MSSQLCE
|
Error dialog; step 4 is then skipped entirely, because the tools cannot possibly succeed without it |
| 3 | Create the hMailServer service |
hMailServer.exe --service-account <choice> /Register, then sc failure and sc description. A service to be moved to NT SERVICE\hMailServer is registered as LocalSystem here and moved after step 4; one that already runs as an account of its own is granted its folders again (/GrantServiceAccess - since 6.3.6 through a junction or mount point the administrators alone control, which up to 6.3.5 failed the upgrade; and one that cannot read the database says NOT READ and ends in 7 unless an administrator confirmed, a silent move then waiting and Setup saying what to run). Then, since 6.3.6, at every installation and upgrade and whatever account the service runs as, hMailServer.exe /ProtectFolders, before the service is granted its folders again and before the database step, so that the database it makes and the logs the service starts are made inside folders already private (the progress page says Making the program's data, log and database folders private...; on a large message store the first time takes a few minutes; the progress bar still counts six) |
Error dialog naming the exit code; step 5 is skipped. A /ProtectFolders that does not end in 0 is said in a message, with the command to run again, and in the setup log; the installation goes on, and what it could not change is as it was |
| 3a | Set the administrator password (since 6.3.4) |
hMailServer.exe --set-admin-password, with the password in the installer's environment (HM_ADMIN_PASSWORD), never on a command line; the server writes it as PBKDF2. Only when a password was collected and the file has none |
The installer says so and the install fails; the server is left with no administrator password until one is set on Administrative access |
| 4 | Create or upgrade the database |
DBSetupQuick.exe for the built-in engine or an existing configuration, DBSetup.exe when an external engine is being chosen for the first time. /silent is forwarded, and since 6.3.4 the password - or the live update's token, as token:<hex> - reaches the tool in its environment, HM_ADMIN_PASSWORD, emptied as soon as it has finished, and DBSetupQuick hands it to DBUpdater.exe the same way; until then it was password:<value> on their command lines, unquoted, and a password with a space, a double quote or backslashes before one failed this step with exit code 3 |
Error dialog naming the exit code, and the install fails |
| 4a | Secure a new installation (since 6.3.4) |
hMailServer.exe --apply-new-install-defaults, on a database this installation created: a self-signed certificate, STARTTLS on 25, 587, 110 and 143, and TLS required for authentication on the Internet IP range (SecureDefaults.md) |
Said in a message box, and logged - except an exit 5 after DBSetup.exe, a database it attached rather than created, which is only logged; the installation succeeds either way, and the setup checklist says what is left |
| 4b | Apply the chosen profile (since 6.3.4) |
hMailServer.exe --apply-profile NAME --once --if-new --confirm (below) |
Said, naming the profile as not applied; the installation succeeds with the shipped settings |
| 4c | Make the stored-secrets key (since 6.3.4) |
hMailServer.exe --create-stored-secrets-key, on a new installation only; a message then asks you to export it (§4.6) |
Said, with the command to run by hand; the installation succeeds, and each account's second factor and the secret settings are kept as written until a key is made |
| 4d | Move the service to NT SERVICE\hMailServer (since 6.3.4)
|
When the service account page chose it: hMailServer.exe /GrantServiceAccess (with --confirm in an attended installation), and only when that ends in 0, --service-account virtual /Register
|
The service stays on LocalSystem, working, and the installer says why; the installation succeeds |
| 5 | Start the service |
net START hMailServer, then the verdict is taken from the SCM, not from net.exe
|
"The hMailServer service was installed but did not start." — check hMailServer.log and the ERROR log |
| 6 | Completed | — | — |
What a running service does and does not prove.
ServiceMainreportsSERVICE_RUNNINGbefore it connects to the database, so step 5 succeeding means the process started — not that the schema is usable. The schema is covered by step 4's exit code, which is why that one fails the install.
Open Services (services.msc) and find hMailServer. It should say Running,
startup type Automatic, logging on as NT SERVICE\hMailServer on a new 6.3.4
installation that kept the page's default, and as Local System on an upgrade that kept
its account or an installation from before 6.3.4.

The Log On As column in this 6.2.11-era shot is LocalSystem's; a new 6.3.4 installation
shows NT SERVICE\hMailServer.
The Description column is blank in this 6.2.11-era shot. Current installers set it — see the
sc description call in ConfigureServiceRecovery() — so a fresh install reads "hMailServer
email server - SMTP, POP3 and IMAP."
Or from PowerShell:
Get-Service hMailServerStatus Name DisplayName
------ ---- -----------
Running hMailServer hMailServer
Check the recovery configuration too — this is set by the installer, not by the service itself, and it is the difference between a mail server that comes back after a crash and one that stays down until somebody notices:
sc.exe qfailure hMailServerSERVICE_NAME: hMailServer
RESET_PERIOD (in seconds) : 86400
FAILURE_ACTIONS : RESTART -- Delay = 60000 milliseconds.
RESTART -- Delay = 120000 milliseconds.
RESTART -- Delay = 300000 milliseconds.
Three restarts, escalating 1 → 2 → 5 minutes, with the counter cleared after a day without a failure. Deliberately not unbounded: a server that fails four times inside a day has a problem restarting will not fix, and by then the SCM has recorded four failures for whoever looks.
The installer does not open firewall ports for you. Until you do, nothing can reach your server. Run this in an elevated PowerShell:
New-NetFirewallRule -DisplayName "hMailServer SMTP" -Direction Inbound -Protocol TCP -LocalPort 25 -Action Allow
New-NetFirewallRule -DisplayName "hMailServer Submission" -Direction Inbound -Protocol TCP -LocalPort 587 -Action Allow
New-NetFirewallRule -DisplayName "hMailServer IMAP" -Direction Inbound -Protocol TCP -LocalPort 143 -Action Allow
New-NetFirewallRule -DisplayName "hMailServer IMAPS" -Direction Inbound -Protocol TCP -LocalPort 993 -Action Allow
New-NetFirewallRule -DisplayName "hMailServer POP3" -Direction Inbound -Protocol TCP -LocalPort 110 -Action Allow
New-NetFirewallRule -DisplayName "hMailServer POP3S" -Direction Inbound -Protocol TCP -LocalPort 995 -Action AllowYour router or cloud firewall needs the same ports forwarded to this machine.
993 and 995 are in that list because you will want them, but a fresh install only listens on 25, 587, 110 and 143 — those four are the rows seeded into
hm_tcpipportsby the create script. Add the TLS ports on Connections & protocols → TCP/IP ports; see Encryption and Certificates.
The installer is Inno Setup, so the standard switches apply. Four are this installer's own, and one is used by the server's own update helper.
| Switch | Meaning | Notes |
|---|---|---|
/SILENT |
No wizard, but a progress window | |
/VERYSILENT |
Nothing on screen | |
/SUPPRESSMSGBOXES |
Dialogs take their default button | Use it with /VERYSILENT, always. Without it a failure waits for a keypress forever |
/LOG="<path>" |
Write a setup log | Use it. It is the only record of what happened |
/DIR="<path>" |
Destination folder | On a machine with a previous install, OverrideInstallationFolder() puts the recorded InstallLocation into the directory box during InitializeWizard, so an upgrade goes back to the original folder |
/COMPONENTS="…" |
Comma-separated: server, admintools, controlpanel
|
Omit to get the full installation |
/useinternaldbms=true|false |
true (the default) uses the bundled SQL Server Compact database; false when pointing at an existing MySQL, MariaDB, PostgreSQL or MS SQL server |
Read in InitializeWizard
|
/adminpassword=<password> |
Sets the administrator password the wizard page would have asked for | At least five characters, or setup refuses to start. Without it, and without HM_ADMIN_PASSWORD, the key is left out of the ini entirely. Inno Setup drops every double quote from its command line, anybody listing processes can read the switch while setup runs, and with /LOG the setup log records setup's command line, the switch with it |
HM_ADMIN_PASSWORD (an environment variable, since 6.3.4)
|
The same password, read when neither /adminpassword nor /upgradetoken is given |
Carries a double quote, which /adminpassword cannot, and is on no command line. Set it in an elevated prompt: setup started without administrator rights elevates itself through the UAC prompt, and the variable does not cross it |
/upgradetoken=<token> |
The single-use token the server issues to its own update helper, handed to the database tool as its credential (token:<token> in HM_ADMIN_PASSWORD since 6.3.4; password:token:<token> on its command line before) |
Not something you pass by hand. It is never written to the ini |
/profile=<name> |
Since 6.3.4. The setting profile a new installation starts in: office, gateway, relay, sender, or none for the shipped settings (below) |
Ignored on an upgrade and on a database that is already in service. A profile that could not be applied is said in the log, and the installation still succeeds with the shipped settings |
/serviceaccount=virtual|localsystem|keep |
Since 6.3.4. The account the service runs as, the service account page's answer | Without it, a new installation gets NT SERVICE\hMailServer and an upgrade keeps what it has. A silent move leaves the service on LocalSystem when the configuration names a folder or key file outside the folders it may grant, since nobody is there to approve it. Anything else is ignored, and said in the log |
In an elevated prompt, with the password in HM_ADMIN_PASSWORD rather than on the command line, which the setup log records:
set HM_ADMIN_PASSWORD=<password>
hMailServer-6.3.4-x64.exe /VERYSILENT /SUPPRESSMSGBOXES /LOG="C:\Temp\hmail-install.log" ^
/COMPONENTS="server,controlpanel" /useinternaldbms=true
if errorlevel 1 (
echo Install FAILED - see C:\Temp\hmail-install.log
exit /b 1
)Always check the exit code. The installer checks that the database tool ran and its exit code, and raises on failure, so a failed database create or upgrade cannot report a successful install. The tools' own codes, which end up in the log:
| Tool | Code | Meaning |
|---|---|---|
DBSetupQuick.exe |
0 |
Database created, or already present and up to date |
1 |
The create failed, or DBUpdater.exe could not be started |
|
3 |
Authentication failed — the administrator password was wrong or missing | |
| other | Whatever DBUpdater.exe returned, forwarded unchanged |
|
DBUpdater.exe |
0 |
Upgraded, or already at the required schema version |
1 |
The upgrade failed, or the window was closed before it finished | |
2 |
Configuration error — settings could not be loaded, or no upgrade path exists between the two schema versions | |
3 |
Authentication cancelled or refused |
Why the password has to be forwarded on the upgrade path too.
DBUpdatermust authenticate before it can move the schema. Until 6.2.23,DBSetupQuickforwarded only/silent— so a silent upgrade had no password, fell through to a modal dialog nobody was there to answer, and hung the install indefinitely. Both paths forward it now, and the sharedAuthenticatorfails rather than prompting under/silent, so the worst case is a reported exit code instead of a wait with no end. Since 6.3.4 it goes in the tools' environment,HM_ADMIN_PASSWORD, not on their command lines, so the password arrives as it was typed.
On a new installation only - one with no database yet - the last page
before the installation offers the four setting profiles, one sentence each, with
None chosen until another is: office (a small office's own mail server), gateway
(behind a filtering gateway), relay (an outbound relay that holds no mailbox) and
sender (a high-volume sender). The sentence names the listener, the filter or the trust
the profile changes, and choosing it is the confirmation. After the database step the
installer stops the service the database tools started and runs
hMailServer.exe --apply-profile NAME --once --if-new --confirm before starting it again;
--if-new leaves alone a database that already holds ten accounts or more. Every failure is
said, naming the profile as not applied, and the installation succeeds with the shipped
settings. The same four profiles, each with its difference from this server shown first, are on the
Control Panel's Setting profiles page and in the Control Deck's checklist.
Profiles and Environment has what each one sets.
The server judges its own first hour: a profile, a domain, an account, TLS on the submission
port, passwords only over TLS, SPF, DKIM, DMARC, a backup destination, a second factor for
the administrator, the service account and the stored-secrets key, each done, action needed or cannot tell with a sentence saying what
it found. It is the Control Deck's Checklist view, the head of the Control Panel's
External setup page and its dashboard's "needs attention" card, GET /api/v1/setup/checklist
and COM's Utilities.GetSetupChecklist. Beside it, a button on the Deck's checklist and on
the Control Panel's Welcome page makes a throwaway sample domain, example.test, with
three mailboxes, a list, a rule and some delivered mail to learn on, and a second button
removes it again (Your First Domain and Mailbox).
Worth knowing, because it is what you back up, and what you edit when something needs to change outside the Control Panel.
{app}\Bin\hMailServer.INI — the only configuration file. Everything else lives in the
database. Since 6.3.4, the database is also the store for
the [Settings] keys from schema 6042; the file keeps [Directories], [Database],
[Security] and [GUILanguages] - everything the installer writes - and the server writes
each stored setting into a [Settings] section as a copy, adds a two-key [SettingsStore]
note saying so, and keeps PasswordPepper there, if one is set, as the one setting the
database never holds, and from 6.3.6 the live update's trust, which is read from the file
alone. Under NT SERVICE\hMailServer the file is read-only to the
service: it works on with the database's values, says in the application log at a
reinitialise, where application logging is on, that the copy is not refreshed, and
refuses with a sentence what would write the file - a change of the
administrator password over COM among them, which is then made with
hMailServer.exe /SetAdministratorPassword from an elevated prompt
(ServiceAccount.md). The file also holds
[Security] StoredSecretsKey once the installation has a stored-secrets key, sealed under
the machine's DPAPI.
[Directories]
ProgramFolder=C:\Program Files\hMailServer
DatabaseFolder=C:\Program Files\hMailServer\Database
DataFolder=C:\Program Files\hMailServer\Data
LogFolder=C:\Program Files\hMailServer\Logs
TempFolder=C:\Program Files\hMailServer\Temp
EventFolder=C:\Program Files\hMailServer\Events
[GUILanguages]
ValidLanguages=english,swedish
[Security]
AdministratorPassword=$h1$<iterations>$<salt-hex>$<key-hex>
StoredSecretsKey=<sealed with DPAPI>
[Database]
Type=MSSQLCE
Database=hMailServer
Server=
Username=
Password=<encrypted>
PasswordEncryption=6
Port=0
Internal=1| Key | Written by | Preserved on upgrade? |
|---|---|---|
[Directories] ProgramFolder |
[INI] in section_ini.iss
|
Overwritten every time — it must match where you just installed |
[Directories] DatabaseFolder, DataFolder, LogFolder, TempFolder, EventFolder
|
[INI], flag createkeyifdoesntexist
|
Preserved. A data folder you moved stays moved |
[GUILanguages] ValidLanguages |
[INI] |
Overwritten |
[Security] AdministratorPassword |
hMailServer.exe --set-admin-password, as PBKDF2 (since 6.3.4; up to 6.3.3 the [INI] section wrote an MD5 digest, guarded by Check: HasAdministratorPassword) |
Preserved, and only written at all when a password was actually collected and the file has none |
[Security] StoredSecretsKey |
hMailServer.exe --create-stored-secrets-key, on a new installation (since 6.3.4) |
Preserved; an upgrade makes none |
[Database] * |
DBSetup / DBSetupQuick through the COM API, not by the [INI] section |
Preserved |
Every [Settings] key in the Settings Reference
|
You, by hand, or the Control Panel - on 6.3.3 and earlier. Since 6.3.4: stored in the database through the Control Panel, REST, hmctl or COM, and copied into the file by the server where it may write the file - not under NT SERVICE\hMailServer, above; a hand edit to a key the database holds is not used at the next start (HM5804), and is put back where the service may write the file |
The installer never touches them |
Writing nothing when no password was collected is load-bearing. Before the
HasAdministratorPasswordguard (6.3.3 and earlier) and the--set-admin-passwordstep (6.3.4), an installation that never collected a password — every silent install, because the password page only exists in the interactive wizard — wroted41d8cd98f00b204e9800998ecf8427einto the ini: the MD5 of the empty string. That is not "no password set"; it is a valid entry the server authenticates an empty password against, becauseCrypt::GetHashTypetreats any 32-character value as MD5. It also silently disabled the two protections that key off an unset password. Leaving the key out is the safer state, and it is the one the rest of the product is written for.
Up to 6.3.3 the installer stored the password as an unsalted MD5 digest
(GetMD5OfString), which nothing re-hashed. 6.3.4's installer has the server write it as
PBKDF2, which looks like $h1$<iterations>$<salt-hex>$<key-hex>, and a 6.3.4 server writes
an older MD5 or SHA-256 value again as PBKDF2 at the first successful administrator
sign-in - the Control Panel, COM, REST, hmctl or the Control Deck - where the service can
write the file; under NT SERVICE\hMailServer it cannot, keeps the old value and says so
once (HM7494), and hMailServer.exe --set-admin-password from an elevated prompt rewrites
it (SecretsAtRest.md).
The stored-secrets key. A new 6.3.4 installation makes one (step 4c) and says so: each
account's TOTP second factor and the [Settings] secrets (SRSSecret, BATVSecret,
OAuth2HmacSecret and the rest) are sealed under it in the database with AES-256-GCM. The
key exists in this machine's hMailServer.INI alone, never in the database or a backup, so
export it and keep the file with the database backups, stored apart from them:
# elevated, in the Bin folder
.\hMailServer.exe --export-stored-secrets-key D:\keys\hmailserver-stored-secrets.keyA database restored without it opens none of those secrets. An upgrade makes no key and
seals nothing until an administrator runs --create-stored-secrets-key, which the setup
checklist offers; ProtectStoredSecretsWithDPAPI=0 keeps everything as written.
Registry. One value, in the 32-bit view, and that is not a mistake:
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\hMailServer
InstallLocation = C:\Program Files\hMailServer
Registry::GetStringValue opens the key with KEY_WOW64_32KEY, so the 64-bit server reads
the 32-bit view; writing to the 64-bit view would make the lookup fail on every machine. It
is declared in section_registry.iss rather than written from code so that the uninstaller
removes it, and so that it exists before the service is first started.
Service.
| Property | Value | Set by |
|---|---|---|
| Name / display name | hMailServer |
hMailServer.exe /Register |
| Binary | "…\Bin\hMailServer.exe" RunAsService |
ServiceManager::RegisterService |
| Start type | Automatic | the same |
| Dependencies | RPCSS |
the same |
| Log on as |
NT SERVICE\hMailServer for a new 6.3.4 installation, LocalSystem when the page chose it; an upgrade keeps what it had. /Register takes the account from --service-account alone: ServiceAccountName and ServiceAccountPassword are no longer read (since 6.3.4) |
the same, with --service-account
|
| Recovery | restart after 60 s, 120 s, 300 s; counter reset after 86400 s |
sc.exe failure, from ConfigureServiceRecovery()
|
| Description | "hMailServer email server - SMTP, POP3 and IMAP." |
sc.exe description, from the same function |
Files that are never overwritten and never uninstalled. These carry the
onlyifdoesntexist uninsneveruninstall flags, so an upgrade cannot clobber your edits and an
uninstall cannot delete them:
-
{app}\Events\EventHandlers.vbsand the rest of{app}\Events - everything under
{app}\Addons -
%WINDIR%\System32\atl70.dll, on a machine an installer before 6.3.4 wrote it to (shared with other products; hMailServer neither downgrades nor removes it). 6.3.4 no longer ships it: nothing on a v145 build links it.
What NT SERVICE\hMailServer is granted (since 6.3.4): Modify on the program
folder's own Data, Logs, Temp and Database, Read on its other folders, Modify on
Bin\hMailServerApiKeys.ini, nothing on hMailServer.INI, and a folder the configuration
names elsewhere - a data or backup folder, a certificate folder - only once an administrator
approves it (hMailServer.exe --confirm /GrantServiceAccess, or the Control Panel's
Windows service account card under Server limits & expert settings). What only
LocalSystem could do is refused with a sentence: the live update's apply (since 6.3.6 Install
update in the Control Panel on the server installs it with one Windows prompt; on 6.3.4 and
6.3.5 an administrator installed the verified installer from the release page), the auto-ban's
Windows Firewall rules (AutoBanFirewall, HM7460) and Utilities.MakeDependent. SQL Server
reached with integrated authentication on the same machine needs a login for
NT SERVICE\hMailServer before the move: since 6.3.6 a new installation's installer makes it
(hMailServer.exe --grant-database-login - a login, a database user and db_owner on a SQL
Server on this computer; none on another computer, and none in a database with DDL triggers of
its own), and where it cannot, on a database Setup has just created, the service stays on
LocalSystem, the message gives the four statements and the sqlcmd line, and Setup exits
10; every moved service is then held to opening its database as the virtual account, and
moved back with exit 10 or 11 if it cannot (The Service Account, Its login on SQL
Server). The Service Account has the whole table, and how to move back.
Since 6.3.6, whatever account the service runs as, the program folder's own Data, Logs,
Temp, Database and Events and Bin\hMailServer.INI are private: SYSTEM and the
Administrators with full control; the service with what its grant gave it - Modify on the four
data folders, Read on Events - where it runs as anything but LocalSystem; and the service's
Read on hMailServer.INI under every account. Up to 6.3.5 they kept what Program Files hands
down, BUILTIN\Users' Read among it (Security Hardening §17.3, Who else on the computer
may read the mail). The grant also goes through a link the administrators alone control -
owned by BUILTIN\Administrators, SYSTEM or TrustedInstaller, and nobody else may change
it or remove it - the path it holds held from that volume's root, every link on it asked about,
on a fixed local drive; the grant is written on the folder the link leads to; any other link is
still refused, the message naming who may change it or who owns it (icacls <link> /setowner *S-1-5-32-544 /L and icacls <link> /inheritance:r /grant:r *S-1-5-32-544:(F) *S-1-5-18:(F) *S-1-5-32-545:(RX) /L give a link to the administrators alone).
Since 6.3.7 the program's own folders too: /ProtectFolders hardens the program folder,
Bin and ControlPanel at every installation and upgrade - SYSTEM and the Administrators with
full control, BUILTIN\Users with Read & execute where every user could read them before,
nothing inherited, and the Administrators as the owner of one somebody else owned. Up to 6.3.6
they took their permissions from the folder they are in, which under Program Files lets only
SYSTEM, the Administrators and TrustedInstaller change them, but at the root of a drive let any
account that could sign in to the computer replace the programs the service runs. Setup also
gives a program folder it makes those permissions before it copies anything into it, and says,
without refusing it, when the folder chosen lets every user change what is in it. To have an
installation at a drive's root hardened before an upgrade runs anything from it, follow
The Service Account, Before upgrading an installation at a drive's root, first
(Upgrading hMailServer 18.4f).
A new installation, since 6.3.6. One whose database step did not complete leaves the mark
NewInstallationPending (and NewInstallationProfile) under
HKEY_LOCAL_MACHINE\SOFTWARE\hMailServer; Setup run again, or DBSetup.exe (its wizard, or
/unattended run elevated), finishes it as a new installation - secure defaults, profile,
stored-secrets key, the move to the virtual account. One whose administrator cannot open the
database gets its secure defaults from the service itself, started with sc start hMailServer --apply-new-install-defaults (Setup and DBSetup do it) before its listeners start, and its
stored-secrets key when the service runs as LocalSystem, which may write hMailServer.ini;
HM7498 (the key), HM7510 and HM7511 (the defaults) name what it could not do, and the
setup checklist shows the outcome. Both installers take an external database on the command
line (/dbtype=, /dbhost=, /dbport=, /dbname=, /dbuser=, /dbpasswordfile=,
/createdatabase=, /dbservice=) or in HM_DB_*; the ARM64 installer refuses a silent new
installation given no database (this path has not been run against a server by a pipeline; the
smoke test's --database run is made by hand). An older database named with
/createdatabase=0 is no longer reported as "too old" while it is upgraded, and
DBSetupQuick.exe exits 4 when it cannot reach the service, having changed nothing.
sequenceDiagram
autonumber
participant U as You
participant S as Setup
participant SCM as Service Control Manager
participant Q as DBSetupQuick.exe
participant D as DBUpdater.exe
U->>S: Run the new installer
S->>S: OverrideInstallationFolder reads HKLM32 InstallLocation
S->>S: GetCurrentDatabaseType reads the existing INI, so the DB page is skipped
S->>S: An existing AdministratorPassword skips the password page
U->>S: Install
S->>SCM: Stop hMailServer, then poll until STOPPED
SCM-->>S: STOPPED, or the wait expires and setup refuses to continue
S->>S: Copy files, preserving Events, Addons and the INI keys marked createkeyifdoesntexist
S->>Q: DBSetupQuick.exe /silent, the password in HM_ADMIN_PASSWORD
Q->>Q: Database.DatabaseExists is true, so this is an upgrade
Q->>D: DBUpdater.exe /SilentIfOk /silent, the password in HM_ADMIN_PASSWORD
D->>D: Compare CurrentVersion with RequiredVersion, 6104 for 6.3.4
D-->>Q: 0 up to date or upgraded, 1 failed, 2 no upgrade path, 3 auth refused
Q-->>S: the same code, forwarded
S->>SCM: net START hMailServer
SCM-->>S: RUNNING, checked through the SCM rather than net.exe's exit code
Three things follow from that picture:
- The database is upgraded before the service starts, and after the binaries are replaced. That ordering is why setup refuses to proceed when the service will not stop: the old binary left in place against a new schema makes the server refuse to start at all ("The database is too new for this version of hMailServer").
-
The schema version for 6.3.4 is 6104 (6040 for 6.3.3, 64 steps before it).
DBUpdatercomparesDatabase.CurrentVersionwithDatabase.RequiredVersionand exits0immediately when they match, so re-running the installer over an up-to-date installation costs nothing. -
Back up first. See Backup and Restore and Upgrading hMailServer for the full
procedure; nothing on this page replaces taking a copy of
Data\,Database\andBin\hMailServer.INIbefore you start.
Since 6.3.4, four things change around this picture. The
service drains before it stops - the SMTP, IMAP, POP3 and ManageSieve listeners are
closed at the socket and the queue paused, so senders retry rather than being cut off - and
ShutdownDrainSeconds (30 is a reasonable figure) lets what is in flight finish. And a new
bootstrap key, [Database] UpgradeOnStart=1, lets the service itself apply the schema
chain as it starts, for an installation whose binaries are replaced by something other than
this installer; it is off by default, backs nothing up first, and belongs on one node at a
time. Upgrading hMailServer has both. An upgrade keeps the service's account and its
settings: the service account page defaults to the account the service has, the secure
defaults are never applied to an upgraded database, and no stored-secrets key is made. And
6.3.4 is installed by hand on every server: it carries no Sigstore bundle, so no
server's live update installs it.
| What you see | What it means | What to do |
|---|---|---|
| "The hMailServer service did not stop within N seconds" | The old service is wedged or the stop failed | Stop it in services.msc, or net stop hMailServer, then run setup again. Do not work around this |
| "The hMailServer COM API could not be registered (… returned -1)" |
RegisterAppId or RegisterServer failed |
From an elevated prompt in {app}\Bin: hMailServer.exe /RegisterTypeLib
|
| "The hMailServer service could not be created (… returned -1)" |
CreateService or ChangeServiceConfig failed |
Check the hMailServer error log, then hMailServer.exe /Register from an elevated prompt in {app}\Bin
|
| "The SQL Server Compact 4.0 runtime installation failed (msiexec returned N)" | The bundled MSI would not install | Install SSCERuntime_x64-ENU.msi by hand, then run DBSetupQuick.exe
|
| "The hMailServer database could not be created or upgraded (exit code N)" | Step 4 failed; N is from the table in §4.5 |
Fix the cause, then DBSetupQuick.exe from {app}\Bin
|
| "The hMailServer service was installed but did not start" | The process would not come up | Read Logs\hmailserver_*.log and the ERROR log, then net start hMailServer
|
| "A post-installation step failed: …" | An exception escaped RunPostInstallTasks
|
The program files are installed. Finish by hand from {app}\Bin: hMailServer.exe /Register, then DBSetup.exe, then start the service |
Setup finishes but Get-Service hMailServer says nothing |
The server component was not selected |
Re-run setup and tick it |
ssPostInstall is past the point at which Inno can roll anything back, which is why these
messages tell you what to run rather than offering to retry.
Use Apps & features, or the Installation → Uninstall hMailServer start-menu shortcut.
The order matters and is set in section_uninstallrun.iss and CurUninstallStepChanged:
- the service is stopped and its process waited for before anything is removed (since
6.3.4: a
net stopalone returned about a second before the process ended, and lefthMailServer.exeand its DLLs inBin; a file still in use is now removed at the next restart), thennet.exe STOP hMailServeras before -
net.exe STOP hMailServerMySQL— for a very old installation that bundled MySQL -
hMailServer.exe /Unregister— removes the service and unregisters COM, and since 6.3.4 the event log source; each entry runs once, so an uninstall after an upgrade no longer leaves the COM AppID behind - three more entries for hMailServer 3- and 4-era files, all flagged
skipifdoesntexist
The stop comes first for a reason:
/UnregistercallsDeleteService, which on a running service only marks it for deletion and leaves the process alive — so the uninstaller then began deleting{app}withhMailServer.exeholding its own files open, and COM was unregistered from under a live server.
What is left behind, on purpose: {app}\Data, {app}\Events, {app}\Addons and
Bin\hMailServer.INI. Your mail and your configuration are not deleted by an uninstall.
Remove them by hand only when you are certain.
Next: The Control Panel, then Your First Domain and Mailbox.
hMailServer 6.3.7, the latest release (17 October 2026, schema 6108) · AGPL-3.0-or-later · Repository · Mirror on GitHub · Report a documentation error (a GitLab issue naming the page)
Home — full index
Start here
1. Install and run
- Before You Install
- Installing hMailServer
- Installing on Linux
- Running in a Container
- Profiles and Environment
- The Control Panel
- The Control Deck
- Your First Domain and Mailbox
- Connecting a Mail Client
- The Webmail
- DNS for Your Domain
- Migration
2. Secure it
- Encryption and Certificates
- Database TLS
- Encryption for People
- Stopping Spam
- Stopping Viruses
- Security Hardening
- Secure Defaults
- The Service Account
- Secrets at Rest
- Sign-in and Identity
- Security Policy
3. Operate it
- Monitoring and Health
- The SNMP Agent
- Backup and Restore
- Message Storage
- Compliance and eDiscovery
- Troubleshooting
- Diagnosing Stalled Mail
- Relocating an Installation
- Upgrading hMailServer
- Upgrading Guide
- The Update Feed
- Migrating the Database Backend
- High Availability Runbook
- Warm Standby
- Runbooks Digest
4. Extend it
- Rules and Sieve
- Aliases Lists and Public Folders
- Rooms and Equipment
- Mailing Lists
- Routes and Relays
- Mail In to a Webhook
- Outbound Shaping
- The COM API and Scripting
- Event Scripts
- The REST API
- Command Line
- APIs Reference
5. Contribute to it
- Project Handbook
- Architecture
- Contributing
- Release Process
- Governance
- Assurance Case
- Regression Test Environment
- Fuzzing
- Regulatory Scope
- Third-Party Binaries
Look it up — from any journey
- Settings Reference
- Settings Overview
- Capabilities and Configuration
- Control Panel Reference
- Control Panel Pages
- Ports Reference
- Changes-Since-6210
- Version-History-to-6210
- Glossary
About this wiki
- hMailServer 6.3.7 is the latest release (17 October 2026, schema 6108)
- Pages say since 6.3.4 where a feature is new in it
- AGPL-3.0-or-later
- Repository, the one place the project is worked on
- Its mirror on GitHub, since 18 October 2026, with no Issues
- Questions: a GitLab issue with the Question template, GitHub Discussions Q&A, or the forum
- Report a documentation error: a GitLab issue naming the page