Skip to content

Troubleshooting

chrisholloway5 edited this page Sep 8, 2026 · 2 revisions

Troubleshooting

This page began as a chapter of the 6.2.10 manual and has been corrected and extended for 6.2.28. 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-6210. Where a value here disagrees with the Settings Reference, which is generated from the code, the reference is right.

19.1 Start here, always

Three pages, in this order. Most problems are named outright by the first one.

  1. Monitoring & troubleshooting → Diagnostics — the built-in self-test. Nine checks: server details, IPv6, outbound port 25, the backup directory, MX lookup, connecting to your own MX, message file locations, IP ranges, and whether any error log exists. Monitoring and Health §16.8 says what each one actually does and what makes it fail.
  2. Monitoring & troubleshooting → Live logs — watch what happens as you reproduce the problem. Turn debug messages on first if the answer is not obvious, and off again afterwards.
  3. Monitoring & troubleshooting → Delivery queue — is mail stuck, and what does the NextTry and Tries pair say about it?

The first sixty seconds, from PowerShell on the server:

# Is the service running, and has it been restarted recently?
Get-Service hMailServer | Format-List Name, Status, StartType
Get-Process hMailServer -ErrorAction SilentlyContinue | Select-Object StartTime

# Is anything actually listening on the mail ports?
Get-NetTCPConnection -State Listen |
  Where-Object LocalPort -in 25,110,143,465,587,993,995,8080,9100 |
  Sort-Object LocalPort | Format-Table LocalPort, LocalAddress, OwningProcess

# Has the server written an error log today? Its existence is itself a diagnostic.
Get-ChildItem "C:\Program Files\hMailServer\Logs\ERROR_*.log" |
  Sort-Object LastWriteTime -Descending | Select-Object -First 3 Name, Length, LastWriteTime

# The last 40 errors, whatever they were.
Get-Content (Get-ChildItem "C:\Program Files\hMailServer\Logs\ERROR_*.log" |
  Sort-Object LastWriteTime -Descending | Select-Object -First 1).FullName -Tail 40

If you have the metrics listener on (see Monitoring and Health §16.3), one more line answers "is this server healthy at all":

Invoke-RestMethod http://127.0.0.1:9100/healthz

Which of these problems do you have?

flowchart TD
    A["Something is wrong"] --> B{"Is the service running?"}
    B -->|"no"| B1["Read the ERROR log for today. A refused start is nearly always the database, or a port already in use"]
    B -->|"yes"| C{"Can a client connect at all?"}
    C -->|"no"| C1["19.5 for the Control Panel, 19.6 for mail clients. Firewall, ports, TLS"]
    C -->|"yes"| D{"Which direction is broken?"}
    D -->|"inbound"| E{"Does the sender get an SMTP error, or a timeout?"}
    D -->|"outbound"| F{"Does the message reach the queue?"}
    D -->|"delivered but wrong"| G["19.4 for spam folders, and check Mail flow and delivery, Rules"]
    E -->|"an error"| E1["19.7 - the reply code names the cause"]
    E -->|"a timeout"| E2["Diagnosing Stalled Mail, accepting half"]
    E -->|"nothing at all"| E3["19.2 - it is not reaching you"]
    F -->|"no"| F1["19.3 - relaying, authentication or the client's port"]
    F -->|"yes, and stays"| F2["Diagnosing Stalled Mail, delivering half"]
Loading

19.2 "I can't receive mail from outside"

Work through in order. Each row eliminates one link in the chain, cheapest first.

Check How What a failure means
Is the service running? Get-Service hMailServer Start it, then read the error log for why it stopped
Is anything listening on 25? Get-NetTCPConnection -LocalPort 25 -State Listen The port is not configured, is bound to one address only, or another program has it. Connections & protocols → TCP/IP ports
Is port 25 open on Windows Firewall? Get-NetFirewallRule -Enabled True | Where-Object DisplayName -like "*hMail*" Add a rule (below)
Does the local machine answer on 25? Test-NetConnection 127.0.0.1 -Port 25 If this fails, it is the server, not the network
Is port 25 forwarded by your router or cloud firewall? Your firewall's own configuration The far end sees a connection refused or a timeout
Does your ISP block port 25? Ask them Very common on consumer lines. You will need a relay host or a business line
Is your MX record right? Monitoring & troubleshooting → MX query, or Resolve-DnsName example.com -Type MX Fix DNS. See DNS for Your Domain
Can the world reach you? From outside your network: Test-NetConnection mail.example.com -Port 25 Everything before this passed, so it is the path in
Is the domain in hMailServer and Active? Accounts & domains → Domains An inactive domain is not accepted for
Is the mailbox Active, and is it full? The account dialog A full mailbox gets a temporary failure, and the sender retries; the account holder gets a quota warning first

