Skip to content
hMailServer 6.3.8 is the current release, signed 2 November 2026. Windows and Linux, and an in-place upgrade from 5.3 or later, but for the original hMailServer's 5.7.Download 6.3.8 Documentation FAQ
  • 0 Votes
    1 Posts
    132 Views
    ProgressiverobotP
    Written for 6.3.4. hMailServer 6.3.7 (17 October 2026) signs an authenticated submission as another hosted domain only when the account may send as the address its From names - its own, an alias pointing at it, a mailbox that granted it the post right, an address it proved, or a masked address of its own; otherwise the mail is sent unsigned as that domain, so give such an account the alias or the grant before upgrading. Mail from outside whose From names a hosted domain is no longer signed as it, nor is an alias's or a distribution list's copy of it to an outside address; where such a message did not pass DMARC for the organisation its From names when it arrived, a copy whose envelope sender is at this server's host name, or at a hosted domain or a subdomain of one, in that organisation is not sent where an alias or a distribution list expands to an outside address, a managed list does not distribute a posting whose From names the list domain's organisation, and a distribution list's bounce address is not given to it; a managed list's copies of a posting from outside are not signed as the list's domain when an address of the list domain's organisation is in its From fields. Creating a domain alias is now the server administrator's: a credential confined to named domains is refused it, over REST and over COM. See the 6.3.7 announcement. There are three ways of making one address reach somewhere other than a mailbox of the same name - an alias, a distribution list and a route - and one way of giving several people the same folder. This topic covers all of them as they are in 6.3.4 (27 September 2026, schema 6104): aliases, domain aliases and plus addressing; distribution lists, who may post to them and how moderation works; the membership query, which lets a list define its own members; the list manager, which turns a distribution list into a mailing list people join and leave themselves; and public folders with their permissions. The membership query and the list manager are new in 6.3.4; the distribution list itself is in every release. The one thing to know first: the address is resolved in one function (RecipientParser::CheckDeliveryPossibility), in a fixed order, and an account always wins. The order an address is resolved in At RCPT TO the server works through this, and stops at the first answer: Domain aliases rewrite the domain. Plus addressing trims the local part. Account? If found, deliver to the mailbox. Alias? If found, follow it and start over, up to 25 hops. Distribution list? If found, expand to the members, or to the moderator. Route? If found, send to the route's target server. The domain's postmaster address, the catch-all: when nothing above matched, the resolution starts again with that address, which is why a mistyped address is delivered there rather than refused. If it is empty, 550 Unknown user. Since 6.3.4 one question is asked before all of these: is the address, or its domain, routed to a webhook? A webhook route that only posts takes the address's mail instead of its mailbox, alias or list - a list whose address is routed never sees the message, nor applies its posting rules to it. Route the addresses you mean rather than a list's whole domain; mail in to a webhook has the routes themselves. Aliases An alias is a second address that delivers to an existing target. In the Control Panel: Accounts & domains → Domains, select the domain, then the Aliases panel. The Control Panel and COM are Windows-only. On Linux, where there is neither, the Control Deck is the administration people click through, and it is the front end of the REST API, which both platforms have: What REST route A domain's aliases GET and POST /api/v1/domains/{domain}/aliases; DELETE /api/v1/aliases/{address} A domain's other names GET and POST /api/v1/domains/{domain}/domain-aliases; DELETE on .../{name} beneath it A domain's lists GET and POST /api/v1/domains/{domain}/lists; PUT and DELETE /api/v1/lists/{address} A domain's plus addressing PUT /api/v1/domains/{domain} (plus_addressing_enabled, plus_addressing_character) The Control Panel paths and COM properties below are for Windows. Field COM property Meaning Alias address Alias.Name The address people send to. Must be in this domain Target Alias.Value May be anything: another account here, another alias, a distribution list, an address covered by a route, or an address at a different server Active Alias.Active Unticked: RCPT TO is answered 550 Alias is not active. - not passed on to the catch-all The target replaces the address and resolution starts again, so an alias may point at an alias, which may point at a list. Beyond 25 hops the answer is 550 Mail server configuration error. Too many recursive forwards. An alias is only consulted when no account has that address. Creating sales@ as an account after sales@ exists as an alias silently changes where the mail goes. An alias to an external address is treated as inbound mail, not as relaying, so [email protected] → [email protected] works for external senders without opening a relay. Since 6.3.4 three more kinds of second address exist, and they are the person's own rather than the administrator's: the alias a mailbox move leaves (renaming or moving a mailbox keeps the old address as an alias of the new one by default); masked addresses (schema 6067), which the person makes in the webmail for one shop or sign-up and which, switched off, are refused as an address that never existed; and verified send-as (schema 6066), which receives nothing here - it is a From address, not an alias. Domain aliases. Accounts & domains → Domains → Properties → Names. The rewrite is total: [email protected] becomes [email protected] before anything else is looked at. You do not create per-address aliases for an alias domain; the sender address is rewritten too, which is what lets a list in membership mode recognise a member who posts from the alias domain; and the alias domain needs its own MX record. Since 6.3.7 adding one is the server administrator's: a credential confined to named domains - such as a domain administrator, or an API key issued for its domains - is refused, over REST and over COM, because a domain alias decides what names the server accepts mail for. Plus addressing is off by default and enabled per domain on Accounts & domains → Domains → Properties → Limits (default character +). With it on, [email protected] resolves to [email protected], and the full original address is still in the To: header. It applies to the recipient address only, after domain aliases and before the account, alias and list lookups. When off, alice+invoices@ is an unknown address. Distribution lists A distribution list delivers one message to many recipients. In the Control Panel: the Distribution lists panel of the domain, then Properties and Members. Mode Stored value Who may post Refusal Public - anyone can send 0 Anyone at all - Membership - only list members can send 1 Any address on the member list, after domain aliases are applied to both sides 550 Not authorized sender. Announcements only 2 Only the address in Require sender address 550 Not authorized owner. Anyone in the domain can send 3 Any sender whose domain is the list's own 550 Not authorized domain. (on any mode) Require SMTP authentication flag An unauthenticated session is refused first 550 SMTP authentication required. "Anyone in the domain" is a claim, not a proof. MAIL FROM is free text, so an outsider can assert a local address. Tick Require SMTP authentication with that mode or the list is open to the Internet. A fifth mode, 4, "Anyone with a server account can send", existed only in the type library and behaved as Public; put_Mode now refuses the value and the option is gone from the dialog. One more check runs for every mode, Public included: the poster must be allowed to reach every recipient of the list, so a list containing a members-only list the poster is not in is refused as a whole. Moderation. Set a Moderator address and a posting the rules above would refuse is accepted with 250 and forwarded to the moderator instead, stamped X-hMailServer-Moderation. The moderator approves it by resending it to the list from an authenticated session; that authentication is the security boundary and is unconditional. Three failures are numbered in the log: 6360 (the moderator was removed between the check and the expansion), 6361 (the moderator address does not resolve; the recipient is refused with 550) and 6363 (the list is its own moderator). Bounce address. Empty means bounces go to the poster. Set, it becomes the envelope sender of every copy, so a dead subscriber's bounce reaches the list owner, and an external member's server evaluates SPF against the list's own domain. A bounce address pointing at the list itself is ignored, with error 6362. Headers. An unmanaged list adds List-Id, List-Post (the literal NO for an announcements-only list), List-Help, List-Owner and a mailto:-only List-Unsubscribe, before DKIM signing. Nothing is added when the message already carries a List-Id, or when the list or owner address is not US-ASCII. A list that defines itself: the membership query, since 6.3.4 Schema 6074. A list can carry a membership query: one short text that says who its members are, answered against the server's accounts at the moment a message is sent to it. [email protected] with the query domain reaches every active account of the domain on the day, including the person who joined this morning and not the one switched off last night. Query Members (empty) A static list: the addresses under Recipients and nothing else domain Every active account of the list's own domain domain:other.example Every active account of that domain, which this server has to host pattern:sales-*@example.com Every active account whose address matches the wildcard; * is any run, ? exactly one, case ignored everyone Every active account of every active domain on the server It is a union with the list's own recipients, never a replacement. An address that is both is delivered to once. It answers accounts only - not aliases, other lists or outside addresses - and never a disabled account or an account of a disabled domain. It is resolved once per SMTP transaction, not once per RCPT TO, and nothing is stored. Who may set which form. A domain administrator, or an API key with a domain scope, may set domain or a pattern: in a domain it holds. everyone, domain: naming another tenant's domain, and a pattern whose domain part is itself a wildcard are the server administrator's. The same rule governs reading the answer: GET /api/v1/lists/{address}/members answers 403 to a confined credential when the query reaches past its domains. A query is judged when it is saved. domain: naming a domain this server does not host, a pattern: with no @, or any text that is none of the five forms is refused, by the same sentence over COM, over REST and in the Control Panel. "Answers nobody" and "could not be answered" are different. A query whose named domain has been deleted is not an error at delivery: the message goes to the list's rows and code 6980 is logged. But when the accounts cannot be read - the database locked by a backup - the recipient is refused 451 4.3.2 and the sender retries, with code 6982, and the members route answers 503. It is set as Membership query in the Control Panel's list dialog and the Control Deck, membership over REST, DistributionList.Membership over COM, and hmctl list update [email protected] --set membership=domain. The Deck's list editor shows Delivers to now, each address marked Kept by hand or From the query. The list manager: a mailing list, since 6.3.4 Schema 6092. A distribution list with the list manager switched on is one people join and leave themselves. Nothing changes for a list until it is switched on: every list an upgrade finds is unmanaged. On the list: Managed in the Control Panel's list dialog, managed in the Deck's list editor and on PUT /api/v1/lists/{address}, or DistributionList.Managed over COM. The links. The confirmation page, each member's page, the owner's approval page, the subscribe form and the archive are served by the REST listener, which is off until RestApiPort is set (turning the REST API on). Make it reachable over HTTPS, then set list_base_url (ListBaseUrl), such as https://lists.example.com. Empty, the default, offers no link at all. Only an https:// base gives RFC 8058's one-click. DKIM on the list's domain. The copies are signed as that domain after the list's fields are in place, so the signature covers List-Unsubscribe and List-Unsubscribe-Post. With DKIM off for the domain the copies go unsigned and the providers do not offer the one-click. Address What it does [email protected] Post to the list [email protected] Ask to join, and confirm by replying [email protected] Ask to leave: the member is sent a link and a token, and nothing more happens until they follow it [email protected] The help text [email protected] The person who runs the list [email protected] Delivery reports; with VERP, [email protected] None of them is an account; an account, an alias or a list of exactly one of those names is the administrator's and wins over the manager. Joining. subscribe_policy is 0 closed (the default: the administrator adds members), 1 confirm (the address asked for is sent a confirmation with a token) or 2 moderated (after the address confirms, the owner approves on a page, signed in to the webmail as the owner's own account, or on the Deck; a reply by mail approves nothing). The list answers at most twenty requests an hour from one requester and two hundred an hour in all. Delivery. Each member chooses each message, one digest a day, or none. With digest on, one digest goes at digest_hour (7 by default, the server's local time), at most 100 messages and 10 MB. With archive at 1 (members) or 2 (public), every distributed message is kept and shown by month, as text only, never as HTML. The rows of hm_listarchive are not in the backup. What a member's copy carries, over an https:// base with the archive on: List-Id: <team.example.com> List-Post: <mailto:[email protected]> (NO for an announcement list) List-Help: <mailto:[email protected]?subject=help> List-Subscribe: <mailto:[email protected]?subject=subscribe>, <https://lists.example.com/lists/[email protected]/subscribe> List-Unsubscribe: <mailto:[email protected]?subject=unsubscribe>, <https://lists.example.com/lists/unsubscribe?t=...> List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Owner: <mailto:[email protected]> List-Archive: <https://lists.example.com/lists/[email protected]/archive> Precedence: list X-Loop: [email protected] X-hMailServer-List-Member: <a tag, see Bounces> Bounces. A 5.x.x is a hard bounce, a 4.x.x a soft one; a delayed warning counts for nothing. Anybody can write to the bounce address, so a report is believed only when it carries the member's tag, X-hMailServer-List-Member. Setting REST key Default ListHardBouncesToUnsubscribe list_hard_bounces_to_unsubscribe 1 ListSoftBouncesToUnsubscribe list_soft_bounces_to_unsubscribe 5 ListBounceWindowDays list_bounce_window_days 30 A member who reaches either count is set to none - paused, never unsubscribed - and the owner is told once. Public folders Accounts & domains → Public folders, in the Control Panel on Windows, creates shared IMAP folders; public folders have no REST route yet, so Linux has no administrator's page for them. On either platform a client holding the a right manages a folder's permissions over IMAP. Public folders live in their own namespace, #Public, and sub-folders are made by typing the whole path with the hierarchy delimiter, . by default: #Public.Team.Archive. #[email protected] is a different namespace: one account's own folders, shared. Each permission entry grants RFC 4314 rights to an account, a group or Anyone (every authenticated account). Right Letter What it allows Lookup l The folder appears in LIST/LSUB. Without it the folder does not exist as far as that user is concerned Read messages r SELECT and STATUS Keep seen/unseen state s Set or clear \Seen Set flags w Flags other than \Seen and \Deleted Insert i APPEND and COPY into the folder Post p Send mail to the folder's submission address Create sub-folders k CREATE beneath it Delete folder x DELETE Delete messages t Set or clear \Deleted Expunge e EXPUNGE Administer a SETACL, DELETEACL, GETACL, LISTRIGHTS An owner has every right implicitly. For anyone else the server walks up from the folder to the nearest ancestor that has any ACL rows, then uses the row for the account, else for a group the account is in, else for Anyone. The nearest ancestor with any rows wins, and rows are not merged. Adding one permission to a sub-folder removes everyone else's access to it. \Seen is shared in a shared folder, not per user. Grant lrs and delegates share one read/unread state; grant lr and they leave no trace. Turning ACL enforcement off opens public folders only. It does not extend to #Users, which stops existing entirely. What it does not do The list manager does not rewrite From for DMARC. A posting from a domain that publishes p=reject reaches outside members with a From that fails DMARC when the list changed the message, and Gmail and Yahoo may refuse it. No posting from the web, no list password, no approval by reply, no NNTP, no IMAP access to an archive, no weekly digest, and one owner address per list. A membership query has no directory-attribute form and no group: form, and no query can name another list's query. The list manager's fixture is not linked into the Linux test suite: MailingLists.md says its thirty-four tests are of the Windows suite. Where to read more Wiki: Aliases, Lists and Public Folders, Mailing Lists, Mail In to a Webhook Documents at the 6.3.4 tag: DistributionLists.md, MailingLists.md The public documentation: chapter 13 On this forum: Being trusted by the servers you send to for DKIM and DMARC, the 6.3.4 release announcement, the webmail in depth for masked addresses and send-as, and IMAP on the server for shared mailboxes
  • 0 Votes
    1 Posts
    147 Views
    ProgressiverobotP
    Written for 6.3.4. hMailServer 6.3.7 (17 October 2026) accepts the UTF8 that classic Outlook for Windows (Outlook 2016 to 2024) sends after the POP3 login, at which its downloads had stopped; SMTP, POP3 and ManageSieve refuse a SASL PLAIN sign-in that asks to act as another account, and IMAP takes an authzid naming the client itself as none; IMAP's COPY and MOVE by message number read their set in the client's numbering and refuse one that names a message another session has just expunged (NO [EXPUNGEISSUED]), FETCH BODY[N.MIME] and BODY[N] of a multipart are the stored octets, and a refusal by the access control is NO [NOPERM]; and the IMAP and POP3 listeners can take the client's address from a PROXY protocol header, as the SMTP listener does, off by default. An authenticated submission is DKIM-signed as another hosted domain only when the account may send as the address its From names. See the 6.3.7 announcement. hMailServer 6.3.8 (2 November 2026) signs a client in only when its user name is the account's stored address, compared in lower case after a domain alias and the default domain. A user name that differs from it in more than the case of the letters A to Z, or has white space at either end, may no longer sign in: such a name fails as a name that does not exist fails, so correct the user name in the client. See the 6.3.8 announcement. This topic covers connecting a mail client to hMailServer 6.3.4: ports, authentication, folders, automatic configuration, app passwords and devices. The one thing to know first: a new installation of 6.3.4 refuses a password from any machine but itself until the session is encrypted, and an upgraded server is not changed. On either, the TLS ports 465, 993 and 995 exist only once you create them. The settings your users need Setting Value Why, and what goes wrong Incoming server (IMAP) mail.yourcompany.com, port 993, SSL/TLS Implicit TLS: the handshake comes before the greeting. On a port not configured as SSL/TLS the client hangs, then times out Incoming server (POP3) mail.yourcompany.com, port 995, SSL/TLS The same. Only use POP3 if you have a reason to Outgoing server (SMTP) mail.yourcompany.com, port 587, STARTTLS Port 25 is for other servers, not for your users; many ISPs block outbound 25 from residential lines User name The full email address, [email protected] A bare name works only with Maintenance → Advanced → Default domain (for unqualified logons) set Password The account's password, or an app password if the account is enrolled in TOTP See the app passwords section below Encryption Never "none", never "auto-detect" "Auto-detect" is how a client ends up sending a password in the clear The ports, and what 6.3.4 changes on a new installation A new database is seeded with four rows - SMTP 25, SMTP 587, POP3 110 and IMAP 143 - and up to 6.3.3 all four were without encryption. Add 465, 993 and 995 yourself under Connections & protocols → TCP/IP ports in the Windows Control Panel, or on the Control Deck, once you have a certificate of your own. Connection security What the server does None (0) Plain text; STARTTLS is not advertised. Everything, including the password, is in the clear SSL/TLS (1) Handshake first, banner after. Correct for 465, 993 and 995 STARTTLS optional (2) Advertises STARTTLS and accepts both. The right setting for port 25 only: on a submission port it lets a misconfigured client send its password in the clear STARTTLS required (3) Answers 530 5.7.0 Must issue STARTTLS first. to every command except NOOP, EHLO, STARTTLS and QUIT. Right for 587, and for 143 and 110 if you keep them; on port 25 it silently refuses mail from every server that cannot do TLS With TLS chosen and no certificate selected the listener does not start at all: HM5113, Error initializing SSL. Certificate not set., in the application log, connection refused, nothing in the SMTP log; pick a certificate on the port. A port already in use is HM4316, and the rest of the server starts normally. A new installation of 6.3.4 has all four seeded listeners at STARTTLS optional with a self-signed certificate, which a mail client warns about until it is replaced, and the Internet IP range requires TLS for authentication; My computer (127.0.0.1) is left as it was. So from another machine, until the client sends STARTTLS: SMTP AUTH is not offered, and is refused with 530 A SSL/TLS-connection is required for authentication. if it is sent; IMAP advertises LOGINDISABLED, and LOGIN and AUTHENTICATE answer BAD A SSL/TLS-connection is required for authentication.; POP3 USER and AUTH answer -ERR. After STARTTLS every one of them works: the range's rule, not the port's, is what protects the password. When ACME's first certificate arrives it is given to every listener holding the self-signed one: see Let's Encrypt certificates are automatic. An upgraded or attached database is never changed. On Linux the defaults are applied at the unit's first start only when it comes within a day of --create-database. Which databases get them, the verb that applies them by hand and the checklist item that judges an upgraded server are in Hardening a public mail server. The IP range, not the port. RequireTLSForAuth lives on the IP range (Access & abuse protection → IP ranges, the Require auth tab). A range that requires TLS is offered no authentication mechanism at all on a cleartext connection, and IMAP additionally advertises LOGINDISABLED, so a client learns before it sends the password. DisableAUTHList is a comma-separated list of local ports on which SMTP AUTH is neither advertised nor accepted; use it to keep authentication off port 25. Since 6.3.4 such [Settings] keys are kept in the database: change them in the Control Panel, over REST (PUT /api/v1/settings/ini/{name}) or on Linux with hmailserver --set-setting NAME=VALUE. The database's value is the one used; where the service can write hMailServer.ini, a line edited there is put back (HM5804). Which port, decided once. For sending, 587 with STARTTLS required, or 465 if the client does not do STARTTLS properly; for receiving, 993, or 995 for POP3 on exactly one device. Never 143 or 110 without STARTTLS required, and deny 143 and 110 at the firewall once no client is left on them. What the server will actually accept Protocol Mechanism Advertised when Default on a fresh install SMTP AUTH LOGIN AUTH is enabled on the port Yes SMTP AUTH PLAIN Allow plain-text authentication is on No - authallowplaintext is seeded 0 SMTP AUTH SCRAM-SHA-256 Always, when AUTH is enabled Yes SMTP AUTH SCRAM-SHA-256-PLUS On a TLS connection Yes, on a TLS connection SMTP AUTH XOAUTH2 / OAUTHBEARER OAuth2 is enabled, and by default over TLS No SMTP AUTH EXTERNAL The handshake verified a client certificate on that port No IMAP LOGIN command Unless the port or the IP range requires TLS on a cleartext connection Yes IMAP AUTH=PLAIN, AUTH=SCRAM-SHA-256 Allow SASL PLAIN authentication is on No - EnableImapSASLPlain is seeded 0 IMAP SASL-IR Allow SASL initial client response is on No POP3 USER/PASS, SASL PLAIN, SASL SCRAM-SHA-256 Unless authentication is refused on this cleartext connection Yes The switches are on Connections & protocols → Protocols, the SMTP and IMAP tabs. Two consequences look like client bugs when they are not. On a default install, an IMAP client that insists on AUTHENTICATE PLAIN finds no AUTH= capability at all and must fall back to LOGIN. And SCRAM is always the account's own password, so an account with a second factor enrolled, or whose password has passed PasswordPolicyMaximumAgeDays, cannot sign in over SCRAM at all. Outlook on the desktop will not use SCRAM: it needs LOGIN or PLAIN. What the conversation looks like An extract of IMAP on a default install: * OK IMAPrev1 a002 LOGIN alice secret a002 NO Invalid user name or password. Please use full email address as user name. a003 LOGIN [email protected] secret a003 OK LOGIN completed The hint is given because the user name has no @. SMTP submission on 587, STARTTLS required: 220 MAIL01 ESMTP EHLO laptop.example.net 250-MAIL01 250-SIZE 20971520 250-8BITMIME 250-PIPELINING 250-CHUNKING 250-BINARYMIME 250-SMTPUTF8 250-ENHANCEDSTATUSCODES 250-DSN 250-STARTTLS 250 HELP MAIL FROM:<[email protected]> 530 5.7.0 Must issue STARTTLS first. STARTTLS 220 Ready to start TLS There is no AUTH line in that first answer, because the port requires TLS. After the handshake the client must send EHLO again, since the session starts afresh (RFC 3207 section 4.2). The second answer carries 250-AUTH LOGIN SCRAM-SHA-256 SCRAM-SHA-256-PLUS. Folders your users will look for A brand-new mailbox contains INBOX and nothing else. Drafts, Sent, Trash and Junk are created only when Create Drafts, Sent, Trash and Junk for new accounts is switched on (Connections & protocols → Protocols → IMAP), and the setting is seeded off. That is the usual explanation for "my sent mail is not on the server": the client fell back to a local folder because it found nothing designated \Sent. Fact Value Hierarchy delimiter ., so a subfolder of Work is Work.Invoices Public folders namespace #Public Other users' folders namespace #Users, only when ACL (shared folder permissions) is on - it is on by default Special-use designations \Drafts \Sent \Trash \Junk, advertised as SPECIAL-USE and CREATE-SPECIAL-USE IMAP or POP3. hMailServer advertises EXPIRE NEVER, so "leave mail on server" means for good, and a second POP3 session on the same mailbox gets -ERR [IN-USE]. What 6.3.4 changed in IMAP's answers Dovecot's imaptest was first run against this server on 25 September 2026: 31 of its 71 scripts failed, and 4 after 6.3.4 made the server answer as the RFCs say. The capability list is unchanged. A client that relied on the old answers may notice these: When the client 6.3.4 answers Names a mailbox that does not exist, or needs a right the account lacks NO, where it used to answer BAD; a failed SELECT or EXAMINE leaves no mailbox selected Sends an unknown LIST selection or return option BAD Fetches any BODY[<section>] without .PEEK Sets \Seen, BODY[HEADER] and BODY[1.MIME] included Appends a message Stores the literal byte for byte, where it used to add a CRLF, so RFC822.SIZE of a newly appended message is two octets smaller Pipelines a command behind an APPEND with a non-synchronising literal Answers it; it used to be thrown away, which stopped mbsync after one message Sorts, or threads Uses every criterion and builds the RFC's trees, so either can order messages differently Is the first session to be told of new messages Counts them as \Recent, where it said * 0 RECENT Automatic client configuration The server can configure clients, so users type only their address and password. AutoconfigEnabled is already 1; giving the web-services listener a port is what turns it on (WebServicesHttpPort=80, WebServicesHttpsPort=443), at the next reinitialise or restart, since the listener binds when it starts. Both port keys default to 0. Then point autoconfig.yourcompany.com (Thunderbird) and autodiscover.yourcompany.com (Outlook) at the server; both are ordinary host records. URL path Format Fetched by /mail/config-v1.1.xml, /.well-known/autoconfig/mail/config-v1.1.xml Thunderbird autoconfig XML Thunderbird and its relatives /autodiscover/autodiscover.xml Outlook POX autodiscover XML Outlook /email.mobileconfig, /mail/config.mobileconfig Apple configuration profile iOS and macOS Mail Which port ends up in the answer. The server reads your actual port rows and picks the best one per protocol: Rank Port configuration socketType written 100 SSL/TLS (implicit) SSL 90, 80 STARTTLS required on port 587; on any other port STARTTLS 70, 60 STARTTLS optional on port 587; on any other port STARTTLS 10 No encryption plain A protocol with no port at all is omitted. The host name is AutoconfigClientHost if set, otherwise the server's configured host name; with both empty the endpoint answers 404. Delegated mailboxes (since 6.3.4). The Outlook answer also names an AlternativeMailbox for every account that has opened a folder to the address asked about, but only to a request with HTTP Basic credentials, over HTTPS, for that very address. An Outlook IMAP profile never sees it: Outlook reads the element only for an Exchange account, and sends credentials only after a 401, which this server never returns here. What puts a delegated mailbox into a client's folder tree is the IMAP #Users namespace. None of this has been measured in Thunderbird or Outlook. Accounts with a second factor: app passwords A mail client has nowhere to type a six-digit code. Once a TOTP secret exists on an account, the account password is no longer a mailbox credential, and an app password is the only one. The order matters, and the Windows Control Panel puts the tabs in that order on purpose: Open the account: Accounts & domains → Domains → your domain → Accounts → the account. App passwords tab: create one per device, and write down the generated value; it is shown once. Two-factor tab: enrol the secret. Do it the other way round and every configured client stops working with no way back in. App passwords work for Active Directory accounts too, and are unaffected by password expiry, so enabling PasswordPolicyMaximumAgeDays does not silently break configured clients. A person makes their own on the webmail's Security page, which asks for the account's password again. Passkeys and single sign-on do not reach a mail client (since 6.3.4). They sign a person in to the webmail and the Control Deck and nothing else. An account that single sign-on or SCIM made has a random password nobody was told, so it needs a password set by an administrator before its person can make an app password for a phone. A recovery code is not a mail-client credential either. A mailbox encrypted at rest takes its own password only (since 6.3.4). It cannot enrol a TOTP second factor; on IMAP and POP3 its app passwords, an OAuth2 token, a client certificate and a Kerberos ticket are refused, and SCRAM does not open a key that is closed, so the client signs in with IMAP LOGIN or AUTHENTICATE PLAIN, or POP3 USER/PASS or AUTH PLAIN; and a client that was signed in when the switch was made is disconnected once. Devices: what revoking does Every client that has authenticated is one entry on the account's Devices list. Revoking a mail client's entry drops a live IMAP, POP3 or SMTP connection where it stands; a CalDAV, CardDAV or ManageSieve client has no connection to drop, so revoking one means revoking its app password. A revoke is not a ban: a client whose credential still works signs in again, so turn off its app password too, or change the account's password, which drops every connection of the account. Where the list is and what revoking does exactly are in Signing in. When it does not work What the user sees What the server said Cause Fix "Invalid user name or password", with a hint NO Invalid user name or password. Please use full email address as user name. Bare user name, no default domain Use the full address "Invalid user name or password", no hint NO Invalid user name or password. Wrong password, inactive account or domain, a TOTP-enrolled account given its account password, or, since 6.3.8, a user name that differs from the stored address in more than the case of the letters A to Z or has white space at either end Check both are active; issue an app password; give the address as stored "Authentication required" on sending 530 5.7.0 SMTP authentication is required. The client is not logged in for outgoing mail, or is on port 25 Tick "my server requires authentication"; move to 587 "Must issue STARTTLS" 530 5.7.0 Must issue STARTTLS first. Client encryption set to none on a STARTTLS-required port Set the client to STARTTLS A new 6.3.4 installation refuses the password from another machine 530 A SSL/TLS-connection is required for authentication. The Internet range requires TLS for authentication Set the client to STARTTLS, or use 465, 993, 995 once created Client hangs on connect, then times out Nothing: no session is created Implicit TLS expected on a STARTTLS port, or the reverse Match the port's connection security Repeated logon failures, then silence NO Too many invalid logon attempts. and a BYE Ten failures on one connection, the per-name lockout, or the per-IP auto-ban Access & abuse protection → Auto-ban Large attachment rejected 552 5.3.4 Message size exceeds fixed maximum message size The maximum message size, default 20480 KB Max message size, or the domain's own limit While diagnosing on Windows, look at Monitoring & troubleshooting → Live logs and Server status, which lists the listeners the service actually brought up. Per client: if Thunderbird offers "no encryption" it found a plain port, so fix the port, not the client. Where to read more Wiki: Connecting a Mail Client, Ports Reference, Encryption and Certificates, Sign-in and Identity. Documents: SecureDefaults.md, DevicesAndSessions.md. The public documentation: 7. Connecting a mail client, 7.2 Automatic client configuration, 22. Ports reference. On this forum: Let's Encrypt certificates are automatic, IMAP and POP3 on the server for shared mailboxes, when a saved setting takes effect, First install on Linux, Upgrading to 6.3.4 and the 6.3.4 announcement.
  • 0 Votes
    1 Posts
    125 Views
    ProgressiverobotP
    Written for 6.3.4. hMailServer 6.3.6 (6 October 2026) carries Linux packages for x86-64 and AArch64 and one for each of ten distribution releases, both AppImages, an ARM64 Windows installer (a preview) and the first container image. See the 6.3.6 announcement. hMailServer 6.3.7 (17 October 2026) is a security release: mail from outside whose From names a domain hosted here is no longer signed with that domain's DKIM key, an authenticated submission is signed as another hosted domain only when its account may send as the address its From names, and a forward of outside mail is given an envelope sender in the forwarding domain's organisation only when the message passed DMARC for it on arrival. See the 6.3.7 announcement. hMailServer 6.3.8 (2 November 2026), the current release, is a security release: it fixes vulnerabilities the project found in its own code, so upgrade every server running 6.3.7 or earlier. See the 6.3.8 announcement. This tutorial is for someone who has not run a mail server before. It follows a message from one person to another, shows where hMailServer sits on that journey, and says what the software does and does not do. The one thing to know first: port 25 has no password, and it has to be that way. Any server on the internet may connect to your port 25 and offer you mail for your own domains, or nobody could write to you. Your own users send through a different door, port 587, which requires a login. Most of what follows is about keeping those two doors apart. What hMailServer is hMailServer is a mail server: the software that owns an email domain. When someone sends a message to [email protected], their mail server looks up where yourcompany.com receives mail and delivers it to whatever is listening there. If you run hMailServer, that is your machine. Progressive Robot Ltd forked hMailServer in 2026 and maintains the hMailServer 6 line; the current release is 6.3.8, of 2 November 2026. Job Protocol What it means Accept mail from the world SMTP Other mail servers connect and hand you messages for your users Let your users read mail IMAP and POP3 Outlook, Thunderbird, Apple Mail and phones connect to fetch messages Let your users send mail SMTP submission Your users hand you messages and you deliver them onward Where it sits, and what is not yours Running your own mail server means owning the middle of three boxes. DNS is your registrar's, and the mail clients are your users'. The wiki puts it plainly: almost every problem people describe as "hMailServer is broken" turns out to be in one of the two boxes it does not own. You provide hMailServer provides A machine reachable from the internet The SMTP, IMAP and POP3 servers, and the whole delivery pipeline A host name with an A record, and an MX record pointing at it The MTA-STS policy derived from that MX, and a live check of every record A PTR record, which only your ISP can set Nothing can substitute for it SPF, DKIM and DMARC records in your zone The DKIM key generation with a copyable record, the signing, and the inbound evaluation of everyone else's Port 25 reachable inbound, and outbound (many consumer ISPs block outbound 25) Nothing can work around a blocked port; a smart host is the usual answer A certificate, or nothing, and let ACME get one Built-in Let's Encrypt issuance and hourly renewal Somebody who will read a log occasionally The logs, the diagnostics, the message trace and the metrics to read A message's journey You send mail to [email protected]. This is what happens: Your mail client submits the message to your hMailServer on port 587. You log in first. hMailServer answers 250 Queued. It asks DNS who receives mail for example.com. The MX record answers: mail.example.com. It looks up the A and AAAA records for that host, plus TLSA and the MTA-STS policy. It delivers the message by SMTP on port 25: no login, TLS if offered. The recipient's server answers 250 OK and stores the message in Alice's mailbox. Alice's mail client reads it over IMAP. An open relay is the thing to avoid. Never let an unauthenticated stranger send mail through you to the outside world. The wiki's warning is that it will get your server blacklisted within hours. hMailServer refuses this by default. A note on ports. A fresh install seeds ports 25, 587, 110 and 143. The TLS ports 465, 993 and 995 exist only after you create them on the TCP/IP ports page. A submission, and the checks in the order the server runs them The order matters, because it decides when a sender is told no: before the message body is transferred, or after. Stage What is checked Reply when it fails Any command On a STARTTLS required port, everything but NOOP, EHLO, STARTTLS and QUIT 530 Must issue STARTTLS first. MAIL FROM Free disk space: MinimumFreeDiskSpaceMB, default 100 452 4.3.1 Insufficient system storage MAIL FROM Send-As, only when SmtpAuthenticatedSenderCheck=1 (default 0) 550 5.7.1 Sender address rejected MAIL FROM Per-IP rate: MaxSubmissionsPerIPPerMinute (default 0, unlimited) 421 Too many messages from your IP address MAIL FROM Declared SIZE against the domain's maximum message size (default 20480 KB) 552 5.3.4 Message size exceeds fixed maximum message size RCPT TO Is the address deliverable at all? 550 Unknown user, or 451 4.3.2 Unable to verify the recipient at the moment RCPT TO Mailbox full 452 4.2.2 RCPT TO Relay permission for this IP range 550 Delivery is not allowed to this address. RCPT TO Authentication required and not supplied 530 SMTP authentication is required. RCPT TO Greylisting, when it is on (default off) 451 Please try again later. end of data Actual size, bare LF check, post-transmission spam tests 552 5.3.4, 554 5.6.0 Rejected - Message containing bare LF's, 554 5.7.1 4xx and 5xx. A 4xx reply always means "come back later", while a 5xx means "never". The difference decides whether a legitimate sender's message waits in their queue or is destroyed, which is why a full mailbox is 452 and not 550. Refusing early. Every check at MAIL FROM and RCPT TO happens before a single byte of the message crosses the wire. Refusing early costs the sender nothing, and it generates no bounce to an address a spammer only claimed to be. The timing in the last reply is real. A submission ends with a line such as 250 2.0.0 Queued (0.412 seconds): the server times the accept-and-save stage and reports it. A number that climbs into whole seconds is the first sign of a slow spam test, a stalled virus scanner or a saturated work queue. Since 6.3.4 the same session has more places to say no, each of them off until an administrator sets it: country blocking, a domain white and black list, restricted delivery, mail flow rules and others. One thing differs without a switch, and only on a new installation, not an upgrade: the Internet IP range requires TLS for authentication, so from another machine AUTH is not offered before STARTTLS. Who may send through you This is the decision that separates a mail server from an open relay, and hMailServer makes it per IP range. Mail from other domains to yours is taken on port 25 without a password, or nobody could write to you. From the Internet range, mail that gives one of your own domains as its sender needs a login, whoever it is for, and relaying from one remote address to another is allowed on both shipped ranges only with authentication: a stranger who has not logged in is answered 530 SMTP authentication is required. A range that allows relaying without authentication must never exist (the Control Panel's status page warns of one as an open relay). Ranges are matched by priority, highest first, so a narrow range for your own network can sit in front of the broad Internet range; IP ranges, auto-ban, lockout and the rest has the whole grid and the shipped values. After "250 Queued": the delivery pipeline Acceptance and delivery are separate. The 250 means the message is on disk and in the database; delivery happens on the delivery threads afterwards, in this order: The OnDeliveryStart script event. Virus scanning. Global rules. The OnDeliverMessage script event. DKIM signing, then mirroring, each on the first attempt only. Local delivery: account rules, Sieve, forwarding, distribution lists, public folders. External delivery for any recipient outside this server: routes or an MX lookup, MTA-STS, DANE, TLS, then SMTP. A temporary failure is rescheduled: 4 tries, 60 minutes apart by default. A permanent failure, or retries exhausted, produces a delivery status notification to the sender. Where the filters sit Anti-spam runs in two phases, before and after the message is transmitted, and a test's phase is fixed by the test. Two thresholds decide what a score means: mark (default 5) adds spam headers, and delete (default 20) refuses the message, or quarantines it when the quarantine is on. On a fresh install almost every test is off. zen.spamhaus.org, bl.spamcop.net and multi.surbl.org are seeded but inactive; the HELO, PTR, MX and SPF tests are off; SpamAssassin is off; greylisting is off. DMARC is on (ASDMARCEnabled 1), and it evaluates SPF and DKIM itself for its own purposes. Anti-spam does not run at all for an authenticated session, for a whitelisted sender, or for an IP range with spam protection switched off. Reading mail back: IMAP or POP3 IMAP POP3 Mail lives on the server on one device Folders yes, and shared/public folders too INBOX only Read/unread, flags shared across devices per device New-mail notification IDLE pushes it polling only Server-side search yes no Concurrent sessions many one at a time; a second gets -ERR [IN-USE] Default ports here 143, and 993 once you create it 110, and 995 once you create it The wiki's advice is short: use IMAP. The three records that make mail arrive SPF: a list of the servers allowed to send mail for your domain. DKIM: a cryptographic signature proving the message really came from you and was not altered. DMARC: a policy saying what to do when SPF and DKIM disagree, and where to send reports. Without them your mail will go to spam. The wiki calls this the most common reason a new mail server "doesn't work". Note the asymmetry: hMailServer signs your outgoing mail with DKIM as soon as you configure a key, but checking SPF on incoming mail is off by default. Being trusted by the servers you send to has the detail. What hMailServer is not It was not a webmail client; since 6.3.2 it is one. The page at /portal on the REST listener became a mail client in 6.3.2, and a separate webmail such as Roundcube is no longer needed, though it still works over IMAP. Of 6.3.4's paging of a folder of a hundred thousand messages, the wiki says: built, and not yet measured. See The webmail portal at /portal. It is not a spam filter you can point at someone else's mail. It filters mail it receives, for domains it hosts. It is not Exchange. There is no ActiveSync, no MAPI and no Teams integration, so Outlook connects over IMAP and SMTP like any other client. Since 6.3.4 it carries the pieces of groupware that ride on standards, such as calendars over CalDAV. Who should run it: a small business that wants its own mail on its own server; a developer who needs a real SMTP/IMAP endpoint for testing; a hosting provider running mail for many domains. Who should not: if nobody in your organisation is comfortable editing DNS records and watching a log file occasionally, a hosted mailbox provider will serve you better. What you run it on Windows Linux Platform 64-bit Windows 10 1607 / Server 2016 or later Since 6.3.0. 6.3.4's packages are x86-64 only: a .deb for Ubuntu 26.04 and 24.04, an .rpm for Fedora 43 and 44 and Enterprise Linux 10 Administration The Control Panel, the COM API, the Control Deck and the REST API The Control Deck and the REST API. The Control Panel and the COM API are Windows-only Event scripts VBScript or JScript JavaScript, since 6.3.4 The AArch64 packages and the AppImage were last published with 6.3.3. 6.3.4 is installed by hand; no live update installs it. hMailServer on Linux: what you get and what you do not and First install on Linux go further. "Additive and off by default" The design rule is that an existing installation upgrades without behaving differently until you turn something on. Category State on a fresh install Optional listeners: the REST API and /portal, web services, metrics, ManageSieve Off. Each stays inert until its port setting is non-zero Optional features: quarantine, message trace, full-text index, archive Off Outbound transport security: MTA-STS, DANE, DNSSEC validation On (MtaStsEnabled, DaneEnforcementEnabled, DnssecValidationEnabled). Each can be switched off A new installation of 6.3.4, not an upgrade A self-signed certificate, STARTTLS offered on 25, 587, 110 and 143, TLS required for authentication from the Internet range: see Hardening a public mail server Since 6.3.4 the database is the settings store: a [Settings] line edited in hMailServer.ini is ignored in favour of the stored value, and put back where the service can write the file. Words you will meet Term Meaning MTA Mail Transfer Agent: a mail server that accepts and forwards messages. hMailServer is one MSA Message Submission Agent: the server your own users hand mail to, normally on port 587, normally with authentication MUA Mail User Agent: the mail client Relay Accepting a message for a domain you do not host and passing it on Smart host Another server you send all your outbound mail through, often your ISP's STARTTLS Upgrading a plaintext connection to an encrypted one, in-band Implicit TLS TLS from the first byte, no upgrade step: ports 465, 993, 995 Envelope vs header The MAIL FROM/RCPT TO addresses the servers use, versus the From:/To: a person reads. They need not match Deferral Holding a message for a later attempt after a temporary failure Backscatter Bounces sent to a forged sender address MX record The DNS record saying which server receives a domain's mail PTR record Reverse DNS: maps an IP back to a host name Where to read more Wiki: How Email Works, What hMailServer Is and Is Not and the Glossary. The public documentation: chapter 1, chapter 2 and the glossary. On this forum: Read this before you post and Where to post what; for the next steps, Your first domain and mailbox, and the DNS records your domain needs, Connecting a mail client, The anti-spam stack end to end and Every port hMailServer listens on.
  • 0 Votes
    1 Posts
    118 Views
    ProgressiverobotP
    This topic covers how much mail an hMailServer 6.3.4 server keeps, and for how long: each mailbox's limit and the quota policy 6.3.4 adds around it; retention, the administrator's and each person's, with the recover-deleted window; and the server archive under ArchiveDir. The one thing to know first: out of the box nothing is deleted because of its age. A new account has no limit (0), no domain has a retention policy, the archive is off, and once it is on, ArchiveRetentionDays is 0, keep for ever. The limit, and what a full mailbox does Where it is set. Account.MaxSize over COM, max_size_mb over REST, in megabytes; 0, the default, is no limit. Set it on the Control Panel's account dialog (Quota (MB), Windows only), in the Control Deck's account editor, with PUT /api/v1/accounts/{address}, in the max_size_mb column of an accounts CSV file (since 6.3.4), or with Set-HmAccount. A domain's Limits tab caps the whole domain (Maximum domain size (MB), 0 for none; once reached, delivery to its mailboxes fails) and sets the quota new accounts get. What counts is each message's original size: compression does not lower it, and a mailbox encrypted at rest keeps its sizes in the clear. The kept copy of a message the person sent to expire counts against their quota (413, quota_exceeded). Where At the limit SMTP RCPT TO, with RejectFullMailboxAtRcpt on (1, the default) A mailbox already at or over its limit, and past any grace (below), is answered 452 4.2.2 Mailbox is full., a temporary refusal: the sending server keeps the message and retries A message that arrives while there is room and would overflow it Caught at delivery, with a non-delivery report to the envelope sender RejectFullMailboxAtRcpt at 0 Accepted, then bounced to an envelope sender that spam has usually forged. Leave it on IMAP APPEND, COPY, MOVE Refused with [OVERQUOTA], so a client can tell a full mailbox from any other refusal APPEND into a folder shared from another mailbox Since 6.3.4 charged to the folder's owner, as COPY and MOVE were A migration or PST import job Pauses with the account has no room left under its quota and tries again; raise the limit or make room A full disk is a different refusal. Below MinimumFreeDiskSpaceMB (100) free on the store's volume, MAIL FROM gets 452 4.3.1 Insufficient system storage. and IMAP APPEND NO [UNAVAILABLE], for every mailbox. The log warns first, below DiskSpaceWarningThresholdMB (1024). What the person sees. The webmail's Storage page (since 6.3.2, GET /api/v1/me/storage the share used, every folder by size, the twenty largest messages, and a clean-up of Trash and Junk older than 7, 30 or 90 days, or everything. See The webmail portal at /portal. GET /api/v1/me answers quota with limit_mb and used_bytes. IMAP QUOTA: QUOTA=RES-STORAGE is advertised; GETQUOTA and GETQUOTAROOT answer one unnamed root for the whole account with STORAGE in kilobytes, and an empty list for an account with no limit. SETQUOTA is refused: the limit is the administrator's. It is on as seeded; the switch is imap_quota_enabled on PUT /api/v1/settings (IMAPQuotaEnabled over COM). The quota policy (since 6.3.4) The server-wide warning at QuotaWarningPercent (90) has been there since 6.2.22-pre6. Schema 6061 adds a domain's own warning share and words, a grace and a send-stop, each a share of the limit; schema 6088 lets an account hold its own shares too. Point Server Domain (-1 takes the server's) What it does Warning QuotaWarningPercent, 90; 0 warns nobody quota_warning_percent The delivery that takes the mailbox across this share sends its owner one notice, from the domain's postmaster Grace quota_grace_percent, 0 quota_grace_percent How far past the limit mail from other people is still accepted Send-stop quota_send_stop_percent, 0 (never) quota_send_stop_percent The share at which the account can no longer send Over COM (Windows): Settings.QuotaGracePercent, Settings.QuotaSendStopPercent, and Domain properties of the same names. The warning is sent once, by the delivery that crosses the threshold; nothing records who was warned, so a mailbox emptied and filled again is warned again. The grace is for mail other people send, the mail otherwise lost. A 1 GB mailbox with a 50% grace receives until it holds 1.5 GB; the owner's own saves and copies over IMAP and the webmail stop at the limit. The send-stop refuses the account, not the address. An authenticated MAIL FROM is refused with 552 5.2.2 and the reason, keyed on the account that signed in, even under a domain alias, not the address it named. Receiving goes on. QuotaPolicy.md describes the refusal at SMTP only; test the webmail's send and the send API before relying on it there. The words are the QUOTA_WARNING_SUBJECT and QUOTA_WARNING server messages, with %MACRO_MAILBOX%, %MACRO_QUOTA% (MB), %MACRO_USED% (MB) and %MACRO_PERCENT%. Server messages are server-wide (the Control Panel's Mail flow & delivery → Server messages, the Deck's Server messages page, PUT /api/v1/settings/messages/{name}). A domain sets its own subject and text, quota_warning_subject and quota_warning_text (Domain.QuotaWarningSubject, Domain.QuotaWarningText), so its people can be warned in their own language. They are chosen apart: a domain that sets only the text keeps the server's subject. Levels. The warning is a preference: the deepest level holding a value wins. The grace and the send-stop are limits: an account's own value may tighten its domain's, never loosen it, while a domain's may sit either side of the server's. The domain's shares are the domain administrator's, and a domain-restricted key's. <name>_effective and <name>_source on the domain and account routes say why a mailbox was not warned. An account's own quota shares are tested only through what the routes answer, and only on Windows. The mechanism is in Settings: what is not stock, when a save takes effect, and the three levels. Where it is set. Control Deck: the domain editor's Quota policy group; the server's grace and send-stop on the Settings page. Control Panel (Windows): the domain dialog's Limits tab; the server's grace and send-stop under SMTP, beside QuotaWarningPercent. REST: the five domain keys on PUT /api/v1/domains/{name}; the server's two on PUT /api/v1/settings. An account's own value: the Levels tab of the Control Panel's account dialog, the Deck account editor's levels card, hmctl account set, or PUT /api/v1/accounts/{address}. QuotaWarningPercent is a key of the settings store: set it in the Control Panel (Windows) on Connections & protocols → Protocols, SMTP tab, with PUT /api/v1/settings/ini/{name} or hmctl ini set, which answer to the administrator password alone (never an API key, nor an account holding a role), or, on the Linux server itself, hmailserver --set-setting, not by editing hMailServer.ini. Every value here applies when it is saved through the server, at every level; when a save takes effect explains why a line edited in the file does not hold and when a value stored by --set-setting arrives. A backup taken before the policy restores with the server's values. One domain warned at 85%, stopped from sending at the limit and given a 20% grace, with a German subject; then one account put back on its domain's grace: hmctl domain set example.com quota_warning_percent 85 hmctl domain set example.com quota_send_stop_percent 100 hmctl domain set example.com quota_grace_percent 20 hmctl domain update example.com --set "quota_warning_subject=Ihr Postfach ist fast voll" hmctl account set [email protected] quota_grace_percent inherit Who is nearest their limit GET /api/v1/reports/quota lists every mailbox with a limit and at least one message, nearest first: megabytes, quota_megabytes, percent, the warns_at and sending_stops_at points that apply to it, and a state of ok, warned, stopped or over. It takes domain, top (1 to 200, default 10) and format=csv, and ignores the date window. Its test has run on the Windows bench only. The Deck's Reports page shows it as Near their quota. Other than the administrator password, a credential needs view_configuration and view_message_trace. The sections hmctl report documents do not include it: curl -u Administrator:your-admin-password \ "http://127.0.0.1:8443/api/v1/reports/quota?domain=example.com&top=200&format=csv" Nothing records what a mailbox held yesterday; per-domain storage by day is the storage section, in Alerts, the audit trail, syslog and the journal, and per-domain reports. Retention: the administrator's policy MessageRetentionDays (since 6.2.25) is set per domain and per account; there is no server value. On a domain, 0 (the default) is no policy and a number deletes mail older than that many days. On an account, 0 (the default) takes the domain's, a number is its own, and -1 keeps for ever whatever the domain says. The sweep. MailboxRetentionTask runs at start-up and every six hours. It removes delivered messages whose stored creation time is older than the window, in every folder of the mailbox, through the same deletion an IMAP EXPUNGE performs, so the quota, the QRESYNC record and an open IMAP session all see it. Utilities.RunMessageRetention (COM, Windows only) runs it now and returns the count; no document names a REST route or hmctl verb for it, so on Linux wait for the next pass. Where it is set. On Windows the Control Panel's domain dialog (Limits tab) and account dialog (General tab); the Deck's domain and account editors; message_retention_days on the domain and account routes; hmctl domain set and hmctl account set. A domain's retention is the server administrator's (COM refuses a domain administrator, the domain route a restricted key); an account's own value is the domain administrator's, so an account's -1 can switch its domain's policy off for that account. Before switching a domain's policy on: Give -1 to each account that must keep everything. Decide whether what the sweep removes should be recoverable for a while (recover_deleted_days, below). Off, a removed message is gone. Set the domain's days. It applies when saved; the next pass, at most six hours away, deletes. Easy to miss. A restore of the built-in backup does not carry a domain's retention days: the wiki's Backup and Restore page lists them as silently reset to 0, so re-enter them. And a legal hold outranks retention: a held account is left alone by the policy and by the person's own choices, and the log says so. Each person's own retention (since 6.3.4) Three choices on the webmail's preferences page: Empty Trash after, Empty Junk after and Archive Inbox mail after, each never, 7, 30 or 90 days, or a year, kept as retention_trash_days, retention_junk_days and retention_archive_days. The same six-hourly sweep runs them after the administrator's policy. Trash and Junk (the folders designated \Trash and \Junk, or named as clients name them) are emptied of what is older; Inbox mail older than the choice is copied to the \Archive folder, made as a top-level Archive if there is none, then removed from the Inbox. That is a folder of the person's mailbox, not the server archive. A value that is not a whole number of days from 1 to 3650 is off. The recover-deleted window (since 6.3.4) recover_deleted_days on PUT /api/v1/settings or the Deck's Settings view (0 to 365; 0, off, by default) keeps a copy of what a person deletes, and of what either retention removes, for the person to put back from the webmail's Recover deleted items. A domain or an account may keep copies for fewer days than the level above, never more. The copies, under <data directory>/Recoverable/<account id>/, count against no quota and are not in the backup, so size the window with the disk in mind; the six-hourly task ends those past the window, and all of them at 0. The person's side is in The webmail in depth: search, offline mail, expiring messages, send-as and recovery. The server archive With ArchiveDir set, the server writes a copy of every message received by SMTP into a tree of its own, as received and in the clear: encryption at rest does not cover it, and the mailbox retention policy does not reach it. The layout, as the Settings Reference writes it (Windows separators, names lower-cased): Message Where the copy goes From a local sender ArchiveDir\<senderdomain>\<sendername>\Sent-<file> From anybody else ArchiveDir\Inbound\<file> For each local recipient ArchiveDir\<recipientdomain>\<recipientname>\<file>, made from the first copy when there is one A bounce or report with a null sender The archive's Error folder, with no index row The archive's settings: Key Default What it does ArchiveDir empty (off) The folder the copies go to ArchiveDomains empty (every message) Comma-separated: a message is archived only when its local sender or a recipient is in a listed domain, and only the listed domains' copies are made ArchiveHardLinks 0 Hard-link instead of copy: a promise that nothing outside the server edits a message file in place ArchiveRetentionDays 0 (keep for ever) Deletes archived copies older than this many days Its sweep runs at start-up and every twelve hours. It removes only .eml files, follows no symbolic link or junction, is depth-capped, and asks the index first: a held copy stays however old. The index (since 6.2.25, schema 6029): a row per copy in hm_archiveindex, with who, when, what, where and whether it is held; copies made before schema 6029 have none. Search it in the Deck's Archive view (since 6.3.4), with GET /api/v1/archive (domain, mailbox, sender, recipient, subject, since, until, hold=1, limit 1 to 1000, default 200, newest first), or with Utilities.SearchArchive over COM (Windows). A role needs view_archive; a key restricted to named domains must name one of its own, and the Inbound copies are the administrator's alone. Searching the words of archived mail is an eDiscovery case's work. A hold on one copy, POST /api/v1/archive/{id}/hold or Utilities.SetArchiveHold, keeps its file and row from the sweep and from an address's erasure; DELETE lifts it. Holds on whole accounts and domains are eDiscovery's: see Compliance: eDiscovery, legal holds, personal data, erasure and the audit trail. curl -u Administrator:your-admin-password \ "http://127.0.0.1:8443/api/v1/archive?domain=example.com&[email protected]&since=2026-09-01&limit=50" curl -u Administrator:your-admin-password -X POST http://127.0.0.1:8443/api/v1/archive/4471/hold Where it is set. On Windows, the Control Panel's Maintenance → Advanced, Copies of mail tab (ArchiveDir, ArchiveHardLinks, ArchiveDomains), and ArchiveRetentionDays on the SMTP tab of Connections & protocols → Protocols. The Deck has no page for these keys: use PUT /api/v1/settings/ini/{name} or hmctl ini set <name> <value> (the administrator password only), which take effect when saved, or hmailserver --set-setting NAME=VALUE (with sudo) on the Linux server itself, which, while the service runs, waits for the next save, a reinitialise (POST /api/v1/server/reinitialize) or a restart. Setting one up: Choose a folder outside the data directory: a full restore with the messages option replaces that directory, and an archive inside it too, held copies included. On Windows, a new installation runs the service as NT SERVICE\hMailServer, which writes only where it is granted: approve the folder by running hMailServer.exe /GrantServiceAccess with --approve-modify "<folder>" from an elevated Command Prompt in the installation's Bin folder. It must be a full path on a fixed local drive, outside the program folder, Program Files, the Windows folder and the profiles folder: never a share, a drive's root, or a path through a junction or link. On Linux the service runs as User=hmailserver, and the packaged unit lets it write only under /var/lib/hmailserver, the data directory itself, and /var/log/hmailserver. Every other folder is read-only to it (/home is not even visible), and an ArchiveDir it cannot write stops archiving. Make the folder writable by the hmailserver user, add it to the unit with a drop-in (sudo systemctl edit hmailserver, then under [Service] a ReadWritePaths= line naming the folder) and restart the service. SecureDefaults.md gives this drop-in for a data folder; no document gives it for the archive. Set ArchiveDomains first if only some domains are archived, then ArchiveDir. Send a test message and find its row in the Deck's Archive view. Before relying on it. The backup does not carry it. The backup copies the data directory, and hm_archiveindex is not carried: back up the archive folder, and the database with its own tool for the index. Moving it strands the index. hm_archiveindex.archivepath is matched as an exact string by the sweep, holds and erasure; do not rewrite it in bulk. If the folder moves, move it back or accept that older rows point at the old place. A mailbox move leaves the archive under the old address, and an address's erasure with the archive included leaves the copies in other people's trees and in Inbound until ArchiveRetentionDays ages them out. It is not journaling, which sends a copy elsewhere and keeps nothing here: Journaling and dual delivery. SMTP, as documented. No 6.3.4 document says whether mail the server queues itself, such as the webmail's send, or mail a fetch account collects, is archived. What it does not do No message-count quota: storage is the only quota enforced. No server-wide retention policy, and no documented way to run the retention sweep on demand on Linux. No write-once archive: a hold is a flag an administrator can lift. The archive only grows while ArchiveRetentionDays is 0, and the recover-deleted store is bounded by its window alone: watch the disk they are on. Where to read more Documents at v6.3.4: QuotaPolicy.md, SettingLevels.md, Reports.md, RecoverDeleted.md, Discovery.md, Backup.md, ServiceAccount.md, RelocatingAnInstallation.md, PersonalData.md, Journaling.md, SecureDefaults.md, SettingsApply.md. Wiki: Settings Reference (section 9.13), Your First Domain and Mailbox, Compliance and eDiscovery, Backup and Restore, APIs Reference. The documentation page: Storage, retention and archive, Queue, quarantine and archive. On this forum: Backup and restore, for what a restore resets; Relocating an installation, and moving or renaming a mailbox, for the archive index; the service account on Windows and the Linux unit, for the folders the service may write; The Control Deck.
  • 0 Votes
    1 Posts
    143 Views
    ProgressiverobotP
    Written for 6.3.4. hMailServer 6.3.7 (17 October 2026) has the migrations as a card on the Control Panel's Backup, restore & migration page, where this topic says there is no Control Panel page; and a message collected from an external account is sent to SpamAssassin with the Return-Path the other server recorded, where it was the guess from the From field, so its SPF and envelope rules may score such mail differently. See the 6.3.7 announcement. The Windows installer of hMailServer 6.3.8 (2 November 2026) refuses an installation of the original hMailServer's 5.7 (5.7.0, its pre-release builds 2788 and 2843, 5.7.1 and 5.7.2), which this fork's upgrade chain has no step from, before it changes anything, and the installers of 6.3.7 and earlier must never be run over one: such a server's mail comes in by a migration of kind imap, as Migration.md's From the original hMailServer says. See the 6.3.8 announcement. This topic covers every route 6.3.4 offers for bringing existing mail into this server: the webmail's Other accounts page for one person, an external account with the mirror on for a few mailboxes that must stay in step, migration jobs for hundreds of mailboxes from an IMAP server, Google Workspace or Microsoft 365, the Import Tool for mbox files and a Maildir, and the PST import for Outlook data files. It ends with the mailbox move, for a mailbox that is already here and needs a new address or a new domain. The one thing to know first: every route needs the local account to exist. Create the accounts with the Import Tool's text-file import, POST /api/v1/domains/{domain}/accounts, a spreadsheet over REST and hmctl, or SCIM, and only then bring the mail. Moving an installation is a different subject: Upgrading to 6.3.4 for an upgrade and Moving to new hardware for a new machine. Which route You are moving Use Keeps Does not keep One person's own mailbox, by that person The webmail's Other accounts (since 6.3.4) Folders as copies, then new mail collected Rules, signatures A few mailboxes that must stay in step until the cut-over An external account with Mirror every folder on (6.3.3 and later) Folders, every message byte for byte, the five standard flags, the internal date Subscriptions, custom keywords, ACLs Many mailboxes from an IMAP server, Google Workspace or Microsoft 365 A migration, a job per mailbox (since 6.3.4, schema 6090) The above, with keywords, special-use folders, contacts and calendars Rules, signatures, shared mailboxes, ACLs, Gmail's labels as labels mbox files The Import Tool, one folder per file (Windows only) Every message, the date from the headers Flags A Maildir The Import Tool's Select Maildir (Windows only) The Maildir++ hierarchy, the flags in the file names Custom keywords Outlook PST files PST import, a migration of kind pst (since 6.3.4) Folders, messages rebuilt as Internet mail, contacts, calendar items, tasks Attachments by reference, OLE objects, distribution lists What PST import refuses Outlook itself, over IMAP Whatever Outlook uploads Anything Outlook does not put on the wire One person, from the webmail: Other accounts Since 6.3.4. Settings, Other accounts lets a person do the IMAP route for their own mailbox without an administrator. They pick the old provider (Gmail, Outlook.com, Yahoo Mail and iCloud Mail fill in the server, port and encryption), give the user name and password, choose whether to leave the mail there, and tick Bring the folders over too. It is an external account made through /api/v1/me/fetch-accounts, with these differences from one an administrator makes: The spam and virus filters are on for new mail; folders brought over arrive as copies, without the filters. The host must resolve to public addresses only, on port 110 or 995 (POP3) or 143 or 993 (IMAP), unless the administrator turns on reader_fetch_accounts_private_addresses. Schema 6104 marks such an account reader_created, and the host is judged again at every collection: a name that answers a private address later is not collected, and the error log says why (HM5909). The interval is at least 15 minutes, and a person has at most reader_fetch_accounts_max of them: 3 by default, and 0 takes the page away. A host on FetchOAuth2Hosts (outlook.office365.com by default) is refused from the page; only a server administrator adds one. Signing in rather than giving a password. Outlook.com no longer accepts a password from another mail server, and Gmail takes only an app password. Where an administrator has registered the server with Google and Microsoft, the page offers Sign in to Gmail and Sign in to Outlook.com: the person grants IMAP access there and the account logs in with XOAUTH2. No password is stored, and the permission can be taken back at the provider. The first collection then lists the folders to tick, with Gmail's All Mail, Starred and Important unticked so that nothing arrives twice. The registration is set on PUT /api/v1/settings: import_oauth_redirect_base_url (the redirect URI to register is that plus /portal/oauth/callback), import_oauth_google_client_id and import_oauth_google_client_secret, import_oauth_microsoft_client_id and import_oauth_microsoft_client_secret. The Google client needs the Gmail API and the https://mail.google.com/ scope; the Microsoft Entra registration needs the delegated IMAP.AccessAsUser.All and offline_access permissions. Until Google verifies the app, only the test users named on its consent screen can sign in. A few mailboxes that must stay in step: the mirror With Mirror every folder on, the server's own IMAP client does what imapsync does. The switch is on the account dialog's External tab in the Control Panel (Windows) and on the Deck's fetch-accounts view; over COM (Windows) it is FetchAccount.ServerType = 1 and FetchAccount.MirrorFolders = true. Create the local account. Add an external account on it: server type IMAP, the remote host, port and security (implicit TLS on 993, STARTTLS on 143), the remote credentials, and the mirror on. Decide what happens on the far side. Days to keep messages at 0 deletes each message from the remote folder once it is filed here; any other value leaves it there, so the two servers stay in step for as long as the account polls. A migration usually leaves the messages in place until the cut-over, then one last poll, and the account is disabled. Poll. Download now starts a collection at once. A large mailbox is collected over several polls, and a message is recorded as collected only after it has been filed. A mirrored message is stored byte for byte: no X-hMailServer-ExternalAccount header, no delivery, no rules, no anti-spam or anti-virus, because it is a copy of mail the other server had already accepted. The remote flags and internal date become the local ones, and Archive/2025 becomes Archive.2025. Use a new external account for the mirror. One that has been collecting the INBOX without the mirror collects it once more when the mirror is switched on. A \Noselect mailbox is skipped with a line in the application log, OnExternalAccountDownload does not fire for a mirrored message, and subscriptions, ACLs, quotas, Sieve and vacation settings on the far side are not read. Many mailboxes: migration jobs Since 6.3.4, schema 6090. A migration is a batch the server runs itself: a job per mailbox, throttled, resumed after a failure or a restart, with a report per mailbox and the contacts and calendars beside the mail. It is administered under /api/v1/migrations and in the Control Deck's Migrations view; there is no COM interface, and in 6.3.4 no Control Panel page (in 6.3.7's Control Panel the migrations are a card on Backup, restore & migration). A migration names its source: kind imap (a password per mailbox), google or microsoft365 (each mailbox signed in to by its owner), or pst; concurrency (1 to 32, 4 by default); and messages_per_minute (0 for no limit). A Google or Microsoft 365 migration reads imap.gmail.com or outlook.office365.com on port 993 over TLS, and any other host is refused. A job is queued, running, paused, done, failed or cancelled, through the phases mail, contacts, calendars and report. POST /api/v1/migrations {"name": "Old server", "host": "imap.old.example"} POST /api/v1/migrations/{id}/jobs the CSV below, or one job as JSON POST /api/v1/migrations/{id}/start GET /api/v1/migrations/{id}/jobs/{job}/report GET /api/v1/migrations/{id}/summary.csv sourceuser,secret,target [email protected],Anna's old password,[email protected] [email protected],,[email protected] One request takes up to 5,000 lines. Every line is checked before any job is made, and a bad line refuses the whole request and names itself, so nothing is half added. A job into an account another migration is copying into now is refused (409). Google Workspace and Microsoft 365. A job added with an empty secret waits for its owner: the answer carries signin_url, a one-use link for that person to open, sign in as that mailbox and grant access. A sign-in as anybody else attaches nothing, and POST .../jobs/{job}/signin makes a new link. The scopes asked for are Google's https://mail.google.com/, https://www.googleapis.com/auth/carddav and https://www.googleapis.com/auth/calendar, and Microsoft's https://outlook.office.com/IMAP.AccessAsUser.All and offline_access with Microsoft Graph Contacts.Read and Calendars.Read. A work or school tenant may need an administrator's consent. What a job does. It maps the INBOX to the INBOX, a special-use folder (\Sent, \Drafts, \Junk, \Trash, \Archive) to the account's own folder of that use whatever it is called, and everything else to the same path. It opens each folder with EXAMINE, so nothing on the source is marked read, and stores each message byte for byte with its flags, keywords and internal date. A message too large is skipped as too_large; an account over its quota pauses the job. No rule, filter or scan runs over a copied message. Contacts and calendars follow: from an IMAP server by CardDAV and CalDAV found by RFC 6764 discovery (or dav_url), from Google by its CardDAV and CalDAV, from Microsoft 365 by Microsoft Graph. A phase that cannot run is skipped with its reason and never fails a job whose mail is copied. A job is one copy, not a synchronisation: move the MX records first and migrate after, or keep a mirror for the mailboxes that must stay in step. It survives being interrupted. After every 50 messages and at the end of each folder the job writes its resume marks, and a job that has run before reads back what it wrote, so each message arrives once. A failure time may mend is retried after 1, 5 and 15 minutes and then hourly; after 24 attempts in a row without a message copied the job is failed. Wrong credentials fail it at once, and POST .../jobs/{job}/retry with {"secret": "..."} takes a mended password. Throttling is threefold: concurrency per migration; MigrationConnectionsPerHost (4 by default, 1 to 64) across every migration from one source host, because a provider counts sessions per client address; and at most 64 jobs on the server at once. Who may. Reading needs view_accounts and writing manage_accounts in the target's domain. The server administrator creates a migration, and a domain administrator then sees and adds to it. The audit trail records migrations and jobs, never a secret's value. Jobs are not carried by a backup. HM7240 (a resume mark could not be written) and HM7241 (a message could not be filed) are the two codes that reach the error log for a job from an IMAP server, Google or Microsoft 365. A PST job says the same two as HM7370 and HM7371, and its contacts and calendars phases add HM7410 and HM7411. The report says, folder by folder, how many messages the source held, how many were copied and why any were skipped: duplicate, another_folder, too_large, refused, gone, empty. mbox files, a Maildir and accounts from a text file: the Import Tool The Import Tool is a Windows program (Start menu > hMailServer > Import Tool, or Addons\ImportTool\ImportTool.exe) that works through COM, each message going to the server through Utilities.ImportMessageFromFileToIMAPFolder; there is no Import Tool on Linux. It imports a folder of mbox files into one account, one IMAP folder per file; Inbox in any case is the INBOX, and a subfolder's files are a second run. Each message is dated from its Received or Date header. mbox carries no flags the tool could read, so every imported message is unread. Select Maildir points at the directory holding cur, new and tmp, and lists the INBOX and every Maildir++ folder beside it. The flags after :2, in a file name are set on the copy: S seen, F flagged, R answered, D draft, T deleted. A colon is not allowed in a Windows file name, so the tool also reads ;2, and the same marker written with an exclamation mark in place of the colon; a copy whose names lost the info part imports unread. Accounts from a text file. The tool's other button creates or updates the accounts of one domain from a comma-separated text file, three fields a line: the account's name without the domain, its password and its size limit in MB (0 for none). Where the breach check is on, it runs for each password the tool sets through COM's Account.Password, one request per account: run a large import against your own mirror of the endpoint, or with the check off. Outlook data files: PST import Since 6.3.4. The server reads a PST itself, with a reader of this project's own written from Microsoft's published specifications and no third-party PST code. It is a migration of kind pst: one job per file, each into one account. Off until a directory is named. A job names a file, never a path, and the file is looked for only in the subdirectory named for the target account's domain inside the directory pst_import_directory names (PstImportDirectory in hm_settings, set with PUT /api/v1/settings or on the Deck's Settings page). It is empty as shipped, and while it is empty every PST job is refused with No PST import directory is set on this server. D:\PstImport\ <- pst_import_directory D:\PstImport\example.com\archive.pst <- a job for [email protected] names archive.pst Copy the file into the domain's subdirectory, where the service's account can read it. A share on another machine is refused, and so is a name that climbs out of the domain's directory. Make the migration, POST /api/v1/migrations with {"name": "Archives", "kind": "pst"}, then jobs as CSV lines of file,password,target over REST or in the Deck, or one job as JSON with hmctl api POST /api/v1/migrations/{id}/jobs. There is no Import Tool button for it and no COM route. Start it. It needs manage_accounts and manage_mailbox in the target's domain. What comes in. The folders a person sees in Outlook, with Sent Items, Deleted Items, Drafts and Junk E-mail found by what the store says they are, never by their names. Every message is rebuilt as Internet mail, deterministically, so a resumed job knows what it filed. Read, unsent, flagged and replied state become \Seen, \Draft, \Flagged and \Answered, forwarded the keyword $Forwarded, categories keywords. Contacts go into the address book, calendar items and tasks into the calendars, notes and journal entries into mail folders as messages. ANSI files (Outlook 97 to 2002) are read. What it refuses, with a sentence saying what to do: the 4K-page layout Outlook 2013 and later write for an OST, an OST caching an Exchange mailbox, a file under Windows Information Protection, and a missing or wrong password. A file Outlook still has open pauses the job. A message over 128 MB of text and data together is left out and named. Migration.md is candid about its evidence: no password-protected PST and no OST from Outlook were at hand. The reader runs in a process of its own (hMailServer.exe --pst-read on Windows, hmailserver --pst-read on Linux, not a command for an administrator), killed on a pause, a cancel or a stop, or when it has not answered in ten minutes. A file that crashes it costs one message, not the service. This is crash containment, not a sandbox: the reader runs as the service's own account, bounded in memory (2 GB committed on Windows, 4 GB of address space on Linux). The fixture API.PstImport runs on Windows; nothing runs it on Linux yet. What is not migrated Rules and filters, signatures, out-of-office replies and forwarding: make them again here. Shared mailboxes and permissions; a Microsoft 365 shared mailbox, which nobody signs in as, cannot be a job. Subscriptions: every folder is created subscribed. Gmail's labels as labels. A google migration copies each message once, and the star arrives as \Flagged. Contact groups; from Microsoft 365, the default contacts folder and calendar only. A mailbox already here: renaming it, or moving it to another domain Do not copy it into a second account: that loses everything hanging off the account id, which is its rules, folders, application passwords, second factor, contacts, calendars and role. Move or rename (since 6.3.4) keeps the account's row, and leaves the old address as an alias unless you say otherwise. Relocating an installation, and moving or renaming a mailbox has where it is done, what moves and what is refused. Where to read more The wiki page: Migration The document, with every field, limit and refusal: Migration.md Renaming and moving a mailbox: MailboxMove.md The documentation page: Importing accounts and mail, the Import Tool On this forum: The Control Deck, where the Migrations view is, and The webmail portal at /portal, where Other accounts is.
  • 0 Votes
    1 Posts
    136 Views
    ProgressiverobotP
    Written for 6.3.4. hMailServer 6.3.7 (17 October 2026) changes some of what a client gets. IMAP COPY and MOVE by message number read their set in the client's numbering, and a set that names a message another session has just expunged is refused NO [EXPUNGEISSUED] for the client to send again; a COPY or MOVE that fails part way leaves the destination as it was; SEARCH, SORT and THREAD ask a criterion named again beside itself once; and FETCH BODY[N.MIME], and BODY[N] of a multipart, are the stored octets. POP3 accepts the UTF8 classic Outlook for Windows (2016 to 2024) sends after the login, until the session's first STAT, LIST, UIDL, RETR, TOP, DELE or RSET, so its downloads work again. SMTP, POP3 and ManageSieve refuse a SASL PLAIN sign-in that asks to act as another account. The IMAP and POP3 listeners can take the client's address from a PROXY protocol header, as the SMTP listener does, each from the peers on a list of its own, both off by default. The send-as grant now bears on DKIM too: an authenticated submission is signed as another hosted domain only when its account may send as the address its From names - its own, an alias pointing at it, a mailbox that granted it the post right, an address it proved, or a masked address of its own - and is otherwise accepted and sent unsigned as that domain. See the 6.3.7 announcement. hMailServer 6.3.8 (2 November 2026) signs a name in to an account only when it is the account's stored address, compared in lower case after a domain alias and the default domain, on IMAP, POP3 and SMTP alike, SCRAM-SHA-256 among them: a client that signs in with another spelling of the address, in more than the case of the letters A to Z, or with white space at either end, may no longer sign in, since such a name fails as a name that does not exist fails and is counted as a failure. Correct the name in the client. See the 6.3.8 announcement. This topic is the server side of IMAP, POP3 and SMTP in hMailServer 6.3.4: what each listener advertises and which switch gates it, search limits and the full-text index, QRESYNC's expunge history, connection limits, shared mailboxes, and what 6.3.4 fixed that a client may notice. Know this first: a capability missing from an answer is nearly always a switch or the session's state, not a fault. Two IMAP switches ship off, and since 6.3.4 IMAP offers STARTTLS only before TLS and sign-in, and COMPRESS=DEFLATE only after sign-in. What a mail client needs is in Connecting a mail client; the ACL rights table is in Aliases, distribution lists, mailing lists and public folders. Seeing what the server advertises Ask the server, from any machine with OpenSSL. For SMTP type EHLO test.example.org; for IMAP, CAPABILITY: openssl s_client -connect mail.yourcompany.com:25 -starttls smtp -quiet openssl s_client -connect mail.yourcompany.com:993 -quiet On 6.3.4 ask IMAP before LOGIN and after: the answers differ by design. For POP3, connect to 995 the same way and send CAPA. Ports 993 and 995 exist only once you have created them (Connections & protocols → TCP/IP ports in the Windows Control Panel, or the Control Deck). IMAP: what is always there On every connection, as in 6.3.3: IMAP4 IMAP4rev1 IMAP4rev2 CHILDREN THREAD=ORDEREDSUBJECT THREAD=REFERENCES NAMESPACE RIGHTS=texk MOVE ID SPECIAL-USE CREATE-SPECIAL-USE UNSELECT UIDPLUS ENABLE STATUS=SIZE ESEARCH CONDSTORE QRESYNC LIST-EXTENDED SEARCHRES WITHIN UTF8=ACCEPT LIST-STATUS PREVIEW MULTIAPPEND REPLACE SAVEDATE METADATA OBJECTID BINARY LITERAL- APPENDLIMIT APPENDLIMIT is bare before authentication and APPENDLIMIT=<bytes> after. LITERAL- caps non-synchronising literals at 4096 bytes, so an oversized APPEND can still be refused with TOOBIG. A client opts in to IMAP4rev2 per session with ENABLE IMAP4rev2, which implies UTF8=ACCEPT. ENABLE recognises exactly four names: QRESYNC (implies CONDSTORE), CONDSTORE, UTF8=ACCEPT and IMAP4rev2. After ENABLE IMAP4rev2 the session drops the RECENT response and the [UNSEEN] code on SELECT and EXAMINE, drops RECENT as a STATUS item, and answers a SEARCH with no RETURN options as ESEARCH. IMAP: what is gated, and by what Capability Advertised when Shipped IDLE enableimapidle is on On QUOTA QUOTA=RES-STORAGE enableimapquota is on On SORT enableimapsort is on On ACL enableimapacl is on; it also switches the #Users namespace On AUTH=PLAIN, AUTH=SCRAM-SHA-256 EnableImapSASLPlain is on and authentication is available Off SASL-IR EnableImapSASLInitialResponse is on Off COMPRESS=DEFLATE IMAPCompressionEnabled=1, the client has signed in (since 6.3.4), and the session is not yet compressed On STARTTLS The port is STARTTLS-optional or -required, TLS is not active, and (since 6.3.4) the client has not signed in Per port LOGINDISABLED Authentication is refused on this cleartext connection (STARTTLS-required port, or RequireTLSForAuth on the IP range) Per range The rest depend on the connection: AUTH=SCRAM-SHA-256-PLUS only on TLS (and behind the same SASL switch), AUTH=XOAUTH2 AUTH=OAUTHBEARER with OAuth2Enabled and, unless OAuth2RequireTLS=0, only over TLS, AUTH=EXTERNAL on a verified client certificate that names an address, and UNAUTHENTICATE once signed in. IDLE reports changes in the selected folder (EXISTS, RECENT, EXPUNGE, FLAGS) as they happen. A folder another client has just created is seen at the next folder-list refresh, as there is no IMAP NOTIFY; that is IMAP, not a fault. QUOTA answers with one unnamed root, "", and a STORAGE resource in kilobytes from the account's maximum size; an account with no limit gets an empty list. SETQUOTA is refused, because the quota is the administrator's. Refusals of APPEND, COPY and MOVE for a full mailbox carry OVERQUOTA. SORT: with message indexing off, as it ships, SORT reads each message's header from disk. EnableImapSASLPlain gates SCRAM as well as PLAIN, despite its name. Roadmap.md says it gates the whole AUTHENTICATE command, while the Capabilities wiki gives OAuth2 and EXTERNAL conditions of their own: with it off, test XOAUTH2, OAUTHBEARER and EXTERNAL over IMAP before relying on them. COMPRESS DEFLATE (RFC 4978) compresses both directions of the rest of the session; a client that does not ask is unaffected. A second one is NO [COMPRESSIONACTIVE], STARTTLS under compression is BAD, and IMAPCompressionEnabled=0 withdraws it, the command then answering BAD like an unknown one. POP3 and SMTP: the same question POP3 CAPA always carries UIDL, TOP, RESP-CODES, AUTH-RESP-CODE, IMPLEMENTATION hMailServer, PIPELINING, UTF8 and EXPIRE NEVER. The SASL mechanisms depend on TLS, STLS on the port, and LOGIN-DELAY <n> appears only when Pop3LoginDelaySeconds is above 0 (0 ships). That key advertises and enforces a minimum interval between sign-ins, refusing an early one with -ERR [LOGIN-DELAY] …; on Windows it is the POP3 tab's card How often a client may check for mail. SMTP EHLO always carries SIZE <n> (the maximum message size in KB times 1024; bare SIZE when 0), 8BITMIME, PIPELINING, CHUNKING, BINARYMIME, SMTPUTF8, ENHANCEDSTATUSCODES, DSN and HELP. BINARYMIME is for local delivery: a recipient needing onward relay is refused at RCPT TO with 554 5.6.3. Conditionally: XCLIENT only when SMTPXClientEnabled=1 and the real peer is in SMTPXClientTrustedIPs; an untrusted peer that tries it gets 550. STARTTLS on a cleartext connection to a STARTTLS-optional or -required port. AUTH only when authentication is enabled, withheld on cleartext when the port requires STARTTLS or the range sets RequireTLSForAuth, and never on the ports in DisableAUTHList. Not a keyword, but decided the same way: the HAProxy PROXY protocol is accepted only with SMTPProxyProtocolEnabled=1 and from a peer in SMTPProxyProtocolTrustedIPs, and nothing in EHLO announces it. On SMTP and POP3 the AUTH line and its SASL responses take up to 12,288 octets; every other line keeps 510 (SMTP) or 500 (POP3). What 6.3.4 added to SMTP is refusals, not capabilities. Where the switches are set, and when a change applies What Windows Control Panel Elsewhere Applies IDLE, QUOTA, SORT, ACL, the two SASL switches, the connection limits Connections & protocols → Protocols, IMAP, SMTP and POP3 tabs COM Settings (IMAPIdleEnabled and its neighbours); REST PUT /api/v1/settings (imap_idle_enabled, imap_quota_enabled, imap_sort_enabled, imap_acl_enabled, imap_sasl_plain_enabled, imap_sasl_initial_response_enabled); the Deck's Settings view; hmctl settings set At once Message indexing Maintenance → Performance, Indexing tab COM Settings.MessageIndexing; PUT /api/v1/settings/indexing (enabled); hmctl settings, group indexing At once IMAPCompressionEnabled, IMAPSearchTimeout, IMAPSearchMaxMegabytes, IMAPExpungeRetentionRecords, Pop3LoginDelaySeconds, IndexerFullText and its tuning keys Cards on the IMAP and POP3 tabs; the Indexing tab COM Settings.SetIniSetting; PUT /api/v1/settings/ini/{name} (administrator password only); hmctl ini; on Linux hmailserver --set-setting NAME=VALUE. No Deck page When saved The Control Panel and COM are Windows-only. The last row's keys were the [Settings] section of hMailServer.ini; since 6.3.4 the database holds them, none of them waits for a reinitialise or a restart (docs/SettingsApply.md), and the server does not take a line edited in the file, so set them through an interface. Settings: when a save takes effect covers the store, HM5804, and a value stored by --set-setting while the service runs. The REST lines assume the listener on 127.0.0.1:8443, as the REST API wiki's examples do; RestApiPort ships at 0 (off) and waits for a reinitialise. # Switch IDLE off; in effect when the answer comes back curl -u Administrator:your-admin-password -X PUT -H "Content-Type: application/json" \ -d '{"imap_idle_enabled":false}' http://127.0.0.1:8443/api/v1/settings # A [Settings] key: the administrator password only, never an API key curl -u Administrator:your-admin-password -X PUT -H "Content-Type: application/json" \ -d '{"value":"120"}' http://127.0.0.1:8443/api/v1/settings/ini/IMAPSearchTimeout # On Linux, then a restart so the running server takes it sudo hmailserver --set-setting IMAPSearchTimeout=120 sudo systemctl restart hmailserver Search: two ceilings and the full-text index Without the full-text index, SEARCH BODY and TEXT read every message in the mailbox, attachments whose media type is text included (decoded, bounded at 1 MB). Two ceilings, measured from the moment a command starts and never re-armed by progress, bound SEARCH, SORT and THREAD: IMAPSearchTimeout (60 seconds) and IMAPSearchMaxMegabytes (2048 MB of message content read); 0 turns either off. They are the IMAP tab's card IMAP search limits, and README.md says to raise them for mailboxes of several hundred thousand messages. What a client gets at a ceiling is stated two ways. Roadmap.md records NO with RFC 9051 LIMIT and no untagged result, so a cut-short list cannot pass for a complete one; README.md's comment beside IMAPSearchTimeout says the search returns the matches found so far. Until that is settled, treat a search that hit a ceiling as incomplete, and let nothing act on its result in bulk. The full-text index is off, and needs two switches: IndexerFullText=1 indexes nothing unless message indexing (Settings.MessageIndexing) is on too. It costs a term table of a few kilobytes per message and a backfill pass over every message already delivered, which is why no upgrade turns it on. The index can only prove that a message cannot match; everything else is read and scanned as before, so results are identical on or off. The webmail's search and eDiscovery use the same filter. Key Default What it does IndexerFullTextBatchSize 250 (1 to 100000) Messages one backfill pass reads before the cursor is saved and the thread pauses IndexerFullTextMinTokenLength 3 (3 to 64) The shortest search string the index answers for IndexerFullTextMaxTokensPerMessage 2048 (64 to 1000000) Distinct terms before a message is marked always-scanned instead of indexed The Indexing tab's Index now, and show how far behind it is and Discard the index and rebuild it are POST /api/v1/settings/indexing/index and /clear over REST, and Index() and Clear() over COM, where TotalIndexedCount against TotalMessageCount shows a rebuild's progress. With mailboxes encrypted at rest, the indexed count stays short by their messages for good: those are never indexed. QRESYNC: how much expunge history is kept IMAPExpungeRetentionRecords keeps the newest 5000 expunge records per mailbox (0 keeps all), pruned every twelve hours and once at service start; on Windows it is the card Change history for synchronising clients. The newest is never removed. A client whose last sync is older than what is kept gets a full resync, never a wrong one: every UID in its range that the mailbox does not hold. An installation upgraded from a release older than 6.2.23-alpha1 prunes the table in one pass at its first start. README.md says 0 defers that prune, and an IMAPExpungeRetentionRecords line of 0 added to [Settings] before the upgrade is taken: 6.3.4's first start adopts from the file a key the database has never held, and before 6.2.23-alpha1 the database held this one only if the file had the line. Restart the old service once after adding or changing it (Upgrading hMailServer wiki, 18.3, step 6): CHANGELOG.md's note that a line edited to prepare an upgrade is put back concerns a key the database already holds, and that restart settles it. Set it back to 5000 afterwards through an interface; Upgrading to 6.3.4 has the rest of the order. Connection limits and what guards them MaxSMTPConnections, MaxIMAPConnections and MaxPOP3Connections are on the Protocols page (REST max_smtp_connections, max_imap_connections, max_pop3_connections). None has a limit by default; SMTP and IMAP ship at 0, no cap. The Services tab turns a protocol off altogether (ServiceSMTP, ServiceIMAP, ServicePOP3). Watch hmailserver_sessions{protocol} on /metrics (off until MetricsServerPort is set, which waits for a reinitialise) or sessions in GET /api/v1/status. Around the limits: auto-ban counts failed sign-ins per IP across SMTP, IMAP, POP3, ManageSieve and REST (on: 3 in 30 minutes, a 60-minute ban); LogonTarpitSeconds (off) delays each failed sign-in's refusal; a second POP3 session on one mailbox gets -ERR [IN-USE]; and since 6.3.4 an IMAP LIST or LSUB pattern over 8,192 characters, or more than 32 patterns in one LIST, is answered BAD. The submission rate limit and the tarpits are in IP ranges, auto-ban, lockout and tarpits; refusing a connection by country is in allow and block lists and country blocking. Opening a mailbox to a colleague Shared and delegated mailboxes are IMAP ACL (RFC 4314). The owner opens a folder to another account, and it appears to that account under the Other Users namespace as #[email protected]. No administrator step is needed: any account whose client speaks SETACL can do it, and the audit trail records no row for it. Leave ACL on. With it off, #Users stops existing (NAMESPACE advertises NIL), public folders are open to everyone, and the send-as grant is not honoured. The owner grants rights from an IMAP client with ACL support. An administrator can do it over REST: GET on /api/v1/accounts/{address}/folders gives the folder's id, and /api/v1/accounts/{address}/folders/{id}/permissions lists, adds, changes and removes entries (since 6.3.3; writes need a full key). On Windows, COM has IMAPFolderPermissions.Add. The grantee is an account, a group (/api/v1/groups, since 6.3.4), or Anyone, which is every authenticated account on the server. Grant l, or the folder does not exist for the colleague. r reads, s changes read state, i, t and e file and delete, and p on the INBOX is the send-as grant. Grant on each top-level folder needed. A right is decided at the nearest folder up the owner's tree that has any entries, and entries are not merged: a grant on INBOX reaches its sub-folders that have none of their own, not the Sent folder, and one entry on a sub-folder cuts it off from the parent's. Over SMTP the p grant counts only while SmtpAuthenticatedSenderCheck is on, and it ships off: until then nothing constrains an authenticated MAIL FROM, so any account can send as the mailbox, or as anyone else. Turned on, it applies to every authenticated session on the server; the addresses it then allows are in who may send as whom. In the colleague's client, a pane of subscribed folders shows only the ones the owner subscribed to; the webmail shows them under Shared by <owner>. What follows from sharing: \Seen is stored on the message, not per person: with s, a delegate marks a message read for everyone; with lr alone they leave no trace, and their client cannot track what they have read. Since 6.3.4 an APPEND into a #Users folder is charged to the owner's quota, as COPY and MOVE already were. A delegate reads a folder of a mailbox encrypted at rest only while the owner's key is open; otherwise a FETCH that reads the message answers NO [UNAVAILABLE], and copying out is refused. In the webmail a read-only share refuses a flag or a delete with 403, a message cannot move between one's own mailbox and a shared one, and the owner cannot grant access from the page. Since 6.3.4 a restore puts each folder's access grants back. Every LIST runs one more query while ACL is on. What 6.3.4 fixed that a client may notice Where Dovecot's imaptest found IMAP answering other than the RFCs say (\Seen without .PEEK, APPEND byte for byte, SORT and THREAD order, among others), Connecting a mail client has the list. The rest: What a client did What it gets since 6.3.4 Sent STARTTLS after LOGIN, or inside TLS BAD, and no STARTTLS in CAPABILITY Sent COMPRESS DEFLATE before signing in NO Appended over a compressed connection, data inflating past the 250,000-octet receive buffer The whole message, where it was stored cut short or never finished Read ENVELOPE with a backslash in Date, or BODYSTRUCTURE with a quote or backslash in a part's parameters A structure that parses: the date's backslashes left out; quotes and backslashes escaped, a control character sent as a space Fetched a message the server cannot read NO [UNAVAILABLE] for a closed key; a damaged one (HM7350) left out, the rest fetched and the command ending NO - not OK with an empty ENVELOPE Changed one message's flags from two sessions at once Both changes kept; STORE ... (UNCHANGEDSINCE n) tested in the same step Went on sending a MULTIAPPEND's later literals after a refusal, one over the maximum message size (and 1 MB) The connection closed with BAD [TOOBIG], where it was read whatever its size Fetched a message only an unreachable object store holds IMAP NO [UNAVAILABLE], POP3 -ERR [SYS/TEMP] (object storage is new in 6.3.4, and off) Two heap-corruption aborts are gone as well (two sessions on one message's keywords; LIST beside folder changes). Most of these were in 6.3.3 too. What it does not do No APOP or CRAM-MD5 on POP3, and THREADID is answered NIL. Delegation is not measured in Thunderbird or Outlook, and an Outlook IMAP profile never acts on the Autodiscover answer's delegated mailboxes; the #Users namespace is what works. Where to read more Wiki: Capabilities and Configuration, Settings Reference (9.12), Connecting a Mail Client, Aliases, Lists and Public Folders (13.3), Control Panel Reference (7.5), Security Hardening (17.5, 17.7), Changes Since 6.2.10 (4.3, 4.4). At the 6.3.4 tag: SettingsApply.md, SendAs.md, EncryptionAtRest.md, DeckParity.md, README.md, CHANGELOG.md (6.3.4, IMAP, POP3 and the webmail), Roadmap.md. The public documentation: 34.3 IMAP details worth knowing, 30.3 IMAP folders and permissions. On this forum: Upgrading to 6.3.4, The Control Deck, The REST API: turning it on, Message storage: object storage and encryption at rest, What runs out first: pools, connections, large folders and Monitoring and health. A client that does not get on with these answers is a bug: a GitLab issue or, without a GitLab account, an email to contact-project+hmailserver-hmailserver-86730559-issue-@incoming.gitlab.com, filed as a confidential issue (SUPPORT.md). A vulnerability goes only by SECURITY.md's routes.
  • The webmail portal at /portal

    Pinned Webmail, portal & Control Deck webmail imap
    1
    0 Votes
    1 Posts
    122 Views
    ProgressiverobotP
    /portal is the self-service webmail hMailServer serves out of its REST listener. A mailbox owner signs in with their own address and password and gets folders, search, compose, drafts, flags and inline images. It has contacts too, and since 6.3.4 calendars and tasks and the organisation's directory. CardDAV (added in 6.3.3) and CalDAV (6.3.4), for other clients, are served on the web services HTTPS listener, not this one. It is compiled into the binary. There is no web root to deploy and no file to lose. At 6.3.4 the page is Portal.html and Portal.js, with its manifest, service worker, language catalogues and OpenPGP and S/MIME modules, all embedded at build time. So if the Control Deck answers and the portal does not, an absent file is not the cause. Check you are asking for /portal exactly, because the server answers the page at that path alone (what it serves below /portal/ since 6.3.4 are other pages: single sign-on, password reset, password-protected messages), and check no proxy is rewriting it. 36.14 has the rest of the symptom table. It fetches nothing externally. No font, no image, no stylesheet, no script from a CDN. Its Content-Security-Policy is default-src 'none'; script-src 'self'; style-src 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self'; frame-src 'self' blob:; manifest-src 'self'; worker-src 'self'; form-action 'none'; frame-ancestors 'none'; base-uri 'none'. Note img-src 'self' data: blob:, which permits no image from any other host; 'self' is there for images the server answers from its own routes, such as a colleague's directory photo. A sender's HTML is never merged into the page. It goes into an iframe sandboxed without allow-scripts and without allow-same-origin, under its own policy of img-src data:, so a remote tracking pixel stays in the markup and is blocked. Opening a message tells its sender nothing unless the reader chooses otherwise: showing remote content, for that message or always for that sender, serves the message under img-src data: https: http:, and the pixel then loads. 36.10 explains why the obvious design cannot work. It is not an administration interface. Everything the portal does with a mailbox is under /api/v1/me/, and those routes answer to an account's own credentials and to nothing else. The administrator password is refused on every one of them, and so is an API key. Administration is the other page, the Control Deck at /. Both sit on one listener behind one switch, RestApiPort, so exposing one exposes the other. If mailbox owners reach /portal from the internet, split the surfaces at a reverse proxy: the webmail public, /api/v1/session public because both pages sign in through it, and / plus the administration routes under /api/v1/ on the internal network. At 6.3.4 the webmail is more than /portal, /portal.js and /api/v1/me/*: it loads /portal-*.js, /portal.webmanifest, /portal-sw.js and /portal-lang/, and, for the features you switch on, people who are not signed in reach pages and routes such as /portal/*, /files/, /confidential/, /lists/, /held/, /recovery/verify, /api/v1/password-reset, /api/v1/passkeys/challenge and /api/v1/protected/. Check the proxy's list against what you use. 36.13 IMAP clients are unaffected. The portal is another client against the same store. A flag change requires the rights STORE requires, and every IMAP session on the folder is told. A move is IMAP MOVE: a copy with a new UID, then the original expunged. Folder create, rename and delete run IMAP's checks in IMAP's order and refuse with IMAP's own sentences. The new-mail probe reads the cached per-folder collection that IMAP, POP3 and delivery already share, so polling opens no message file. Outlook, Thunderbird, Apple Mail and phones carry on unchanged, and Roundcube pointed at the IMAP port remains a reasonable choice. Full reference: 36.6 The portal: what a user gets.
  • 0 Votes
    1 Posts
    51 Views
    ProgressiverobotP
    6.2.28 is the first release that can update itself. A scheduled task reads this project's release feed and the Status page reports what it found; fetching an installer and applying it are two further, equally opt-in steps. The upgrade to 6.2.28 itself is manual. What the upgrade involved No schema change: 6031, as 6.2.27. The installer's database upgrade has nothing to do on a 6.2.27 database. Everything this release adds is off by default. UpdateCheckEnabled, RestApiPort (which the portal and the Control Deck need), IMAPCompressionEnabled and HttpProxy are all opt-in. A server upgraded without touching its settings behaves exactly as 6.2.27 did. Known and unfixed: the Control Deck reads but does not write, and holds the administrator password in sessionStorage while it is open. The regression suite runs on Windows only. What is in it Updates. UpdateCheckEnabled=0 is the default and nothing happens until it is set: no request, no identifier, no counts. Turned on, the feed is read every UpdateCheckHours (24 by default). An installer is verified against its Sigstore bundle before it runs: the certificate chains to Fulcio, the identity and issuer are this project's release workflow, and the entry is in the public transparency log. These releases are not Authenticode-signed, so UpdateRequireAuthenticode=1 refuses every one of them, and the Sigstore check cannot be turned off. hMailServer.Updater.exe stops the service, waits UpdateServiceWaitSeconds (180) for it to come back, and reinstalls the previous version if it does not. Webmail. /portal on the REST listener, with /api/v1/me behind it. It answers to the account's own credentials only: no administrator password, no API key. Read, send, search, attachments, the account's own quarantine, Sieve script and password change. A real HTTP server. The REST API and web services move off a single-threaded HTTP/1.0 loop onto HttpServer: HTTP/1.1 on Boost.Asio with keep-alive, chunked bodies, and header and body deadlines. IMAP COMPRESS=DEFLATE (RFC 4978). Advertised until compression is on and refused afterwards, as the RFC requires. STARTTLS is refused once a session is compressed. HttpProxy=host:port sends every web request the server makes as a client through a forward proxy. CONNECT for https, with the same certificate verification as a direct connection. No proxy credentials. Fixed (GitHub issue 156). A masked password in the Control Panel was typed backwards from the second character: 12345678 became 18765432. It hit IME commits and some keyboard layouts. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    50 Views
    ProgressiverobotP
    The DNSSEC validator that guards DANE and the SPF, DKIM and DMARC lookups treated a DS query answered with nothing as an unsigned delegation. That is exactly what an attacker stripping the DS in transit shows a resolver: a signed zone quietly became unsigned, and DANE and validated TXT went with it. Anyone relying on DANE or on DNSSEC-validated SPF, DKIM or DMARC was affected. What the upgrade involved Schema 6030 to 6031: one column on hm_fetchaccounts, added by the installer's database upgrade on every backend. From 6.2.25 or 6.2.26, run the installer. From earlier, read the 6.2.25 and 6.2.24 notes first. Security A missing DS is now proved missing (RFC 4035 §5.2, RFC 5155 §8). The resolver keeps the authority section of a negative answer and requires the parent's proof there: an NSEC at the delegation name with NS set and DS clear, an NSEC3 whose hashed owner matches with the same bits, or an Opt-Out NSEC3 covering the hash, each signed by the parent's key. A proof that fails to verify, has expired, claims a DS exists, or belongs to another name is no proof, and a delegation without one under a signed parent is now Bogus and blocked rather than Insecure. An unsigned parent, or a resolver that cannot be reached, still yields Insecure. The chain result is exposed as Diagnostics.DnssecChainStatus. Mail flow FetchAccount.MirrorFolders (schema 6031; "Mirror every folder" on an IMAP external account in the Control Panel) collects each remote mailbox into the local folder of the same name: every message byte for byte, with its \Seen \Flagged \Answered \Draft \Deleted flags, its internal date, and the remote hierarchy delimiter mapped to the local one. Nothing is delivered, so no rule, anti-spam or anti-virus touches a copy. Each folder records what it has collected, so a second poll takes only what is new. Days to keep messages 0 makes it a move. The Import Tool reads a Maildir: the INBOX and every Maildir++ folder beside it, with the flags the file names carry (;2, and !2, as well as :2,) and line endings made CRLF. An import into a folder a client has open now refreshes it, as a delivery does. Migration.md documents each route in and what it keeps: IMAP, mbox, Maildir, Outlook through IMAP (PST is deliberately not parsed), and bulk accounts. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    52 Views
    ProgressiverobotP
    6.2.24 is the stable release of the work carried by the 6.2.22 pre-releases and the 6.2.23 alphas. If you are on 6.2.21, all of it arrives at once. The headline is mail that was being lost silently. A delegated IMAP APPEND, COPY or MOVE filed the bytes under the wrong account, and a delegated MOVE destroyed the only readable copy. Anyone using shared or delegated mailboxes was exposed. Thunderbird also had every Sent copy refused once UTF8=ACCEPT was enabled (GitHub issue 53). What the upgrade involved The schema moves from 6011 to 6025 in fourteen one-way steps. DBUpdater runs them in order and resumes from wherever a partial upgrade stopped. There is no downgrade: an older server refuses a newer database rather than misreading it. Take a database backup and a data-directory backup with your backend's own tools first. Step 6024 to 6025 rewrites hm_messages.messageflags from tinyint to smallint on MS SQL, SQL Server Compact and MySQL/MariaDB. That is a table rewrite on the largest table you have, holding locks for its duration, so size the maintenance window by your message count. PostgreSQL is already smallint and unaffected. Changes that take effect without a switch MAIL FROM or AUTH straight after the STARTTLS handshake, with no second EHLO, now gets 503 Bad sequence of commands. RFC 3207 has always required that EHLO. A home-grown submission script will find out here. For mail arriving through a relay or fetched from an external account, the DNSBL, SPF and HELO tests now run against the address the relay observed, not the first bracketed value in the Received header, which the sender could set. If you tuned scores around the old behaviour, expect verdicts to move. Mail is refused with a temporary error when free space falls below 100 MB (MinimumFreeDiskSpaceMB, Server settings). Set it to 0 for the old behaviour. Per-account out-of-office now honours the RFC 3834 suppressions that previously applied only to the domain-wide reply. Early-bound COM clients built against a 6.2.22 pre-release interop assembly must be recompiled. Anything built against 6.2.21, and all late-bound scripts, are unaffected. Two further anti-spam bypasses are closed. A forged header could steer a per-account spam override into un-marking the sender's own mail. RSET before EHLO, or STARTTLS without a fresh EHLO, opened a transaction with an empty HELO host, skipping the HELO-host test and the script events. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    193 Views
    ProgressiverobotP
    This was an alpha. Everything in it shipped in 6.2.24. Nothing here should be installed today. Thunderbird 128 and later could not save a single Sent copy. Every message went out over SMTP and nothing was ever stored, with only a per-machine client setting as a workaround (GitHub issue 53). Two ways a sender could steer the anti-spam tests are also closed here. What the upgrade involved This is an alpha because one of the fixes changes what a non-conforming client sees. Relayed and fetched mail is now tested against a different address. The Received parser takes the last observed address before by, ignores values marked as HELO-supplied, and keeps a header whose host name is not a valid domain name. If you sit behind an incoming relay and have tuned scores around the old behaviour, expect verdicts to move. MAIL FROM straight after a STARTTLS handshake with no fresh EHLO now gets 503 Bad sequence of commands, as RFC 3207 section 4.2 requires. If you have a home-grown submission script that skips the second EHLO, this is the release that tells you. Changes IMAP APPEND: once a client enables UTF8=ACCEPT, RFC 6855 lets it wrap the message as UTF8 (~{n} plus a closing ). The parser counted parentheses across the whole line and refused with BAD APPEND Command requires at least 2 parameter before reading a byte. The wrapper is now stripped ahead of the parser, including the non-synchronizing ~{n+} form and later messages of a MULTIAPPEND. Anti-spam bypass: the parser took the first bracketed value after from, which is the HELO literal the client chose, and skipped any header whose host name was not a valid domain (my_pc). DNSBL, SPF and the HELO-host test could be skipped entirely. Two assert(0) on sender-reachable input are gone with it. RSET before EHLO no longer opens a transaction on its own. That had let MAIL FROM through with an empty HELO host, skipping the OnHELO/OnEHLO events. A PTR answer carrying the trailing dot (1.0.0.127.in-addr.arpa.) no longer empties the result. That had been failing open in the HELO and reverse-DNS spam tests. hMailServer.exe is built with /guard:cf in both configurations (GitHub issue 45). An unattended install whose database step fails now fails, rather than showing a suppressible message box and exiting 0. Known limitation: the weekly C++ CodeQL analysis has not run since late August. It targets a self-hosted runner that is no longer registered. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    52 Views
    ProgressiverobotP
    This was the second pre-release in the 6.2.22 line. Everything in it shipped in 6.2.24. Nothing here should be installed today. hMailServer has consumed DMARC policy for years and produced nothing for the domains whose mail it receives. This pre-release adds DMARC aggregate reporting (rua, RFC 7489). Every evaluation is aggregated per UTC day and per policy domain, passes included, and the Appendix C XML is mailed to the addresses a domain asks for with rua=. It stays inert until DmarcRptFromAddress is set. What the upgrade involved The database schema moves to 6015. Upgrading from pre1 requires DBUpdater. Known limitations: FETCH BINARY on a composite section returns an empty literal, so BINARY[], multipart and message/rfc822 sections come back empty (leaf parts are correct). DMARC report data lives in memory, so a restart before the daily send loses that day's statistics. Reporting RFC 7489 §7.1 external-destination verification is enforced. A rua target outside the policy domain's own organizational domain is used only when <policy-domain>._report._dmarc.<target-domain> says it wants the reports. Forensic (ruf) reports are deliberately not implemented. Utilities.SendTlsRptReports(IncludeCurrentDay) and its twin SendDmarcReports send what has been collected so far, not just days that are over. Both refuse, statistics preserved, when the From address is unset. Authentication AccountLockoutThreshold counts failures by the name being guessed at, so a distributed attack that never crosses any single IP's auto-ban threshold is still caught. Off by default, enforced on every path including SCRAM. A locked name gets the ordinary invalid-credentials reply, and that refusal is kept out of the per-IP auto-ban. POP3 AUTH-RESP-CODE (RFC 3206): credential failures carry [AUTH], a failed inbox load carries [SYS/TEMP]. A transient database problem made scheduled clients nag for a password that was never wrong. Anti-virus A scan that could not run was delivered with one line in the error log, indistinguishable from a clean scan. AVFailAction 0 (the default) keeps today's behaviour. 1 holds the message, re-attempts it and returns it to the sender rather than delivering it unscanned. IMAP BINARY (RFC 3516) decodes a part's Content-Transfer-Encoding server-side, and APPEND accepts the literal8 (~{n}) form. OBJECTID (RFC 8474): EMAILID follows a message through copies, MAILBOXID survives RENAME, THREADID is answered NIL. Fixes /Test no longer terminates on an unhandled exception when the machine has no network or a third party's DNS breaks. An idle server stops in about half a second rather than up to two. Nine settings reachable only by editing the ini now have Control Panel fields. Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    58 Views
    ProgressiverobotP
    This was the first pre-release in the 6.2.22 line. Everything in it shipped in 6.2.24. Nothing here should be installed today. The built-in ACME client has never completed an order against a real Let's Encrypt. If you issued certificates through hMailServer rather than an external client, it failed every time. That is fixed here (GitHub issue 34). What the upgrade involved This is a pre-release. Take a backup before installing it. Databases upgrade automatically from schema 6012 to 6014 via the bundled DBUpdater. ACME (GitHub issue 34) Boulder, the software behind Let's Encrypt staging and production, pretty-prints its JSON: "type": "http-01", with a space after the colon. The challenge locator searched for the compact form, "type":"http-01", which can never match a real response. Every issuance failed at the first authorization with "Authorization offers no http-01 challenge". The locator now tolerates any whitespace and checks that the string is genuinely a type key's value, and the real CA response shape is pinned by self-tests. Failure messages now name the domain they concern, and the no-challenge refusal includes the CA's actual response. Log lines going missing (GitHub issue 33) With Keep log files open enabled, each line sat in a ~4 KB write buffer until later lines pushed it out. On a quiet server the tail of a session stayed invisible; the reporter measured forty minutes. The logger now hands every line to the operating system as it is written. Installations without the setting were never affected. Microsoft 365 Microsoft shuts off Basic authentication for SMTP relay in December 2026. XOAUTH2 bearer login is implemented for outbound relay and for POP3 collection from external accounts. Tokens use the client-credentials flow and are cached to 80% of their lifetime. Bearer auth applies only to destinations on the configured OAuth host list; unlisted relays keep password login unchanged. POP3 collection has no password fallback, deliberately. Sieve and IMAP Sieve now implements variables (RFC 5229), editheader (5293), duplicate (7352), reject/ereject (5429), include (6609), enotify (5435), date/currentdate (5260), spamtest (5235), mailboxexists and :regex. ManageSieve gains RENAMESCRIPT and machine-readable response codes. Eleven IMAP extensions, including APPENDLIMIT (7889), LITERAL- (7888), LIST-STATUS (5819), UNAUTHENTICATE (8437), QUOTA=RES-STORAGE (9208), PREVIEW (8970), MULTIAPPEND (3502), REPLACE (8508), SAVEDATE (8514, schema 6013) and METADATA (5464, schema 6014). The delivery client now opens with EHLO on every delivery, not just routes needing TLS or authentication, and declares SIZE (RFC 1870). Still unimplemented: BINARYMIME, IMAP BINARY, CATENATE/URLAUTH, COMPRESS=DEFLATE, OBJECTID and outbound PIPELINING/CHUNKING. Equal-preference MX records are still not randomised (RFC 5321 5.1). Full release notes, checksums and signatures
  • 0 Votes
    1 Posts
    65 Views
    ProgressiverobotP
    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
    49 Views
    ProgressiverobotP
    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
    56 Views
    ProgressiverobotP
    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 (GitHub issue 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
    57 Views
    ProgressiverobotP
    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
    52 Views
    ProgressiverobotP
    hMailServer 6.2.6 added IMAP4rev2 (RFC 9051) as an opt-in session mode. The server advertises IMAP4rev2, and a client that issues ENABLE IMAP4rev2 gets RFC 9051 semantics for that connection. IMAP4rev1 behaviour is unchanged until a client opts in. The rest of the release is Control Panel and installer work. IMAP4rev2 In the opt-in mode: ESEARCH by default, \Recent and RECENT dropped from SELECT, EXAMINE and STATUS, the obsolete [UNSEEN] response code suppressed, and UTF-8 acceptance. Control Panel A central theme-aware colour-token system replaced scattered hardcoded colours. Success, warning, danger and info, and the log palette, now adapt to light, dark and high-contrast themes. A Fluent nav selection style and a brand keyboard-focus ring. Live-log colours legible on the light theme, readable data grids with balanced columns, and settings forms capped to a readable column with right-sized inputs. KPI colours that encode state, softened destructive buttons, "no activity" chart placeholders, and a Welcome page of clickable quick-action tiles. Every configurable server setting now has a GUI control: OAuth2 and external-token auth, SRS and BATV, submission and outbound rate limits, OpenTelemetry and the slow-query log, connection timeouts, delivery and queue tuning, search indexing, message archiving and other INI knobs, Logging.Device and LogFormat, cache size caps, the domain Active Directory link, and a write-only secret editor. Documented in settings.md. Two-factor authentication setup renders a real scannable QR code, with a grouped manual key and a copy button, and a larger verification field. Installer A DPI-scaled custom database-type page, modernised copy and refreshed brand imagery. The dead legacy dependency installers were removed: MSI, IE6, MDAC, JET and .NET 2.0. The server core was validated by the full regression suite, 898 of 898 tests passing, including live SpamAssassin, ClamAV against EICAR, DMARC against live DNS, and TLS 1.2 and 1.3 handshakes end to end. Full release notes, checksums and signatures