Re: Dovecot 2.4.5 on macOS 27 ARM64: post-authentication IMAP connection closes
Hello,
I am comparing Dovecot 2.3.21.1 and 2.4.5 on the same arm64 macOS host. Apple Mail and Thunderbird work normally with 2.3.21.1, but both fail at the same post-authentication boundary with 2.4.5.
The comparison keeps the client, mailbox data, TLS certificate, CRAM-MD5 credentials, public-IP/hairpin path, and base_dir=/var/run/dovecot the same. Only one Dovecot version is running at a time.
With 2.4.5:
TLS and CRAM-MD5 succeed.
SQL passdb and static userdb succeed.
imap-login reports "Logged in".
The authenticated imap process loads its plugins, assumes uid/gid 350, and resolves the expected namespace and Maildir.
It then reports:
Disconnected: Connection closed (No commands sent) in=0 out=502
Two Apple Mail attempts repeat the same result. There is no panic, fatal error, signal, or explicit anvil error in the captured interval. The /proc/self/stat and /proc/self/io debug messages also occur with the working 2.3 build on macOS.
With 2.3.21.1, the same Apple Mail version proceeds immediately to open INBOX, Junk, and Sent, reads headers and complete messages, and logs out normally. Thunderbird likewise completes NAMESPACE, COMPRESS, ID, SELECT, LIST/FETCH, STATUS, and IDLE with 2.3. Under 2.4, its client trace shows NAMESPACE being sent immediately before the socket closes, while the server-side imap process records no command.
One process-model difference is:
2.3: service imap { process_limit = 200 client_limit = 5 service_count = 0 }
2.4: service imap { client_limit = 1 }
I understand that client_limit=1 is the recommended 2.4 setting, so I am not assuming this is misconfiguration; I mention it because the failure occurs at the post-login process/handoff boundary.
The build already includes commit 5100f0fd576d0600c3f8ad7bb056ae08235cab11, so I do not believe the previously reported peer-PID/anvil fix is simply absent.
Attached:
- doveconf-2.4.5-sanitized.txt
- dovecot-2.4.5-apple-mail-sanitized.txt
I have also prepared a short paired 2.3/2.4 excerpt and can provide the complete sanitized Thunderbird client trace if useful.
What additional master/anvil/process logging would best identify where the authenticated connection is being lost on macOS?
--- BEGIN doveconf -n ---
Sanitized output of: doveconf -n
Original preserved unchanged. Operational settings and paths relevant to the
failure are retained; domain, database, and account identifiers are replaced.
2.4.5 (): /opt/dovecot/etc/dovecot/dovecot.conf
Pigeonhole version 2.4.5 (742bb892)
OS: Darwin 27.0.0 arm64
Hostname: example.test
3 default setting changes since version 2.4.5
dovecot_config_version = 2.4.5 auth_debug = yes auth_mechanisms = login plain cram-md5 auth_username_format = %{user} base_dir = /var/run/dovecot default_internal_group = staff default_internal_user = _dovecot default_login_user = _dovenull default_vsz_limit = unlimited dovecot_storage_version = 2.4.5 first_valid_gid = 350 first_valid_uid = 350 imapsieve_url = sieve://127.0.0.1:4190 log_path = /private/var/log/dovecot-info.log mail_debug = yes mail_driver = maildir mail_gid = vmail mail_log_prefix = "%{service}(pid %{process:pid} user %{user}): " mail_path = ~/Maildir mail_uid = vmail postmaster_address = postmaster@example.test protocols { imap = yes lmtp = yes sieve = yes } quota_driver = maildir sendmail_path = /opt/homebrew/sbin/sendmail sieve_global_extensions { vnd.dovecot.pipe = yes vnd.dovecot.environment = yes } sieve_pipe_bin_dir = /private/var/dovecot/sieve sieve_plugins { sieve_imapsieve = yes sieve_extprograms = yes } sql_driver = mysql verbose_proctitle = yes service stats { unix_listener stats-writer { group = vmail mode = 0600 user = vmail } } event_exporter imap_id_log { driver = log format = json } metric imap_id { exporter = imap_id_log fields = id_param_name id_param_version id_param_os id_param_vendor filter = event=imap_id_received } protocol sieve { info_log_path = /var/log/dovecot-sieve.log log_path = /var/log/dovecot-sieve-errors.log managesieve_notify_capability = mailto } service lmtp { executable = lmtp -L unix_listener lmtp { mode = 0600 user = exim } } namespace inbox { inbox = yes separator = / mailbox Archive { auto = subscribe special_use = "\\Archive" } mailbox Drafts { auto = subscribe special_use = "\\Drafts" } mailbox Junk { auto = subscribe autoexpunge = 15 days special_use = "\\Junk" sieve_script report-spam { cause = copy path = /private/var/dovecot/sieve/report-spam.sieve type = before } } imapsieve_from Junk { sieve_script report-ham { cause = copy path = /private/var/dovecot/sieve/report-ham.sieve type = before } } mailbox Sent { auto = subscribe special_use = "\\Sent" } mailbox Trash { auto = subscribe autoexpunge = 30 days special_use = "\\Trash" quota_ignore = yes } } service imap { client_limit = 1 } protocol lmtp { info_log_path = /private/var/log/dovecot-lmtp-info.log log_path = /private/var/log/dovecot-lmtp-errors.log mail_plugins { quota = yes sieve = yes } } service quota-warning { executable = script /opt/dovecot/bin/quota-warning.sh user = vmail unix_listener quota-warning { group = vmail mode = 0600 user = vmail } } sieve_script default-before { path = /private/var/dovecot/sieve/default.sieve type = before } quota "User quota" { storage_size = 18G quota_warning warn-95 { quota_storage_percentage = 95 execute quota-warning { args = 95 %{user} } } } protocol imap { imap_metadata = yes mail_plugins { quota = yes imap_quota = yes imap_sieve = yes } } mail_attribute { dict file { path = %{home}/Maildir/dovecot-attributes } } service managesieve { process_limit = 1024 } ssl_server { cert_file = /private/etc/certificates/example.test.crt key_file = # hidden, use -P to show it } mysql /tmp/mysql.sock { dbname = maildb password = # hidden, use -P to show it user = mail_reader } passdb sql { default_password_scheme = PLAIN query = SELECT username AS user, clear AS password FROM users WHERE username = '%{user}' } userdb static { fields { gid = 350 home = /private/var/mail/%{user | domain}/%{user} uid = 350 } } --- END doveconf -n ---
--- BEGIN shortened 2.3/2.4 comparison --- Dovecot 2.3.21.1 vs 2.4.5: Apple Mail post-authentication comparison
Environment
- macOS / Darwin 27.0.0 arm64
- Apple Mail 16.0 (3901.100.1.1.12)
- TLS with CRAM-MD5
- Same client, account data, public-IP/hairpin path, Maildir, and base_dir=/var/run/dovecot
- Only one Dovecot version running at a time
Dovecot 2.3.21.1: successful baseline (shortened)
Oct 02 08:06:50 master: Info: Dovecot v2.3.21.1 (d492236fa0) starting up for lmtp, sieve, imap (core dumps disabled) Oct 02 08:06:59 imap-login: Info: ID sent: name=Mac OS X Mail, version=16.0 (3901.100.1.1.12), os=Mac OS X, os-version=27.0.1 (26A434), vendor=Apple Inc.: user=<>, rip=203.0.113.10, lip=203.0.113.10, TLS Oct 02 08:06:59 imap-login: Info: Login: user=<user@example.test>, method=CRAM-MD5, rip=203.0.113.10, lip=203.0.113.10, mpid=56853, TLS Oct 02 08:06:59 imap(pid 56853 user user@example.test): Debug: Effective uid=350, gid=350, home=/private/var/mail/<domain>/<user> Oct 02 08:06:59 imap(pid 56853 user user@example.test): Debug: Namespace inbox: type=private, prefix=, sep=/, inbox=yes, hidden=no, list=yes, subscriptions=yes location=maildir:/private/var/mail/<domain>/<user>/Maildir Oct 02 08:06:59 imap(pid 56853 user user@example.test): Debug: Mailbox INBOX: Mailbox opened Oct 02 08:06:59 imap(pid 56853 user user@example.test): Debug: Mailbox Junk: Mailbox opened Oct 02 08:06:59 imap(pid 56853 user user@example.test): Debug: Mailbox Sent: Mailbox opened Oct 02 08:06:59 imap(pid 56853 user user@example.test): Info: Disconnected: Logged out in=269 out=38460 deleted=0 expunged=0 trashed=0 hdr_count=6 hdr_bytes=35888 body_count=0 body_bytes=0
[Message-open lines omitted from this short excerpt. The original log also shows Apple Mail reading complete messages and a second normal logout with in=288 out=42389 body_count=6 body_bytes=38415.]
Dovecot 2.4.5: failure (one of two identical attempts, shortened)
Oct 05 09:37:35 master: Info: Dovecot v2.4.5 () starting up for imap, lmtp, sieve (core dumps disabled) Oct 05 09:41:11 stats: Info: {"event":"imap_id_received","hostname":"example.test","fields":{"id_param_name":"Mac OS X Mail","id_param_version":"16.0 (3901.100.1.1.12)","id_param_os":"Mac OS X","id_param_vendor":"Apple Inc."}} Oct 05 09:41:11 auth(user@example.test,203.0.113.10,sasl:cram-md5)<SESSION-1>: Debug: sasl(cram-md5): Finished passdb credentials lookup (status=ok) Oct 05 09:41:11 auth(user@example.test,203.0.113.10,sasl:cram-md5)<SESSION-1>: Debug: sasl(cram-md5): Interaction succeeded Oct 05 09:41:11 auth: Debug: master userdb out: USER <request-id> user@example.test uid=350 gid=350 home=/private/var/mail/<domain>/<user> auth_mech=CRAM-MD5 auth_token=<redacted-auth-token> local_name=example.test Oct 05 09:41:11 imap-login: Info: Logged in: user=<user@example.test>, method=CRAM-MD5, rip=203.0.113.10, lip=203.0.113.10, mpid=57601, TLS, session=<SESSION-1> Oct 05 09:41:12 imap(pid 57601 user user@example.test): Debug: Effective uid=350, gid=350, home=/private/var/mail/<domain>/<user> Oct 05 09:41:12 imap(pid 57601 user user@example.test): Debug: Namespace inbox: type=private, prefix=, sep=/, inbox=yes, hidden=no, list=yes, subscriptions=yes Oct 05 09:41:12 imap(pid 57601 user user@example.test): Debug: maildir++: root=/private/var/mail/<domain>/<user>/Maildir, index=, indexpvt=, control=, inbox=/private/var/mail/<domain>/<user>/Maildir, alt= Oct 05 09:41:12 imap(pid 57601 user user@example.test): Info: Disconnected: Connection closed (No commands sent) in=0 out=502 deleted=0 expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0
Observed boundary
Both versions complete TLS, CRAM-MD5, userdb lookup, privilege selection, namespace setup, and Maildir path resolution. Under 2.3, Apple Mail proceeds to mailbox commands. Under 2.4, the authenticated IMAP process sends 502 bytes and the connection closes before that process records any client command. A second 2.4 attempt repeats the same in=0 out=502 result. No panic, fatal error, signal, or explicit anvil error appears in the captured interval.
Relevant process-model difference
2.3: service imap { process_limit = 200 client_limit = 5 service_count = 0 }
2.4: service imap { client_limit = 1 }
This is noted as a diagnostic difference, not asserted as the cause. --- END shortened 2.3/2.4 comparison ---
participants (1)
-
George