Opening the firewall, once, for the ports a fresh install seeds:

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 POP3"       -Direction Inbound -Protocol TCP -LocalPort 110 -Action Allow
New-NetFirewallRule -DisplayName "hMailServer IMAP"       -Direction Inbound -Protocol TCP -LocalPort 143 -Action Allow

Add 465, 993 and 995 only if you have created those ports — a fresh install does not seed them. Ports Reference lists them all.

Watch a delivery arrive. Nothing beats seeing the conversation:

$log = "C:\Program Files\hMailServer\Logs\hmailserver_" + (Get-Date -Format "yyyy-MM-dd") + ".log"
Get-Content $log -Tail 0 -Wait | Select-String "SMTPD|SMTPConnection"

19.3 "I can't send mail"

Symptom Likely cause What to do
Client says relay denied, or the server says 550 Delivery is not allowed to this address. The client is not authenticating, or is using port 25 instead of 587 Set the client to port 587 with authentication. If a device genuinely cannot authenticate (a printer, a scanner), give its IP its own range under Access & abuse protection → IP ranges
530 SMTP authentication is required. Same cause, said earlier in the conversation As above
530 Must issue STARTTLS first. The port requires TLS before authentication Turn on STARTTLS or SSL/TLS in the client
535 Authentication failed. Wrong password, wrong user name form (use the full address), or the account is inactive Try the same credentials in the Control Panel's account dialog; check Access & abuse protection → Auto-ban has not banned the client
535 Authentication failed. Too many invalid logon attempts. Auto-ban has stepped in. Default: 3 failures, banned for 60 minutes Access & abuse protection → IP ranges lists the expiring ban; delete it to release the client early
550 Too many recipients. More than maxsmtprecipientsinbatch (100) in one transaction Split the batch, or raise the limit
552 5.3.4 Message size exceeds fixed maximum message size. Size: N KB, Max size: M KB Above the server or domain maximum message size (default 20480 KB) Mail flow & delivery → Delivery of e-mail, or the domain dialog
452 4.3.1 Insufficient system storage. Free space on the message store's volume is below MinimumFreeDiskSpaceMB (100 MB) Free space. This is temporary, so senders retry rather than bounce. The application log warns below DiskSpaceWarningThresholdMB (1024 MB) before it starts refusing
Mail sits in the queue Outbound port 25 blocked, or DNS resolution failing Diagnosing Stalled Mail. A relay host is configured under Mail flow & delivery → Delivery of e-mail
Remote server rejects you Missing PTR, missing SPF, or your IP is blacklisted §19.4
Mail leaves but arrives hours late You are being greylisted, and every first delivery to that destination waits Normal. QuickRetries shortens the first few retries — see Diagnosing Stalled Mail

19.4 "My mail goes to spam"

Almost always DNS. In order of impact:

  1. PTR record — ask your ISP or cloud provider. A missing or generic PTR is the single biggest cause, and no amount of other configuration compensates for it.
  2. SPF — publish it, and make sure it lists the address you actually send from.
  3. DKIM — generate the key on the domain's DKIM tab and publish the TXT record. Accounts & domains → Domains, then the domain's DKIM tab, shows you the exact record to publish.
  4. DMARC — publish it, even as p=none. Without it, SPF and DKIM tell receivers nothing about what to do when a check fails.
  5. Blacklists — check your IP at mxtoolbox. New IP addresses sometimes arrive pre-tainted from a previous tenant; most lists have a delisting form.
  6. Test ithttps://www.mail-tester.com. Fix everything it flags, then send again from a real mailbox rather than from a script.

Check what you have published, from the server itself, using the same resolver the server uses:

Resolve-DnsName example.com -Type MX
Resolve-DnsName example.com -Type TXT | Where-Object Strings -match "v=spf1"
Resolve-DnsName _dmarc.example.com -Type TXT
Resolve-DnsName selector1._domainkey.example.com -Type TXT
Resolve-DnsName 203.0.113.25 -Type PTR         # your public address, reversed by the resolver

If those look right from the server but wrong from outside, you have split-horizon DNS, and the outside view is the one that matters.

