wildduck/lib
titanism ea86c9fd46
fix(pop3): fix pipelining race condition causing mpop "invalid reply" errors (#950)
* fix(pop3): ensure pipelined RETR commands complete before processing next command

When POP3 clients use PIPELINING to send multiple RETR commands, the server
must ensure each message is fully transmitted (including the terminating dot)
before processing the next command. Previously, the server would call next()
when the source stream ended, but the DataStream transform (which adds the
terminating dot) might not have finished flushing to the socket yet.

This caused race conditions where the +OK response for the next RETR command
could be sent before the previous message's terminating dot, violating the
POP3 protocol and causing clients like mpop to report "invalid reply" errors.

The fix listens for the 'end' event on the DataStream (after it has written
the terminating dot) rather than the source stream, ensuring proper sequencing
of pipelined responses.

* test(pop3): add pipelining tests for RETR command race condition fix

Add comprehensive tests to verify that pipelined RETR commands are handled
correctly without interleaving responses. These tests simulate aggressive
POP3 client behavior (like mpop) that sends multiple RETR commands without
waiting for individual responses.

The tests verify:
- Multiple pipelined RETR commands complete in order
- Message terminating dot is sent before next +OK response
- The fix code exists in connection.js
- Rapid pipelining with 10 messages works correctly

* chore(test): add POP3 tests to grunt proto task

Update Gruntfile to include POP3 tests in the proto task, allowing protocol-
level tests (IMAP unit + POP3) to run without requiring MongoDB/Redis.

Changes:
- Add mochaTest:pop3 configuration for POP3 tests
- Add mochaTest:imap-unit for IMAP tests that don't require MongoDB
- Update proto task to run both imap-unit and pop3 tests

* fix(pop3): add defensive checks for stream.options.ttlcounter

Add defensive checks in RETR and TOP commands to handle streams
that don't have the options.ttlcounter property set. This fixes
a TypeError crash in Forward Email and other implementations that
don't set stream.options when returning from onFetchMessage.

The fix checks if stream?.options?.ttlcounter is a function before
calling it, and skips the ttlcounter call if not available.

Also adds:
- mpop pipelining tests for real-world client compatibility
- Tests for streams without options property
- Tests for streams with options but missing ttlcounter
- CI configuration to install mpop for testing
2026-01-08 09:36:27 +02:00
..
acme fix: ZMSA-1: update release workflow, update deps, use updated deps, scope package (#887) 2025-10-17 12:04:48 +03:00
api fix(authlog): ZMSA-34: authLog add protocol for better logging in user update and asp generate and delete (#924) 2025-11-28 15:20:12 +02:00
attachments fix(gridstore-upload): ZMSA-17: fix gridstore upload deadlock (#918) 2025-12-04 09:51:22 +02:00
handlers fix: ZMSA-1: update release workflow, update deps, use updated deps, scope package (#887) 2025-10-17 12:04:48 +03:00
lua
md5
pop3 fix(pop3): fix pipelining race condition causing mpop "invalid reply" errors (#950) 2026-01-08 09:36:27 +02:00
schemas
tasks fix: ZMSA-28: make migrations configurable (#922) 2025-11-27 11:19:56 +02:00
attachment-storage.js
audit-handler.js
autoreply.js
bimi-handler.js
cert-handler.js fix(tls-logging): ZMSA-40: where possible use _ip in gelf logs instead of _remoteAddress (#929) 2025-12-04 09:57:22 +02:00
certs.js fix: ZMSA-1: update release workflow, update deps, use updated deps, scope package (#887) 2025-10-17 12:04:48 +03:00
consts.js
counters.js
data-url.js
db.js fix: ZMSA-1: update release workflow, update deps, use updated deps, scope package (#887) 2025-10-17 12:04:48 +03:00
dkim-handler.js
dkim-stream.js
elasticsearch.js fix: ZMSA-1: update release workflow, update deps, use updated deps, scope package (#887) 2025-10-17 12:04:48 +03:00
encrypt.js fix(crypto.createDecipher): ZMSA-47: dkim legacy decipher fixes (#935) 2025-12-11 11:39:22 +02:00
ensure-es-index.js
errors.js fix: ZMSA-1: update release workflow, update deps, use updated deps, scope package (#887) 2025-10-17 12:04:48 +03:00
events.js
export.js
filehash-stream.js
filter-handler.js fix: ZMSA-17: improve filterHandler and messageHandler logging (#907) 2025-11-19 13:06:25 +02:00
forward.js
hashes.js
header-splitter.js fix: ZMSA-1: update release workflow, update deps, use updated deps, scope package (#887) 2025-10-17 12:04:48 +03:00
imap-notifier.js fix: ZMSA-1: update release workflow, update deps, use updated deps, scope package (#887) 2025-10-17 12:04:48 +03:00
limited-fetch.js fix: ZMSA-29: POP3 TOP command calculate counters correctly and correctly update them (#914) 2025-11-24 10:27:42 +02:00
mailbox-handler.js
maildrop.js fix: ZMSA-1: update release workflow, update deps, use updated deps, scope package (#887) 2025-10-17 12:04:48 +03:00
maildropper.js fix: ZMSA-1: update release workflow, update deps, use updated deps, scope package (#887) 2025-10-17 12:04:48 +03:00
mbox-export.js
mbox-stream.js
message-handler.js fix: ZMSA-17: improve filterHandler and messageHandler logging (#907) 2025-11-19 13:06:25 +02:00
message-splitter.js fix: ZMSA-1: update release workflow, update deps, use updated deps, scope package (#887) 2025-10-17 12:04:48 +03:00
mongopaging-find-wrapper.js
newlines.js
plugins.js fix: ZMSA-1: update release workflow, update deps, use updated deps, scope package (#887) 2025-10-17 12:04:48 +03:00
prepare-search-filter.js
redis-url.js
roles.js fix: ZMSA-1: update release workflow, update deps, use updated deps, scope package (#887) 2025-10-17 12:04:48 +03:00
schemas.js
search-query.js
settings-handler.js fix: ZMSA-1: update release workflow, update deps, use updated deps, scope package (#887) 2025-10-17 12:04:48 +03:00
storage-handler.js
task-handler.js
tools.js fix(hibp-use-keepalive): ZMSA-12: use keepalive when querying HIBP database (#900) 2025-11-07 10:59:42 +02:00
translations.js
user-cache.js
user-handler.js fix(userHandler-asyncGetDeleted): ZMSA-52: user-handler create new asyncGetDeleted function to get deleted user by username, id, main address (#947) 2026-01-06 09:54:26 +02:00