Rewrite email (RFC822) From address to match MAIL FROM (RFC821) envelope address postfix

I've spent some time looking into this and I can't find a pure postfix way. The one suggestion of using header_checks doesn't seem to work because you can't (AFAIK) match one header against another.

What is possible is to write your own program / script to perform the check for you and use this as a content_filter.


Step 1

Here's a simplified version of the one I use written in python. This reads an email from the stdin taking MAIL from and RECPT to addresses as arguments. It checks the From: header against the MAIL from and replaces it if they don't match. I save this as /usr/share/mail_filter/filter.py:

#! /usr/bin/python3

import sys
import subprocess
import email.parser
import email.policy

parser = email.parser.BytesParser(policy=email.policy.default)
message = parser.parse(sys.stdin.buffer)

envelope_from = sys.argv[1]
envelope_to = sys.argv[2]
# This if statement checks envelope from against message from
if message['From'].addresses[0].addr_spec != envelope_from:
    print(f"Replacing sender {message['from']} with {envelope_from}", file=sys.stderr)
    message.replace_header('From', envelope_from)

# sendmail -G -i -f sender@sender_domain.tld recipient@recipient_domain.tld
sendmail = subprocess.Popen(["/usr/sbin/sendmail", "-Gif", envelope_from, envelope_to], stdin=subprocess.PIPE)
with sendmail.stdin:
    sendmail.stdin.write(message.as_bytes())

# If sendmail returns an error, cascade it back to postfix
sys.exit(sendmail.wait())

Step 2

Updated /etc/postfix/master.cf:

# added the -o content_filter...
smtp inet n       -       y       -       -       smtpd
  -o content_filter=filter:dummy

# Added this entire service
filter    unix  -       n       n       -       10      pipe
  flags=Rq user=filter null_sender=
  argv=/usr/share/mail_filter/filter.py ${sender} ${recipient}

Note this references the script location from step 1 and the user defined in step 3

Step 3

I added an OS user filter in a group with access to use sendmail.

useradd --system --gid postdrop filter

Caveats

As per the instructions simple filters (passing forward using sendmail) can only be applied to SMTP clients and cannot filter messages sent via sendmail. If this is a problem for you then you would need to write an advanced content filter.