19.5 "The Control Panel won't connect"

Check Notes
Is the service running? The Control Panel talks to the running service over COM. No service, no connection
Right password? The administration password, not a mailbox password
Just restarted the service? The Control Panel reconnects itself; give it a few seconds
Connecting remotely? The COM API must be reachable and DCOM permitted. The [Database] and [Directories] sections of hMailServer.INI are readable only from the server machine, deliberately, so a few settings pages are read-only remotely
Two-factor enrolled on the administrator? The Control Panel asks for the code after the password. If you have lost the authenticator, see Security Hardening
The window opens but every page says "Server unavailable" The service is running but the engine is paused. Server status has Pause/Resume — Pause stops the engine while leaving the Windows service up

19.6 "A mail client can't connect, or can't log in"

Symptom Cause Fix
Connection refused on 993 or 995 Those ports do not exist on a fresh install Create them on Connections & protocols → TCP/IP ports, then restart the service
Connection accepted, then nothing The client is speaking implicit TLS to a STARTTLS port, or the reverse Match the port's connection security to the client's
Certificate warnings in the client The certificate's name does not match the host name the client typed, or the chain is incomplete TLS & certificates → SSL certificates; serve the full chain, not just the leaf
Logs in on IMAP but not SMTP The submission port does not have authentication enabled, or the client is set to "no authentication for outgoing" Client settings first; then the port and Access & abuse protection → Authentication
Worked yesterday, fails today, for one user Auto-ban, an expired password (PasswordPolicyMaximumAgeDays), or an app password that was revoked Access & abuse protection → IP ranges and the account's App passwords tab
Works from inside, not from outside Firewall or port forwarding, not hMailServer §19.2
An IMAP client resynchronises everything after a restore Expunge records and IMAP metadata are not carried by a backup Expected. See Backup and Restore §15.3

19.7 What the server said, and what it means

The reply code is the fastest diagnosis available, because it is chosen by the code that made the decision. A 4xx is temporary and the sender will retry; a 5xx is permanent and the sender will bounce.

Reply Meaning Usual cause
421 4.4.2 Connection timeout. The session was idle too long A client that opened a connection and went away
421 4.7.0 Too many invalid commands. Bye! The session was disconnected for misbehaving A scanner, or a badly broken client
451 4.3.1 Server temporarily overloaded while accepting the message; please retry. The accept pipeline exceeded FinalizationTimeout Something in the pipeline is slow — Diagnosing Stalled Mail
451 4.3.2 Unable to verify the recipient at the moment. Please retry later. The database did not answer the recipient lookup The server can tell "the database is down" from "no such address", so mail is deferred rather than bounced. Check /readyz and the database
451 4.3.2 The server is shutting down and cannot accept the message. A graceful stop is in progress Expected during a restart with ShutdownDrainSeconds set
452 4.3.1 Insufficient system storage. Free space below MinimumFreeDiskSpaceMB Free space on the message store's volume
452 4.2.2 Mailbox is full. The recipient is already at or over quota. Refused during the conversation, not bounced afterwards, so the failure goes back to the machine that connected The account or domain size limit. The account holder gets a QUOTA_WARNING message before this happens
530 SMTP authentication is required. Relaying without authentication Use port 587 and authenticate
530 Must issue STARTTLS first. The port requires TLS before anything else Enable TLS in the client
535 Authentication failed. Bad credentials Full email address as the user name
535 Authentication failed. Too many invalid logon attempts. Auto-ban §19.3
550 Delivery is not allowed to this address. The IP range this client falls in does not permit this relay direction Access & abuse protection → IP ranges
550 Unknown user No such mailbox, alias or list Check spelling, and whether a catch-all was expected
550 Too many recipients. Over maxsmtprecipientsinbatch Split the batch
553/554 from a remote server in your log The far end rejected you Their message text is the diagnosis — usually SPF, DKIM, PTR or a blacklist

The complete list of what this server can say is in the SMTP log for the session; the codes above are the ones an administrator meets.

19.8 "Database too old" / "Authentication failed" after install

Both were real defects in 6.2.4 and are fixed in 6.2.5 and later. If you see either on a fresh install, you are running an old build — upgrade to the current release.

A genuine schema mismatch on a later build looks different, and is deliberate: the server refuses to start when the database schema is not the one this build requires, in both directions. A half-upgraded pair fails safe and loudly rather than corrupting anything. Run the installer, which runs the database upgrade; see Upgrading hMailServer.

