IMAP and POP3 on the server: capabilities, switches, shared mailboxes, search limits
-
Written for 6.3.4. hMailServer 6.3.7 (17 October 2026) changes some of what a client gets. IMAP
COPYandMOVEby message number read their set in the client's numbering, and a set that names a message another session has just expunged is refusedNO [EXPUNGEISSUED]for the client to send again; aCOPYorMOVEthat fails part way leaves the destination as it was;SEARCH,SORTandTHREADask a criterion named again beside itself once; andFETCH BODY[N.MIME], andBODY[N]of a multipart, are the stored octets. POP3 accepts theUTF8classic Outlook for Windows (2016 to 2024) sends after the login, until the session's firstSTAT,LIST,UIDL,RETR,TOP,DELEorRSET, 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
STARTTLSonly before TLS and sign-in, andCOMPRESS=DEFLATEonly 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 -quietOn 6.3.4 ask IMAP before
LOGINand after: the answers differ by design. For POP3, connect to 995 the same way and sendCAPA. 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- APPENDLIMITAPPENDLIMITis bare before authentication andAPPENDLIMIT=<bytes>after.LITERAL-caps non-synchronising literals at 4096 bytes, so an oversizedAPPENDcan still be refused withTOOBIG.A client opts in to IMAP4rev2 per session with
ENABLE IMAP4rev2, which impliesUTF8=ACCEPT.ENABLErecognises exactly four names:QRESYNC(impliesCONDSTORE),CONDSTORE,UTF8=ACCEPTandIMAP4rev2. AfterENABLE IMAP4rev2the session drops theRECENTresponse and the[UNSEEN]code onSELECTandEXAMINE, dropsRECENTas aSTATUSitem, and answers aSEARCHwith noRETURNoptions asESEARCH.IMAP: what is gated, and by what
Capability Advertised when Shipped IDLEenableimapidleis onOn QUOTA QUOTA=RES-STORAGEenableimapquotais onOn SORTenableimapsortis onOn ACLenableimapaclis on; it also switches the#UsersnamespaceOn AUTH=PLAIN,AUTH=SCRAM-SHA-256EnableImapSASLPlainis on and authentication is availableOff SASL-IREnableImapSASLInitialResponseis onOff COMPRESS=DEFLATEIMAPCompressionEnabled=1, the client has signed in (since 6.3.4), and the session is not yet compressedOn STARTTLSThe port is STARTTLS-optional or -required, TLS is not active, and (since 6.3.4) the client has not signed in Per port LOGINDISABLEDAuthentication is refused on this cleartext connection (STARTTLS-required port, or RequireTLSForAuthon the IP range)Per range The rest depend on the connection:
AUTH=SCRAM-SHA-256-PLUSonly on TLS (and behind the same SASL switch),AUTH=XOAUTH2 AUTH=OAUTHBEARERwithOAuth2Enabledand, unlessOAuth2RequireTLS=0, only over TLS,AUTH=EXTERNALon a verified client certificate that names an address, andUNAUTHENTICATEonce signed in.IDLEreports 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 IMAPNOTIFY; that is IMAP, not a fault.QUOTAanswers with one unnamed root,"", and aSTORAGEresource in kilobytes from the account's maximum size; an account with no limit gets an empty list.SETQUOTAis refused, because the quota is the administrator's. Refusals ofAPPEND,COPYandMOVEfor a full mailbox carryOVERQUOTA.SORT: with message indexing off, as it ships,SORTreads each message's header from disk.EnableImapSASLPlaingates SCRAM as well as PLAIN, despite its name. Roadmap.md says it gates the wholeAUTHENTICATEcommand, while the Capabilities wiki gives OAuth2 andEXTERNALconditions of their own: with it off, testXOAUTH2,OAUTHBEARERandEXTERNALover 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 isNO [COMPRESSIONACTIVE],STARTTLSunder compression isBAD, andIMAPCompressionEnabled=0withdraws it, the command then answeringBADlike an unknown one.POP3 and SMTP: the same question
POP3
CAPAalways carriesUIDL,TOP,RESP-CODES,AUTH-RESP-CODE,IMPLEMENTATION hMailServer,PIPELINING,UTF8andEXPIRE NEVER. TheSASLmechanisms depend on TLS,STLSon the port, andLOGIN-DELAY <n>appears only whenPop3LoginDelaySecondsis 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
EHLOalways carriesSIZE <n>(the maximum message size in KB times 1024; bareSIZEwhen 0),8BITMIME,PIPELINING,CHUNKING,BINARYMIME,SMTPUTF8,ENHANCEDSTATUSCODES,DSNandHELP.BINARYMIMEis for local delivery: a recipient needing onward relay is refused atRCPT TOwith 554 5.6.3. Conditionally:XCLIENTonly whenSMTPXClientEnabled=1and the real peer is inSMTPXClientTrustedIPs; an untrusted peer that tries it gets 550.STARTTLSon a cleartext connection to a STARTTLS-optional or -required port.AUTHonly when authentication is enabled, withheld on cleartext when the port requires STARTTLS or the range setsRequireTLSForAuth, and never on the ports inDisableAUTHList.- Not a keyword, but decided the same way: the HAProxy PROXY protocol is accepted only with
SMTPProxyProtocolEnabled=1and from a peer inSMTPProxyProtocolTrustedIPs, and nothing inEHLOannounces it.
On SMTP and POP3 the
AUTHline 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 limitsConnections & protocols → Protocols, IMAP, SMTP and POP3 tabs COM Settings(IMAPIdleEnabledand its neighbours); RESTPUT /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 setAt once Message indexing Maintenance → Performance, Indexing tab COM Settings.MessageIndexing;PUT /api/v1/settings/indexing(enabled);hmctl settings, groupindexingAt once IMAPCompressionEnabled,IMAPSearchTimeout,IMAPSearchMaxMegabytes,IMAPExpungeRetentionRecords,Pop3LoginDelaySeconds,IndexerFullTextand its tuning keysCards on the IMAP and POP3 tabs; the Indexing tab COM Settings.SetIniSetting;PUT /api/v1/settings/ini/{name}(administrator password only);hmctl ini; on Linuxhmailserver --set-setting NAME=VALUE. No Deck pageWhen saved The Control Panel and COM are Windows-only. The last row's keys were the
[Settings]section ofhMailServer.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-settingwhile the service runs.The REST lines assume the listener on
127.0.0.1:8443, as the REST API wiki's examples do;RestApiPortships 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 hmailserverSearch: two ceilings and the full-text index
Without the full-text index,
SEARCH BODYandTEXTread 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, boundSEARCH,SORTandTHREAD:IMAPSearchTimeout(60 seconds) andIMAPSearchMaxMegabytes(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
NOwith RFC 9051LIMITand no untagged result, so a cut-short list cannot pass for a complete one; README.md's comment besideIMAPSearchTimeoutsays 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=1indexes 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 IndexerFullTextBatchSize250 (1 to 100000) Messages one backfill pass reads before the cursor is saved and the thread pauses IndexerFullTextMinTokenLength3 (3 to 64) The shortest search string the index answers for IndexerFullTextMaxTokensPerMessage2048 (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/indexand/clearover REST, andIndex()andClear()over COM, whereTotalIndexedCountagainstTotalMessageCountshows 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
IMAPExpungeRetentionRecordskeeps 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 anIMAPExpungeRetentionRecordsline 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,MaxIMAPConnectionsandMaxPOP3Connectionsare on the Protocols page (RESTmax_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 untilMetricsServerPortis set, which waits for a reinitialise) orsessionsinGET /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 IMAPLISTorLSUBpattern over 8,192 characters, or more than 32 patterns in oneLIST, is answeredBAD. 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 speaksSETACLcan do it, and the audit trail records no row for it.- Leave ACL on. With it off,
#Usersstops existing (NAMESPACEadvertisesNIL), 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:
GETon/api/v1/accounts/{address}/foldersgives the folder's id, and/api/v1/accounts/{address}/folders/{id}/permissionslists, adds, changes and removes entries (since 6.3.3; writes need a full key). On Windows, COM hasIMAPFolderPermissions.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.rreads,schanges read state,i,tandefile and delete, andpon 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
pgrant counts only whileSmtpAuthenticatedSenderCheckis on, and it ships off: until then nothing constrains an authenticatedMAIL 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:
\Seenis stored on the message, not per person: withs, a delegate marks a message read for everyone; withlralone they leave no trace, and their client cannot track what they have read.- Since 6.3.4 an
APPENDinto a#Usersfolder is charged to the owner's quota, asCOPYandMOVEalready were. - A delegate reads a folder of a mailbox encrypted at rest only while the owner's key is open; otherwise a
FETCHthat reads the message answersNO [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
LISTruns one more query while ACL is on.
What 6.3.4 fixed that a client may notice
Where Dovecot's
imaptestfound IMAP answering other than the RFCs say (\Seenwithout.PEEK,APPENDbyte for byte,SORTandTHREADorder, among others), Connecting a mail client has the list. The rest:What a client did What it gets since 6.3.4 Sent STARTTLSafterLOGIN, or inside TLSBAD, and noSTARTTLSinCAPABILITYSent COMPRESS DEFLATEbefore signing inNOAppended 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 ENVELOPEwith a backslash inDate, orBODYSTRUCTUREwith a quote or backslash in a part's parametersA 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 endingNO- notOKwith an emptyENVELOPEChanged one message's flags from two sessions at once Both changes kept; STORE ... (UNCHANGEDSINCE n)tested in the same stepWent 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 sizeFetched 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;
LISTbeside folder changes). Most of these were in 6.3.3 too.What it does not do
- No APOP or CRAM-MD5 on POP3, and
THREADIDis answeredNIL. - Delegation is not measured in Thunderbird or Outlook, and an Outlook IMAP profile never acts on the Autodiscover answer's delegated mailboxes; the
#Usersnamespace 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.
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login