Dmytro Alieksieiev via Postfix-users:
> Hi Wietse,
>
> Thanks - and glad we agree on the PERM/451 point; that alone would take
> most of the pain out of this.
That is easier said than done.
Postfix table lookups currenly have three possible results:
- DICT_ERR_NONE: the requested item was found, or it does not exist.
- DICT_ERR_RETRY: typically, timeout
- DICT_ERR_CONFIG: configuration error
The difference between DICT_ERR_RETRY and DICT_ERR_CONFIG is in the
error message; both result in the same program behavior, because
configuration errors can be corrected.
The Postfix mapping is:
OK, NOTFOUND -> DICT_ERR_NONE
TEMP -> DICT_ERR_RETRY
PERM -> DICT_ERR_CONFIG
Changing the maning of DICT_ERR_CONFIG into a "reject" would be a
compatibility break, and adding a new "reject" status would require
lots of changes everywhere Postfix looks up information.
Until now there has een no use case for dictionaries to
return an error that says "reject".
> On header_checks: I don't think it can cover this one. header_checks
> match a header as a single logical blob, not per-address, so I can't
> express "reject/shorten the one over-long address token" ? and
> rewriting/truncating text inside a folded, quote-swallowed header is
> fragile (the very thing that makes it dangerous, the unterminated quote,
> is what makes it hard to match a stable pattern against).
Inded, this is an available option, now.
Here's another option:
xxx_maps = pipemap:{prce:/path/to/file,socketmap:{your-stuff}}
In the first example, /path/to/file contains a negative pattern to
select with < 300 bytes. Longer strings will produce a "not found"
result without using the socketmap:
if !/(.{300})/
/(.*)/ $1
ENDIF
In the second example, /path/to/file uses a positive pattern to
to expose the socketmap only to the first 300 bytes of a string.
/^(.{1,300}) $1
No idea how this handles UTF-8 non-ASCII.
This may be a reasonable option for making Postfix work with
an uncooperative socketmap.
Wietse
> I do already have finer-grained control in a milter (rspamd) in front of
> the relay, but it runs into the deeper problem I mentioned: what the
> milter parses and what cleanup ends up sending to the socketmap are two
> different things. The milter's address parser doesn't reproduce
> postfix's tok822 behavior ? the unterminated quote swallowing the fold,
> and cleanup appending remote_header_rewrite_domain ? so the filter can't
> reliably predict, let alone pre-empt, the exact key cleanup will emit.
> It can approximate (flag unbalanced quotes / over-long raw tokens), but
> not match postfix's own tokenization from outside.
>
> So from my side the ideal outcomes would be either:
>
> * reject the message at the inbound relay, before accepting it, or
> * at minimum, make the outbound header_recipient canonicalization
> failure non-fatal ? log skip even and deliver the message rather than
> cancel it.
>
> What I'd like to avoid is accepting on the inbound relay and then
> rejecting on the outbound hop, since that turns into backscatter.
>
> For context on why I can't just filter the source: the volume is small,
> but the dominant origin of these broken messages is Gmail ? and since
> this is already forwarded mail, blocking by sender domain isn't viable -
> unpredictable, and blocking by IP isn't either (too large a provider to
> ban).
>
> Thanks again for looking at it.
>
> Regards,
> Dmytro Alieksieiev
> DevOps Engineer
>
> On 15/07/2026 21:48, Wietse Venema via Postfix-users wrote:
> >> Hi Wietse, Viktor,
> >>
> >> I ran into a funky interaction between|recipient_canonical|header
> >> rewriting and a socketmap map (PostSRSd, doing reverse-SRS), where a
> >> single malformed/header/address can deterministically cancel an
> >> otherwise-deliverable message. I think I've narrowed the root cause down
> >> to something that postfix itself has no way to guard against, and I'd
> >> love your read on it and maybe propose a way to solve this issue.
> >>
> >>
> >> Setup
> >>
> >> An incoming relay accepts mail for forwarding and hands it to an
> >> outgoing relay. The outgoing relay does reverse-SRS via a socketmap and
> >> also canonicalizes header recipients (so the|To:|in a DSN matches the
> >> real MAIL TO, per RFC 3464):
> >>
> >> |recipient_canonical_maps = socketmap:inet:127.0.0.1:10003:reverse
> >> recipient_canonical_classes = envelope_recipient, header_recipient
> >> remote_header_rewrite_domain = domain.invalid # remote clients ->
> >> rewrite context = remote |
> >>
> >> The socketmap server is PostSRSd 2.x, but ? importantly ? it is*not*the
> >> culprit; any socketmap with a bounded request buffer behaves the same
> >> (see below).
> > Would a header_checks pattern work around with this, like replacing
> > long text with a shorter text?
> >
> > I agree that a PERM error should not result in a 451 status.
> >
> > Wietse
> _______________________________________________
> Postfix-users mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
_______________________________________________
Postfix-users mailing list -- [email protected]
To unsubscribe send an email to [email protected]