19.9 The server will not start

Read ERROR_hmailserver_<date>.log first; the reason is almost always in it.

What the log says Cause Fix
A database connection error The database server is down, moved, or the credentials changed [Database] in hMailServer.INI. The password there is DPAPI-protected per machine, so it cannot be copied from another server (Backup and Restore §15.8)
The schema version does not match The binaries and the database disagree Run the installer to upgrade the schema, or reinstall the matching build
A port could not be bound Something else has it — IIS on 25 or 443, another mail server, a leftover instance Get-NetTCPConnection -LocalPort 25 -State Listen, then look up the owning process
MetricsServer: Invalid bind address MetricsServerBindAddress is not an IP literal It must be 0.0.0.0, 127.0.0.1, :: or a specific address — never a host name. The server still starts; the metrics listener does not
Nothing at all, and the service stops immediately The service account cannot read the install directory or write the logs Check the service account's rights on Bin, Data, Logs and Database

The same failures in the order the server meets them. Two things in this picture explain most of the confusing reports: the service tells Windows it is running before any of it happens, and a listener that cannot start takes down only its own port.

flowchart TD
    SCM["ServiceMain reports SERVICE_RUNNING to the SCM<br/>BEFORE anything below runs - which is why a start<br/>that fails leaves a service Windows calls Running,<br/>with nothing listening on any port"] --> INI["Settings read from hMailServer.INI alone.<br/>This is how the server finds the database at all"]
    INI --> DBT{"Is [Database] Type<br/>one it recognises?"}
    DBT -- no --> X0["Start abandoned. There is nothing<br/>to connect to and nothing is logged<br/>about a database that was never named"]
    DBT -- yes --> CHK{"Do the [Database]<br/>settings check out?"}
    CHK -- no --> X1["HM5005 Medium:<br/>Loading of ini file settings failed"]
    CHK -- yes --> CONN{"Connections opened?"}
    CONN -- no --> X2["HM4354 Critical: hMailServer failed<br/>to connect to the database server"]
    CONN -- yes --> VER{"Schema version, against the<br/>one this build requires"}
    VER -- "cannot be read" --> X3["HM5010 Critical: Database<br/>version could not be detected"]
    VER -- older --> X4["HM5011 Critical:<br/>run DBUpdater.exe"]
    VER -- newer --> X5["HM5011 Critical:<br/>upgrade hMailServer"]
    VER -- equal --> RELOAD["Settings read a SECOND time, now with<br/>the hm_inisettings overlay on top"]
    RELOAD --> CFG{"Configuration loads<br/>from the database?"}
    CFG -- no --> X6["Start abandoned"]
    CFG -- yes --> SS["StartServers: session queues, io_service, scheduler,<br/>delivery manager, external fetch, message indexer"]
    SS --> EACH["One listener per row on TCP/IP ports"]
    EACH --> PROTO{"Is that row's protocol enabled on<br/>Connections and protocols, Protocols, Services?"}
    PROTO -- no --> SKIP["Skipped in silence. No error, no listener -<br/>the commonest reason for nothing on 143"]
    PROTO -- yes --> ACC{"open, bind, listen"}
    ACC -- refused --> X7["HM4316 High: Failed to bind to local port,<br/>often caused by another server listening on<br/>the same port. That port only - the rest still come up"]
    ACC -- ok --> LIVE["Accepting connections"]
    SS --> SIDE["The optional listeners, each only when its own port<br/>setting is non-zero: metrics, REST API, web services,<br/>ManageSieve. A bind address that is not an IP literal<br/>logs Invalid bind address and that one alone stays down"]
Loading

Everything above the StartServers box is fatal to the whole server, and every one of those exits but the first writes the code shown to the ERROR log; everything below it costs one listener and goes to the application log. That is why "the service is running and nothing is on port 25" and "the service will not start" are different problems with different logs (Common/Application/Application.cpp InitInstance/StartServers, hMailServer/hMailServer.cpp ServiceMain, Common/TCPIP/IOService.cpp DoWork, Common/TCPIP/TCPServer.cpp InitAcceptor).

19.10 Where the files are

