Skip to content

Add option for more relaxed barelf handling and changed softdeny to deny - #358

Merged
msimerson merged 4 commits into
smtpd:masterfrom
wornet-aer:bugfix-make-barelf-perm-deny-5xx
Oct 6, 2026
Merged

msimerson merged 4 commits into
smtpd:masterfrom
wornet-aer:bugfix-make-barelf-perm-deny-5xx

Conversation

@wornet-aer

Copy link
Copy Markdown
Contributor

Since #318 (1.02), any line in the DATA phase that doesn't end in CRLF is rejected, not only the final dot. That is RFC 5321 compliant, but it changed two things for operators:

  1. The response is a temporary 421. A bare LF is a permanent defect of the message, and a retry fails the same way. Legitimate senders keep the message queued and retry for days before bouncing. The receiving side sees the same rejected session over and over.
  2. There is no way to opt out. After upgrading to 1.02 we saw rejections go from 0 to ~4-8% of daily sessions overnight (~3,700-6,900 per day per server, against ~85k queued). Most came from
    cloud VMs, so the strict check is useful, but some operators need to accept mail from non-conforming legacy software.

Changes

  • Bare LF/CR in DATA is now rejected with 554 (# 5.6.0) and the connection is closed. Senders get an immediate, readable bounce instead of retrying a message that can never pass. This follows the existing permanent-denial path in DATA (DENY_DISCONNECT 554).
  • New config barelf:
    -> strict (default): unchanged 1.02 semantics, any line not ending in CRLF is rejected.
    -> tolerant: bare LF lines in the body are accepted, but the data only ends at .. A bare-LF/CR final dot, or a final dot directly after a bare LF (.), is still rejected, so the SMTP smuggling vectors stay closed.
    -> lazy: the pre-1.02 behaviour (only the final dot is checked). It is documented as allowing . smuggling and is not recommended. It exists for operators who need an exact rollback.
  • An unknown value logs a warning and falls back to strict.

Tests

t/qpsmtpd-smtp.t now expects 554 for the existing bare-LF cases. It also covers each mode against a bare LF in the body, a bare-LF final dot and the . smuggling sequence, plus the fallback for unknown values. Full suite passes.

@msimerson

msimerson commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Looks great. The only thing that gives me pause is the lazy option which seems like a potential foot gun. What do you think about removing the option and pointing at a URL (this issue?) that provides a patch for lazy handling, along with the usual "known smuggling vector, don't enable this on public facing servers, etc, etc" warnings?

@wornet-aer

Copy link
Copy Markdown
Contributor Author

Thanks for looking into this!

I was just afraid that the new behaviour may break some of our connections from non-RFC compliant communication partners. That's why I also thought about the lazy switch.

For most cases the tolerant option should be sufficient when dealing with non-RFC compliant systems, as it stops the possibility for SMTP smuggling, but is still more tolerant with broken email messages than the new strict default mode.

I'll update the PR as suggested.

@wornet-aer
wornet-aer marked this pull request as draft October 6, 2026 18:43
@msimerson

Copy link
Copy Markdown
Member

I was just afraid that the new behaviour may break some of our connections from non-RFC compliant communication partners. That's why I also thought about the lazy switch.

Yep, but I'd rather enshrine "just in case" in a comment and/or issue. We can always add it later if / when that use case surfaces.

@wornet-aer

Copy link
Copy Markdown
Contributor Author

I was just afraid that the new behaviour may break some of our connections from non-RFC compliant communication partners. That's why I also thought about the lazy switch.

Yep, but I'd rather enshrine "just in case" in a comment and/or issue. We can always add it later if / when that use case surfaces.

Definitely. Thanks for your constructive feedback as always!
It's often helpful to discuss changes with others to have different views and get the best outcome for the project.
That's why I'm here ;-)

I'll remove the Draft state as soon, as I've removed the lazy option.

@wornet-aer
wornet-aer marked this pull request as ready for review October 6, 2026 19:23
@msimerson
msimerson merged commit 144380d into smtpd:master Oct 6, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants