hMailServer 6.2.17: relayed mail could stall after end-of-data with no 250
-
If your server accepts inbound mail from a trusted relay, a Proxmox/Postfix front end for example, and you run SpamAssassin, messages could stall after end-of-data and never get a 250. Reception was never the problem. The stall was in the accept/save work that runs after the terminating dot and before the reply.
What the upgrade involved
No database change. Schema version stays at 6005.
The same audit found other unbounded waits, not fixed here: synchronous DNS lookups in the spam tests have no application-level timeout, the database connection pool has no acquisition deadline, event scripts have no execution limit, and the ClamAV read/write timeout on delivery is ineffective.
Why it only ever hit relayed mail
For a trusted incoming relay, hMailServer defers the whole spam battery to after end-of-data. For a direct or authenticated sender those tests run earlier, during MAIL FROM/RCPT TO, on the connection thread. The post-DATA work runs on a bounded pool, 15 threads by default, and holds the thread that sends the 250. SpamAssassin's wait had no overall ceiling: the connection's idle timeout is re-armed on every byte received, so a scanner that stalls or dribbles holds the thread indefinitely. Against a blackholed SpamAssassin endpoint, one message was acknowledged after 120 s. Eighteen concurrent messages produced zero acknowledgements: 15 workers blocked, the rest with no worker at all.
The fixes
- SpamAssassin's wait is bounded. Hard ceiling of SAMaxTimeout + 30 s, after which the message is accepted without a verdict, the same outcome as spamd being down.
- New
FinalizationTimeout, default 240 s, inside Postfix's 600 s data-done timeout, 0 disables it. Acceptance past that answers 451 4.3.1 and the sender retries. The check runs on the accepting thread and only before anything is saved, so it cannot duplicate mail. - Acceptance is timed per stage and each spam test timed individually. A slow stage is logged at APPLICATION level, not only under debug:
Spam test: SpamTestSpamAssassin, Score: 0, Time: 120031 ms.
Upgrading is enough to turn silent stalls into either a completed delivery or a clean 451 retry. Enable debug logging and the per-stage timings name the scanner, DNS lookup or event script responsible.
Also in this release: regression coverage for clients that vanish mid-operation (aborted DATA, truncated BDAT, IMAP APPEND literals cut short, POP3 disconnects during RETR), plus an installer smoke test on a clean machine.
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