C:\Program Files\hMailServer\
├── Bin\
│   ├── hMailServer.exe            the service
│   ├── hMailServer.INI            configuration - [Database], [Directories], [Settings]
│   └── ...
├── Data\                          the message store
│   ├── example.com\               one directory per domain
│   │   └── user\                  one per account, then the folder tree
│   ├── ACME\                      automatic certificates: fullchain.pem, privkey.pem
│   └── Sieve\                     per-account Sieve scripts and their state
│       └── example.com\user\active.sieve
├── Database\
│   └── hMailServer.sdf            the built-in database, when you use it
├── Logs\
│   ├── hmailserver_<date>.log
│   ├── ERROR_hmailserver_<date>.log
│   ├── hmailserver_backup.log
│   ├── hmailserver_events.log
│   └── hMailServer_messagestore_consistency.report
└── Temp\
What Default location Overridden by
Program C:\Program Files\hMailServer\Bin The installer
Configuration C:\Program Files\hMailServer\Bin\hMailServer.INI
Messages C:\Program Files\hMailServer\Data [Directories] DataFolder
Logs C:\Program Files\hMailServer\Logs [Directories] LogFolder
Temp C:\Program Files\hMailServer\Temp [Directories] TempFolder
Built-in database C:\Program Files\hMailServer\Database
ACME certificates <data directory>\ACME AcmeCertificateDirectory
Sieve scripts <data directory>\Sieve\<domain>\<local part>\

The [Directories] and [Database] sections are per machine and are never mirrored into the database. Do not copy another server's hMailServer.INI over this one's. The [Settings] section is mirrored, and is reconciled at every start — see Warm Standby.

19.11 Things that look like faults and are not

Observation Why it is normal
The first message from a new sender is delayed a few minutes Greylisting. It is doing its job
hmailserver_processed_messages_total is larger than the number of messages received It counts delivery passes, and a deferred message is passed again (Monitoring and Health §16.4)
/readyz connection refused while the service starts The metrics listener is started only once the server is Running
A queued message shows a next-try time of 1901-01-01 An ETRN hold, waiting for the far end to ask for its mail
Counters reset to zero The service restarted. hmailserver_start_time_seconds says when
hmailserver_messagestore_missing_files is always 0 The consistency check is off by default (MessageStoreConsistencyCheck=0)
The backup log says "Verified restore skipped" Either BackupVerifyRestore=0, or the temp volume could not hold a second copy of the store. The line says which

19.12 Getting help

When reporting a problem, include:

  1. Your exact versionMonitoring & troubleshooting → Server status, or hmailserver_build_info on the metrics endpoint.
  2. Which database backend you use, and its schema version (the Server status page shows both).
  3. The relevant log extract, with passwords removed: the SMTP or IMAP conversation, plus the same window from ERROR_hmailserver_<date>.log.
  4. What you have already checked from this page, and what the Diagnostics page said.
  5. Whether the message eventually arrives, arrives twice, or never arrives.

The project's own guidance is in SUPPORT.md.

19.13 Verified against the code

Checked 8 September 2026 against hMailServer 6.2.28. The SMTP replies in §19.3 and §19.7 are the literal strings in SMTPConnection.cpp (SendErrorResponse_ and SendResponse_), with 550 Delivery is not allowed to this address. coming from the IP-range relay check in ProtocolMAIL_, 452 4.3.1 from the free-space guard on MAIL, and 451 4.3.2 Unable to verify the recipient from the two DatabaseUnavailableMarker::Scope blocks in ProtocolRCPT_. The auto-ban defaults (AutoBanOnLogonFailureEnabled 1, MaxInvalidLogonAttempts 3, AutoBanMinutes 60), maxsmtprecipientsinbatch 100 and maxmessagesize 20480 KB are the seeded values in the create scripts; MinimumFreeDiskSpaceMB 100 and DiskSpaceWarningThresholdMB 1024 are IniFileSettings::LoadSettings, and the two log lines they produce are DiskSpace::ReportBand_. The nine self-tests are Diagnostic::PerformTests. The log file names are Logger::GetCurrentLogFileName; the data-directory layout is PersistentMessage, SieveStorage::GetAccountDirectory_ and AcmeClient::GetCertificateDirectory. The Windows service is registered as hMailServer in hMailServer.cpp. The schema pin that refuses to start on a mismatch is REQUIRED_DB_VERSION in Constants.h, enforced by Application::OnDatabaseConnected. MetricsServer: Invalid bind address is MetricsServer::Start. The Control Panel's Pause/Resume, and the fact that [Database] and [Directories] are not exposed over COM, are StatusView and IniFeatureStore in the Control Panel sources.


Clone this wiki locally