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]

Reply via email to