Skip to content
hMailServer 6.3.3 — signed 15 September 2026, Windows and Linux, database schema 6040, and a drop-in upgrade from any 5.x install.Download 6.3.3 Documentation
  • 0 Votes
    1 Posts
    7 Views
    P
    Every message over 60,000 bytes sent to a server advertising CHUNKING has stalled since outbound BDAT arrived in 6.2.25. Every release from 6.2.25 to 6.3.2 is affected. If your smart host or the destination offers CHUNKING, large mail has been failing, and OutboundChunking=0 is the workaround on any of them. 6.3.3 fixes it (issue #261). The SMTP client armed the read for the reply as soon as the BDAT command, or with PIPELINING the envelope, had been queued, and the chunk's second 60,000-byte buffer was queued behind that read in the operation queue, which starts only the operation at its head. The read could not complete while the remote waited for the bytes behind it, so nothing sent them, and the remote gave up on its own timeout. iCloud returned 421 after five minutes in the report. DATA never met it, because its body streams only after the 354. The queue now runs once more after a read has started. If you cannot upgrade yet, OutboundChunking=0 in hMailServer.ini is the workaround. Before you upgrade Two schema changes, both upgrade in place. Schema 6039 widens a domain's relay-password column: it held 255 characters and a DPAPI envelope is 314, so a relay password could not be saved on any Windows installation. Schema 6040 adds the CardDAV tables. On PostgreSQL the escaper doubled backslashes unconditionally, which is correct only while standard_conforming_strings is off, and that has been on by default since PostgreSQL 9.1. DKIM key-file paths, signatures, vacation messages and rules were stored doubled. Values already stored that way stay as they are. Edit and save them once. Also in this release The four [Settings] ini routes over REST answered to any api key. A read-only key could read the OAuth2 HMAC secret, the password pepper and the service account password, and a write key could set AutoBanCommand, which the firewall reconciliation runs as the service. They take the administrator password only now. A domain-scoped key is refused the eleven administrator-only fields on PUT /api/v1/domains/{domain} with 403. CardDAV (RFC 6352) for the account's address book, one book named Contacts, vCard 3.0 and 4.0, HTTP Basic over HTTPS only. The web services HTTPS listener has to be on (WebServicesHttpsPort). The webmail is rebuilt: inbox tabs, mute, pinning as $Pinned, follow-up dates as $FollowUp and $Due-YYYY-MM-DD, fourteen more search operators, twenty languages. The full-text indexer no longer reports an error for a message deleted before its terms were saved. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    A SURBL lookup that failed was being read as a hit. The Spamhaus zones answer a query they refuse with a code in 127.255.255.0/24, and until now any answer at all counted as a listing. A server resolving through a public resolver such as 8.8.8.8, or sending too many queries, tagged every message carrying a link as spam (discussion #167). What the upgrade involved The database goes to schema 6038: steps 6032 to 6037 add contacts, account preferences, scheduled sends and snoozes, files sent as links, message keywords and S/MIME keys, and 6038 the SURBL expected result. 6.3.1 listed the 6029 to 6030 upgrade step as known and unfixed: on a database holding orphaned rows it could re-orphan rows it had already cleaned, then refuse its own foreign keys. It is fixed in all four backends. Changes Each SURBL server now has an expected result (SURBLServer.ExpectedResult, in the Control Panel's SURBL editor) in DNSBL syntax: 127.0.1.0-255, 127.0.0.2*, ranges and wildcards. With none set, any answer counts except the codes in 127.255.255.0/24. The debug log records what the zone answered and what was made of it. The portal at /portal is now a mail client, over /api/v1/me and the account's own credentials. Conversations by thread, search operators (from:, subject:, has:attachment, is:unread, label:), labels stored as IMAP keywords so every IMAP client sees them, undo send for up to thirty seconds, send later and snooze held on the server, oversize attachments sent as expiring links from /files/{token}, read receipts (RFC 8098) and one-click unsubscribe (RFC 8058). S/MIME runs in the browser on the Web Crypto API, the private key wrapped under a key derived from the account password. Not in this release: 3DES content, EC key agreement for encryption, legacy PKCS#12 encryption, OpenPGP. SASL GSSAPI (RFC 4752) on SMTP, IMAP and POP3, on Windows. Off unless GssapiEnabled=1 in [Settings]. Auto-ban can reach the firewall. AutoBanFirewall=1 writes an inbound block rule per banned address in Windows Defender Firewall, or keeps an nftables set on Linux. AutoBanCommand and AutoBanNeverBan go with it. All three are off as shipped. Making an app password now takes the account's own password, and an app password is never accepted for it. The 6.3.1 .deb depended on the builder's exact Boost sonames and would not install on Ubuntu 26.04. Boost is linked statically now. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    If you run hMailServer on SQL Server Compact, the 6.2.25 installer told you the database could not be upgraded. It had been upgraded. Every Compact Edition upgrade through schema 6030 was reported as failed after it had succeeded (#114), and two seconds later the service ended and service recovery started it again. What the upgrade involved If the 6.2.25 installer failed on your database, that database is at schema 6030 with its foreign keys in place, and this installer finds nothing left to upgrade. If you restored a backup from before the attempt, the whole chain runs and the verification passes. From 6.2.24 or earlier, the 6.2.25 notes and the 6.2.24 notes before them describe what changes on the way, and everything there still applies. What was wrong After each upgrade script the database updater proves the schema changed by running a probe statement, and reads a failed probe as a missing object. The four probes for schema 6030, the foreign keys, used case when exists (subquery) in the SET expression. That is valid on SQL Server, MySQL and PostgreSQL. On SQL Server Compact it is an access violation inside the OLE DB provider, on a correct database with every constraint present. The server reported HM10045 Unknown error, the updater declared that Upgrade6029to6030MSSQLCE.sql had not created fk_hm_accounts_domain and blamed an [IGNORE-ERRORS] marker the statement does not carry. The fix The probes now read update hm_dbversion set value = value / (value - value) where not exists (select 1 from information_schema.table_constraints where constraint_name = '...' and constraint_type = 'FOREIGN KEY'). With the constraint present no row matches and nothing is evaluated. With it absent the one row matches and the division by zero fails the statement on every backend, leaving hm_dbversion untouched. The updater's message no longer asserts a cause it cannot see. It gives the backend's own words and says how to read them. This was reproduced from a Compact Edition database created at schema 6011 and upgraded with the shipped scripts: it reaches 6030 with all seventeen foreign keys, and the probe then faults the provider. build/check-db-scripts.ps1 now runs every probe through the provider the server uses, with a negative control that must fail, and a regression fixture runs them through the same COM path the updater takes. Both fail on the 6.2.25 statement. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    ACME issuance and renewal ended the hMailServer process (#93). Anyone running automatic certificates on 6.2.24 lost the service on every issuance and every renewal. Two calls in the ACME client handed the OpenSSL DLL a FILE* opened by the server's own C runtime: the DANE TLSA line logged straight after issuance, and the re-read of the existing private key at the start of every renewal (the default, AcmeReuseKey). With no OPENSSL_Applink export in the executable, OpenSSL does not return an error. It writes OPENSSL_Uplink(...): no OPENSSL_Applink to the Windows Application log under the source "OpenSSL" and calls TerminateProcess. The symptoms: an OpenSSL event whose message looks blank, a 7031 from the service control manager in the same second, no crash dump, and no "ACME (automatic)" certificate record. Both calls now go through OpenSSL's own file I/O, and the deployment runs before the TLSA line. If 6.2.24 issued you a certificate before it died, the files under Data\ACME are valid. 6.2.25 deploys them at its first ACME check after start-up and logs "issued but never deployed". What the upgrade involved The schema moves from 6025 to 6030 in five steps, one way. DBUpdater runs them in order and resumes from a partial upgrade; there is no downgrade. The 6029 to 6030 step adds seventeen FOREIGN KEY constraints with ON DELETE CASCADE and removes the orphan rows they would refuse. On a large database it reads every child table once, so plan for it like an index build. If you are on 6.2.21 or a 6.2.22/6.2.23 pre-release, read the 6.2.24 notes first. Everything there still applies. Behaviour that changes without a switch The Apple .mobileconfig profile is served over HTTPS only. Plain HTTP gets a 301 to the WebServicesHttpsPort listener, or a 403 when none is configured. A TLS-terminating proxy must send X-Forwarded-Proto: https. A Message-ID is added only to submissions (upstream #552). Relayed mail keeps its headers, so a filter counting on the header will now see messages without one. IMAP sequence numbers are stable within a session (upstream #602). Another session's expunge no longer renumbers a client's messages under it. Also fixed: two restarts at once, one over COM and one from an ACME deployment or backup restore, rebuilt the same queues under each other and could end in an access violation. Restarts now run in sequence. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    3 Views
    P
    This was an alpha. Everything in it shipped in 6.2.24. Nothing here should be installed today. Local delivery could lose a message with no trace. When the account-level copy could not be written, LocalDelivery reported HM5209 and returned, but the recipient row was deleted anyway and the queued message with it. The sender had already been given 250 and the recipient never heard of it. Anyone running a message store near full was exposed. The sender is now told. This is an alpha. Do not put it on a production mail server. What the upgrade involved The schema moves 6022 to 6025 in three registered steps, and it is one way. An older server refuses to run against a newer dbversion, so rollback needs a pre-upgrade database backup and a data-directory backup. The 6024 to 6025 step widens hm_messages.messageflags from tinyint to smallint on MS SQL, SQL CE and MySQL/MariaDB. That is a table rewrite on your largest table, holding locks throughout. Size the maintenance window to your hm_messages row count. PostgreSQL is unaffected. Silent upgrades with /VERYSILENT previously hung forever on a modal password dialog. Fixed. Five COM properties added during the 6.2.22 pre-releases were declared mid-interface, shifting the vtable on AntiSpam, Account, Application and GlobalObjects. They are appended now, restoring binary compatibility with 6.2.21. Late-bound scripts were never affected. Recompile anything early-bound against a 6.2.22 pre-release. Three new defaults change behaviour. MinimumFreeDiskSpaceMB=100 refuses new mail below the floor, 452 4.3.1 at MAIL FROM and NO [UNAVAILABLE] at IMAP APPEND. WindowsEventLogEnabled=1 forwards errors to the Windows Application log under the source hMailServer. DatabaseStatementTimeout=30 is untested on MySQL and PostgreSQL, the two backends it was built for. Existing per-account out-of-office replies now apply RFC 3834 suppression and stop answering bounces, list traffic and anything carrying Auto-Submitted or List-* headers. Also in this release PROXY protocol v1/v2 and XCLIENT in front of SMTP, so DNSBL, SPF, greylisting and auto-ban see the real client. Both ship off with empty trust lists. Shared and delegated IMAP mailboxes at #[email protected], gated on RFC 4314 ACLs. On by default, enableimapacl ships as 1. RFC 3030 BINARYMIME. Relay of a binary message is refused 554 5.6.3 rather than converted. RFC 3464 bounces. Every NDR is now multipart/report. Re-check anything parsing whole bounce bodies. External HTTP filtering hook (FilterHookUrl, FilterHookTimeoutSeconds default 10), plain HTTP only. Sender blacklist, per-account spam thresholds, distribution-list moderation, domain-wide out-of-office, IPv6 on the REST and metrics listeners. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    Inbound mail from a Postfix-based relay could hang forever. The connection logs 354 OK, send., stops dead, and the sender eventually gives up with "timed out while sending end of data", leaving a zero-byte file in the Data folder. Anyone taking mail from Postfix or a Proxmox Mail Gateway was affected, and a same-host relay hits it almost every time. Three previous releases claimed to fix it and did not. This one was settled by running a real Postfix 3.10 against the server and reading the bytes on the wire. What the upgrade involved Two known issues stand. Equal-preference MX records are not randomised (RFC 5321 5.1); the server always tries them in the order the resolver returned, and a comment and COM help string that claimed otherwise have been corrected. One-click unsubscribe (RFC 8058) is not implemented. RFC 2369 List-* headers are still emitted for distribution-list postings. Changes Postfix pipelines the terminating dot and QUIT into one segment, so the terminator sits mid-buffer and every tail-only end-of-data check missed it. The receive path now searches for <CRLF>.<CRLF> anywhere in what arrived and returns the remainder to the command parser. Bare-LF terminators are still recognised only at the very end of the buffer, with anything behind them discarded, which is the CVE-2023-51764 rule. SMTP dot transparency (RFC 5321 4.5.2) now carries line-start context across buffer boundaries in both directions. Previously a line-leading dot landing a byte or two into a chunk went unstuffed, silently truncating messages. Sieve scripts were left behind by domain and account renames and deletes. Recreating an address could reactivate the previous holder's filter, redirects included. Renames now move the Sieve tree, deletes remove it, and the Control Panel writes the script only after the save succeeds. Sieve body test (RFC 5173) implemented and advertised over ManageSieve, with :text, :content and :raw. SORT () US-ASCII ALL spun a connection thread at 100% of a core forever. Empty sort criteria are now rejected per RFC 5256. The 512 MB message-list cache never evicted and only counted upwards. Eviction now measures entries as they are. Malformed DNS answers are retried once over TCP. The Control Panel MX tool (#29) now uses the server's resolver via Utilities.ResolveMXRecords. Control Panel: seven Administrator functions restored, plus Welcome page icon alignment (#30). Everything in the 6.2.20 notes is in this release too. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    6.2.20 fixes a fresh-install failure introduced in 6.2.19. Database creation failed on a new install, and the installer then hung instead of reporting the failure. Fresh installations of 6.2.19 on the built-in database, which is the default, were affected, and most likely fresh installations onto MySQL. What the upgrade involved Upgrades of an existing installation were never affected. Upgrades run the upgrade scripts, and those were clean, and existing servers already have their databases. Only fresh installs hit this. If an unattended 6.2.19 install is still sitting there doing nothing, it is waiting on a message box. What was wrong The SQL script runner splits a script into commands on blank lines. SQL Server Compact, the embedded database a fresh install uses, executes one statement per command and refuses a batch. A recent change added settings to the create scripts with a single newline between inserts, so three statements arrived as one command. Full SQL Server accepts that batch, so the development database and the 1,490-test regression suite saw nothing wrong. The same adjacency was in the MySQL and PostgreSQL create scripts. All three are fixed, and a mechanical sweep of all 199 SQL scripts confirms no multi-statement command remains in any create script or any SQL CE script. Five upgrade scripts from the 5.x era keep their batches for the full-server backends that accept them. The error raised a plain message box, and /VERYSILENT /SUPPRESSMSGBOXES suppresses only the suppressible kind. A silent install did not report the failure, it waited on a dialog with nobody at the keyboard. In CI that was ninety minutes until a person cancelled it. All 28 dialogs in the installer now take their default button under /SUPPRESSMSGBOXES, and the installer proceeds to an exit code a deployment script can read. Interactive installs see exactly the dialogs they always saw. Also in this release IMAP THREAD (RFC 5256), both algorithms, THREAD=ORDEREDSUBJECT and THREAD=REFERENCES, with real References-chain threading. It is bounded by the same per-command ceilings as SEARCH and SORT. An adversarial review found and fixed a stack overflow reachable through a deep reply chain, an uninterruptible header pass and a malformed-Date sort inversion. The installer smoke test now bounds the silent-install step at ten minutes, keeps the installer's own log, and on a database failure re-runs the setup tool and prints its stderr. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    Fresh installations of this build failed. Database creation broke on the built-in SQL Server Compact backend, which is the default, and most likely on MySQL, and a silent install then hung on a hidden message box instead of reporting the failure. Upgrades of existing installations were unaffected. 6.2.20 fixed both. For anyone already running it: if a custom DNS server was configured, every DNS lookup hMailServer made had been failing since 6.2.16. This release fixed that. Installations with no custom DNS server were never affected, because the server list is only built when one is set. 6.2.16 moved name resolution onto the asynchronous DnsQueryEx and gave the custom-DNS-server entry a destination port of 53. A DNS_ADDR carries a full SOCKADDR, so setting the port looks correct. It is not: the DNS client supplies the port itself, and with port 53 every query returns status 87 and no records. MX lookups for outbound delivery, DNSBL, SPF and SURBL all failed. It surfaced loudest as HM5507 The IP address for SpamAssassin could not be resolved, which is how #25 came in. A regression test now points DNSServer at TEST-NET-1 (192.0.2.1) and requires the lookup to time out; a timeout proves a packet left the machine. What the upgrade involved The database schema moves from 6005 to 6011. DBUpdater applies it. Take a backup first. Settings are preserved. The [Settings] INI values move into the database for remote administration; the file still wins where both carry a value. Also in this release Active Directory can now create accounts, not just link them. Settings.PreviewDirectorySync and Settings.ApplyDirectorySync read an LDAP directory and create or update the mailboxes it says should exist, with a Control Panel page and an optional unattended schedule. A domain takes part only if its Active Directory domain name is set, so provisioning is opt-in per domain. Nothing is ever deleted. Sieve imap4flags now reaches the message. setflag, addflag, removeflag and the :flags tag were parsed and evaluated, then discarded at delivery. They are now applied to the stored message, and imap4flags has moved into the ManageSieve capability line. Only the five system flags can be stored; a keyword is logged rather than dropped in silence. GetUniqueMessageID could hand out the same UID twice, which makes a client show one message in place of another. An account address containing a colon accepted mail at RCPT TO, then failed when the message was filed: the local part becomes a directory name in the message store. Known issue: #26, partial FETCH BODY[]<offset.length> against 6.2.18, does not reproduce here against new tests that reassemble whole messages from chunks over FETCH and UID FETCH. If you can still reproduce it, post an IMAP protocol log. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    A recipient lookup that failed because the database did not answer returned 550, exactly as a lookup that found nothing did. The two cases were indistinguishable inside the server, so a database briefly locked by a backup told the sending server that a valid mailbox did not exist and the mail was bounced instead of retried. That is mail loss with a delivery receipt. Anyone running against a database that stalls under backup, maintenance or load was affected. Those lookups now return 451. What the upgrade involved DBConnectionAcquireTimeout now defaults to 60 seconds rather than 0. It shipped disabled in 6.2.17 precisely because timing out an acquisition turned a slow database into a bounce. The 451 fix is what made it safe to turn on, but the pool deadline is live after this upgrade, so check the value if you set it explicitly. Bounded waits (#23, #24) Outbound delivery sessions get an absolute ceiling, ClientSessionCeiling, 30 minutes, separate from the idle timeout. The idle timeout re-arms on every byte received, so a peer dribbling one byte at a time held a delivery thread indefinitely. ClamAV on the delivery path (#23) is bounded and reports a timeout rather than holding the thread. DNS queries, event scripts and external scanner processes (#24) are bounded by DNSQueryTimeout (10s), ScriptTimeout (60s) and ExternalProcessTimeout (300s). Work queue saturation is reported on a schedule and names the task holding each thread, with its session and peer IP. Pre-authentication IMAP command buffering is capped at 11 MB. An unauthenticated peer could previously buffer without limit. Backup restore validates the source archive before deleting the target. It deleted first, so a corrupt archive destroyed the data it was restoring over. Other A first static analysis pass fixed a buffer overrun on long paths in GetExecutableName and two MySQL path helpers, and a shadowed fileExists in Logger::WriteLogFile that made rotation test an uninitialised value. A correction to the roadmap: ARC sealing is narrower than previously described. Arc::Seal sits after every early return in DKIMSigner::Sign, so relayed third-party mail is never sealed. Discussion #18 is fixed and bounded, but not yet confirmed against the original reporter's Postfix/PMG setup. If you are affected, the per-stage timings in the troubleshooting guide will name the culprit in one log line. Please post it on the discussion. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    3 Views
    P
    If your server accepts inbound mail from a trusted relay, a Proxmox/Postfix front end for example, and you run SpamAssassin, messages could stall after end-of-data and never get a 250. Reception was never the problem. The stall was in the accept/save work that runs after the terminating dot and before the reply. What the upgrade involved No database change. Schema version stays at 6005. The same audit found other unbounded waits, not fixed here: synchronous DNS lookups in the spam tests have no application-level timeout, the database connection pool has no acquisition deadline, event scripts have no execution limit, and the ClamAV read/write timeout on delivery is ineffective. Why it only ever hit relayed mail For a trusted incoming relay, hMailServer defers the whole spam battery to after end-of-data. For a direct or authenticated sender those tests run earlier, during MAIL FROM/RCPT TO, on the connection thread. The post-DATA work runs on a bounded pool, 15 threads by default, and holds the thread that sends the 250. SpamAssassin's wait had no overall ceiling: the connection's idle timeout is re-armed on every byte received, so a scanner that stalls or dribbles holds the thread indefinitely. Against a blackholed SpamAssassin endpoint, one message was acknowledged after 120 s. Eighteen concurrent messages produced zero acknowledgements: 15 workers blocked, the rest with no worker at all. The fixes SpamAssassin's wait is bounded. Hard ceiling of SAMaxTimeout + 30 s, after which the message is accepted without a verdict, the same outcome as spamd being down. New FinalizationTimeout, default 240 s, inside Postfix's 600 s data-done timeout, 0 disables it. Acceptance past that answers 451 4.3.1 and the sender retries. The check runs on the accepting thread and only before anything is saved, so it cannot duplicate mail. Acceptance is timed per stage and each spam test timed individually. A slow stage is logged at APPLICATION level, not only under debug: Spam test: SpamTestSpamAssassin, Score: 0, Time: 120031 ms. Upgrading is enough to turn silent stalls into either a completed delivery or a clean 451 retry. Enable debug logging and the per-stage timings name the scanner, DNS lookup or event script responsible. Also in this release: regression coverage for clients that vanish mid-operation (aborted DATA, truncated BDAT, IMAP APPEND literals cut short, POP3 disconnects during RETR), plus an installer smoke test on a clean machine. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    3 Views
    P
    The Control Panel raised an error dialog every time you dismissed the Ctrl+K settings palette (#21, reported by grumpymojo). It was present in both 6.2.14 and 6.2.15, and because choosing a result and pressing Esc both went through the same path, it appeared on essentially every search rather than on any particular search term or configuration. What the upgrade involved No server change and no database change. Schema version stays at 6005. Anyone coming from 6.2.14 or earlier should read the 6.2.15 notes as well, because everything in them applies here. Fixed Closing the palette moves the focus away, which raised the deactivation handler while the close was still in progress, and that handler closed the window a second time. WPF refuses that outright: System.InvalidOperationException: Cannot set Visibility to Visible or call Show, ShowDialog, Close, or WindowInteropHelper.EnsureHandle while a Window is closing. The deactivation handler now closes the palette only when a close is not already under way. Nothing was lost to this defect. The navigation had already happened by the time the dialog appeared, so no setting was misapplied. It was noise in the one feature added to make settings easier to find. Still open at this release Discussion #18, the stall after 354 when relaying from Postfix or Proxmox Mail Gateway, remained open and unreproduced. 6.2.15 added debug logging to the SMTP DATA path that distinguishes the three candidate stages, and that log is what will identify the cause. Tracked in #20. Validated by the full regression suite: 1040 of 1040 passing, zero failures. The download is hMailServer-6.2.16-x64.exe. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    The IMAP sequence-set parsers only recognised * as the end of a range. Anywhere else it was parsed as zero, so UID STORE *:* +FLAGS (\Deleted) flagged every message in the mailbox, UID EXPUNGE * deleted every \Deleted message, and FETCH * returned nothing while answering OK. Any client using * outside a range was affected. What the upgrade involved No database change. The schema stays at version 6005. Issue #18 is not fixed and remains open, see #20. All four sequence-set parsers now resolve * on either side of a colon and normalise descending ranges, so 3:1 is the same set as 1:3, per RFC 3501. Twelve regression tests cover it, all twelve failing against 6.2.14. Also fixed: Restoring messages emptied the live data directory before checking the backup's message store existed. A settings-only backup restored with the messages option ticked, or a failed extraction, left an empty data directory and the only copy of the mail in a GUID-named temporary folder. It now checks first. A message whose file could not be read hung the outbound connection after the remote answered 354, idle until the client timeout of up to ten minutes, then re-queued and repeated. It now fails immediately. Only a genuinely missing file fails the delivery permanently. BDAT exact-length reads padded short chunks with NUL bytes. A sender announcing BDAT 100000 LAST that vanished after 40,000 octets had the truncated message delivered as complete. DKIM signing hashed the header name in lower case while writing it capitalised (upstream PR #530), so signatures using simple canonicalization failed strict verifiers. Several paths left files with no database row: rejected POP3 RETR, header rewrites leaving .eml.tmp, downloads with no local recipient, unsendable bounces. The account cache had no size cap. ManageSieve now disconnects after three failed authentication attempts and registers them with auto-ban. STATUS (RECENT) reported the selected folder's count for every folder. Settings configurable only in hMailServer.ini gained Control Panel pages: authentication, administrative access, DNS resolver, web services and autoconfiguration, and the consistency scan results. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    7 Views
    P
    A message file that could not be written was treated as success. IMAP APPEND answered OK [APPENDUID ...] for messages that were never stored, so Sent Items copies, drafts and migration uploads were lost while the client showed them saved. Anyone hitting a full volume, or a file locked by antivirus or backup, lost mail silently. A failed message copy killed the delivery task in local delivery, forwarding, Sieve redirect and mirroring, leaving the message locked in the queue to fail again on every restart. Both came from an adversarial audit that found and fixed 21 defects. No database change: schema version 6005, unchanged. The regression suite passed 1026 of 1026. Mail loss and stability Every string SQL parameter on MS SQL and SQL CE was bound from freed memory. A failed transaction start leaked its pooled connection, and after a few occurrences SMTP, IMAP and POP3 blocked until a service restart. A failed IMAP folder insert was reported as success, so messages filed into it were written to disk with nothing to find them by. Security DKIM test mode (t=y) turned a failed signature into a pass, which then satisfied DMARC alignment. A failure in test mode is now neutral, per RFC 6376. IMAP SASL credentials were logged verbatim: AUTHENTICATE PLAIN passwords and XOAUTH2/OAUTHBEARER tokens. Only the first DKIM key record at a selector was read, so roughly half of a rotating sender's mail failed verification. MTA-STS enforcement and MX failover were lost for recipients past the first batch. Protocol and Control Panel SELECT/EXAMINE report a sequence number in [UNSEEN], as RFC 3501 requires, not a UID. Reverse-DNS lookups for the Received header moved to their own thread pool, completing the 6.2.13 fix. Backup would not start (#19): a Control Panel call to a method the backup interface does not have. Ctrl+K now searches settings, all 227 indexed by label and INI key. Logging, scanner timeout, indexing and retry settings moved to the pages that own them, which is where #16 went. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    The headline fix is an SMTP DATA stall that only affected relayed mail. Relaying from Postfix or Proxmox Mail Gateway, the connection could hang after 354 OK, send. until the sending MTA gave up with "timed out while sending end of data", leaving a zero-byte spool file. The cause was a reverse-DNS (PTR) lookup on the network I/O thread while generating the Received header, so an internal relay with no reverse zone stalled the session through DNS retries. That lookup now runs on a worker thread and header generation never waits on it. Direct sending was unaffected. What the upgrade involved No database change. Schema version stays at 6005. Minimum OS is Windows 10 1607 / Server 2016, 64-bit, which the installer's version check now names. SMTP. A parse exception no longer wedges a connection, data pipelined in the same segment as DATA is consumed correctly, a rejected BDAT/CHUNKING command drains or terminates its payload instead of desyncing the session (it matters for Exchange), the EHLO SIZE keyword no longer overflows, and TCP_NODELAY is set on every connection. IMAP. A malformed partial-fetch range such as BODY[]<0.-1> could drive a near-SIZE_MAX allocation, or read heap memory from before the buffer and send it to an authenticated client. The octet range is now clamped and normalized. OnClientLogon now fires from every AUTHENTICATE mechanism (PLAIN, SCRAM-SHA-256, XOAUTH2/OAUTHBEARER). SpamAssassin. A malformed or truncated spamd response could spin a core and hang the session, write the raw SPAMD header into the message, or overwrite it with a zero-byte file. The 256 MB scan ceiling is now clamped to the 80 MB MIME parser limit, and the original message is preserved on any failure. Upgrade and installer. DBUpdater labels database versions 6002-6005, a failed database create or upgrade returns a real exit code instead of a false success, and a customised EventHandlers.vbs survives reinstall. Control Panel. Diagnostics no longer reports every test as FAILED, and restarting the service is elevation-aware. The regression suite passed 1026 of 1026 against the rebuilt 6.2.13 service. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    Two lists in the Control Panel announced their CLR type name to screen readers instead of their contents. The alias list on the Domains page read hMailServer.ControlPanel.Views.DomainsView+AliasRow for every row, and Live logs read LogsView+LogLine for every line. The live log is the worse of the two. It is the page an administrator is most likely to be reading with a screen reader when something has gone wrong. Both lists use an ItemTemplate, so the text a sighted user sees comes from a binding, while a ListViewItem's accessible name falls back to ToString(). Neither class overrode it. Scope is genuinely those two. Every other list in the application is a DataGrid, which builds a row's name from its cells. The Domains page now reports [email protected][email protected], and the live log reports 37 items, none announcing a type name. (16184ce) The regression suite now runs in full 27 of the suite's 1026 tests had never executed on the release machine. They reported inconclusive because SpamAssassin and ClamAV were not installed. Installing both ran them for the first time and two failed, both defects in the tests rather than the server. TestWithVirus put the EICAR string in the plain body of a non-MIME message. Current ClamAV does not extract a plain body as a scannable part, so the message scanned clean and was delivered, failing its own "no messages" assertion. It now sends EICAR as a base64 attachment and matches the signature family rather than one exact name. TestSANotRunning called ServiceController.Stop() and returned immediately. Stop() only asks, so spamd was still answering on port 783 and the message came back with the X-Spam-Status header. It now waits for the port to refuse connections. It also asserted error 5157, reported only when a connection is established then lost mid-read. With spamd stopped, only 5508 is reported. 1026 of 1026 now pass, zero inconclusive, with live SpamAssassin and ClamAV, DMARC against live DNS and TLS 1.2/1.3 handshakes. Drop-in over 6.2.10. No database change (schema version 6005), no configuration change, no server-core change. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    6.2.9 is a follow-up to 6.2.8. It completes what that release deliberately left out: the LiveCharts upgrade 6.2.8 had to pin back. No server-core changes, and the regression suite still stands at 898/898. LiveCharts 2.0.5 (#11) 6.2.8 pinned LiveCharts to 2.0.0-rc2 because upgrading painted both dashboard charts as an opaque white block over the dark theme, taking the "No delivery activity yet" and "No active sessions" labels with them. CartesianChart derives from Control, and 2.0.x gives that Control a solid default Background where the release candidate left it unset, so the chart painted a white rectangle across the dark card. The overlay labels were never actually hidden. They are light-grey text that happened to land on that white. Setting Background explicitly fixes both symptoms. Verified in both light and dark themes. Worth recording what it was not. 2.0.5 pulls SkiaSharp.Views.WPF, OpenTK and OpenTK.GLWpfControl, which looks exactly like a GL-hosted surface and the usual WPF airspace problem. It is not that. LiveCharts.RenderingSettings.UseGPU defaults to false, so rendering stays on the software path and ordinary WPF layering applies. Control Panel tests (#12) The GUI previously had no test coverage at all. CI compiled it and stopped there. A ControlPanel.Core library exposes the side-effect-free services (PasswordStrength, NumericField, PasswordGenerator) through shared compile links, so no code moved and the Control Panel project itself is untouched. ControlPanel.Tests runs 17 xUnit tests against them, with coverlet emitting Cobertura coverage that CI publishes on every push. The three .NET 8 projects also gained a solution, ControlPanel.sln. Repository Release tags are now protected against being moved or deleted, and master against force-pushes. Secret scanning and push protection are enabled. A Code of Conduct was added, and the issue chooser routes questions to Discussions. It was a drop-in over 6.2.8: no database change (schema version 6005), no configuration change, no server-core change. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    A Control Panel bug-fix release. Both defects made a healthy server look broken, and they hit every Windows GUI administrator. There are no server-core changes since 6.2.6, and the regression suite still stands at 898/898. What the upgrade involved Drop-in over 6.2.7. No database change (schema version 6005) and no configuration change. #6: list editors showed blank rows Every data-driven list pane rendered the right number of rows with nothing in them. Adding an entry appeared to create an empty row, and only the Edit dialog showed the value you had typed. The row model exposed its data as a field, and WPF data binding resolves properties only, so every generated column silently bound to nothing. It was reported against domain aliases, but the same control backs SURBL servers, DNS blacklists, the anti-spam and greylisting white lists, blocked attachments, groups, server messages, external POP3 accounts and account rules. #7: the Control Panel died after a service restart The COM server lives inside the hMailServer service process, so restarting the service invalidated every interface pointer the GUI held, including restarts the Control Panel performed itself after saving a setting. Every page then failed with "The RPC server is unavailable" until you closed and reopened it. The session now verifies the link before use and re-authenticates transparently. A restart triggered from the Control Panel waits for the server to report Running rather than latching onto a service that has registered with Windows but is still opening its database. A restart by anyone else is detected on your next action and healed, with a "Connection restored" notification. The liveness check reads ServerState rather than Version, because a shutting-down service keeps answering Version from a static string after closing its database. The superseded COM proxy is released, and the Control Panel no longer starts a service the administrator deliberately stopped. Both fixes were reproduced on the previous build and verified against a live server: unit assertions on the session logic, a harness driving the real CollectionEditorView and DomainDialog, and UI automation over the running Control Panel. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    hMailServer 6.2.5 fixed two faults that stopped a default install from connecting to its own database. Anyone who installed with the shipped defaults, an internal SQL Server Compact database with DPAPI secret protection, was affected. Critical fixes DPAPI database-password truncation (SQL CE error 25028). IniFileSettings::ReadIniSettingString_ used a fixed 255-character buffer, so GetPrivateProfileString truncated the ~356-character DPAPI-protected database-password envelope. The truncated blob failed to decrypt, which yielded an empty password and SQL CE error 25028, Authentication failed. The buffer is now 4096 characters, which also covers long OAuth2 HMAC secrets and the password pepper. Fresh-install database version, 6004 to 6005. The CreateTables scripts for MSSQL, MySQL and PostgreSQL still stamped hm_dbversion = 6004 while the server required 6005, so a brand-new install reported "database too old". SQL CE uses the MSSQL script, so it was caught by this too. The recipientdsnnotify column was already present. Only the version row was stale. Validation Checked end to end on a Windows Server 2025 Active Directory domain controller. A default internal-database install connects. AD authentication passes through COM ValidatePassword in both the DNS domain.tld and NetBIOS DOMAIN\user forms, and through a real IMAP LOGIN, correct password returning OK and wrong returning NO. Control Panel The .NET 8 WPF Control Panel (hMailCP.exe) reached full settings parity with the classic Administrator here. The Server Status page (version, server state, database details, statistics, session counts, uptime, and a configuration-warnings panel that includes open-relay detection) and the per-account rule criteria and action editor are validated and wired into navigation. Windows x64 only: one installer, hMailServer-6.2.5-x64.exe, bundling the server, the Control Panel and the .NET 8 Desktop Runtime bootstrapper. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    The Control Panel gained a read-only Active Directory browser, which was the last functional-parity item left from the classic Administrator. The whole product is stamped 6.2.4: the server, the Control Panel window header and About page, and the installer all report the same version. Active Directory account pickers Services/ActiveDirectoryService.cs enumerates every domain in the current forest from the RootDSE defaultNamingContext and the Partitions container's domain crossRefs, so there is no dependency on System.DirectoryServices.ActiveDirectory. A domain's users are searched with a single LDAP-escaped DirectorySearcher matching sAMAccountName, displayName, mail and userPrincipalName. It is built on System.DirectoryServices, which net8.0-windows resolves from the Windows Desktop shared framework the installer already bundles. On a machine that is not domain-joined it reports the reason instead of throwing. Account then Directory carries "Browse Active Directory…". The picked account fills ADDomain and ADUsername and ticks linked to Active Directory. Distribution-list recipients gained "Add from AD…", which multi-selects accounts and imports their e-mail addresses into the list. Validated end to end against a live domain controller (progressiverobot.local): domain enumeration, the all-users query and the name and e-mail filters all returned the expected results. Other changes A generic TargetInvocationException from the server is now unwrapped and the real cause explained: connect with the server-administrator account, or the server cannot reach its database. That is what produced the misleading "26 settings could not be read" message on the Protocols page over a non-admin connection. The vendored MariaDB Connector/C client (libmysql.dll and its auth plugins) is staged into the build output by the server post-build step, so MySQL and MariaDB back ends work out of the box. The About page carries maintainer and company details. The Control Panel requires the .NET 8 Desktop Runtime, which the installer bundles and installs silently when missing. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    2 Views
    P
    6.2.1 completed Track B4, the deliverability and modern SMTP standards work. It added four ESMTP extensions, SRS for forwarded mail and SMTP rate shaping. PIPELINING (RFC 2920) advertised in EHLO. SMTPUTF8 / EAI (RFC 6531/6532): internationalised addresses accepted and relayed. ENHANCEDSTATUSCODES (RFC 2034): x.y.z codes on ESMTP replies. DSN (RFC 3461/3464): RET, ENVID, NOTIFY and ORCPT accepted. Per-recipient NOTIFY is honoured, and NOTIFY=NEVER suppresses failure DSNs. SRS (Sender Rewriting Scheme): HMAC-signed, reversible envelope rewrite on forwarding, for SPF alignment. Bounces are decoded back to the original sender. Opt-in via [Settings] SRSEnabled and SRSSecret. SMTP rate shaping, per-IP and per-destination, via [Settings] MaxSubmissionsPerIPPerMinute and MaxOutboundPerDestinationPerMinute. Both default to off. One fix: Unicode::WideToMultiByte returned a trailing NUL that could corrupt DPAPI-protected stored secrets. The result is now trimmed to the exact byte length. Everything new here defaults to off and is back-compatible, so the release changed nothing about an existing configuration until a setting was turned on. The build was clean, 0 warnings and 0 errors, with the SMTP regression suite and the in-server self-tests green. Full release notes, checksums and signatures