[pfx] Re: cleanup(8): recipient_canonical can emit an over-long socketmap query with no operator guard; PERM then retried as 451

Dmytro Alieksieiev via Postfix-users <[email protected]> Wed, 15 Jul 2026 22:17:05 +0200
Newsgroups gmane.mail.postfix.user
Message-ID <[email protected]>
This is a multi-part message in MIME format.
--===============4514944276040578966==
Content-Type: multipart/alternative;
 boundary="------------LvRyDTnY7bTJDcmGgM4tjFzn"
Content-Language: en-US

This is a multi-part message in MIME format.
--------------LvRyDTnY7bTJDcmGgM4tjFzn
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit

Hi Wietse,

Thanks — and glad we agree on the PERM/451 point; that alone would take 
most of the pain out of this.

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).

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
--------------LvRyDTnY7bTJDcmGgM4tjFzn
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Hi Wietse,<br>
      <br>
      Thanks — and glad we agree on the PERM/451 point; that alone would
      take most of the pain out of this.<br>
      <br>
      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).<br>
      <br>
      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.<br>
      <br>
      So from my side the ideal outcomes would be either:<br>
      <br>
      * reject the message at the inbound relay, before accepting it, or<br>
      * at minimum, make the outbound header_recipient canonicalization
      failure non-fatal — log skip even and deliver the message rather
      than cancel it.</p>
    <p>What I'd like to avoid is accepting on the inbound relay and then
      rejecting on the outbound hop, since that turns into backscatter.<br>
      <br>
      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).<br>
      <br>
      Thanks again for looking at it.</p>
    <pre class="moz-signature" cols="72">Regards,
Dmytro Alieksieiev
DevOps Engineer</pre>
    <div class="moz-cite-prefix">On 15/07/2026 21:48, Wietse Venema via
      Postfix-users wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:[email protected]">
      <pre class="moz-quote-pre" wrap=""><blockquote type="cite"
      style="color: #007cff;"><pre wrap="" class="moz-quote-pre">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 -&gt; 
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).
</pre></blockquote><pre wrap="" class="moz-quote-pre">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</pre></pre>
    </blockquote>
  </body>
</html>

--------------LvRyDTnY7bTJDcmGgM4tjFzn--

--===============4514944276040578966==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Postfix-users mailing list -- [email protected]
To unsubscribe send an email to [email protected]

--===============4514944276040578966==--