0

I am using postfix to manage email on a certain machine.

Some mail eventually gets relayed to a particular address, say nasty@example.com, and the mail server serving this address REQUIRES the envelope (MAIL FROM) field to be a particular value, say MAIL FROM james@bond.com.

How can I make postfix replace whatever it originally intended to have at this field by what I want?

The solutions which do not work:

smtp_generic_maps sets the sender address based on the original sender address, sender_canonical_maps does the same, except at a different point in the mail processing pipeline.

I need to change the Sender address based on the Recipient address. Headers must be left intact.

Nothing can be assumed about the message source. Can be local or external.

2 Answers2

0

Your're asking about masquerading. But the thing is, basically, all out-of-the-box solutions for any modern MTA is to masquerade the sender address basing on the sender domain, not the recipient. What you're requesting is still possible, but there's no stock functionality for this. You could, however, write your own milter doing exactly that, but this seems to be overcomplicated.

In reality, I suppose your receiving MTA doesn't require the envelope address to be in some relation to the receiver address, it's rather using some common antispat technique, which you could easily obey.

drookie
  • 9,120
  • 1
  • 21
  • 29
0

I have solved this for myself by adding a line to master.cf:

# https://serverfault.com/questions/322657/how-can-i-route-some-emails-to-a-script-in-postfix
coolscript unix -    n    n    -    50    pipe
    flags=R user=nobody argv=/etc/bin/separate-sender.bash --sender=${sender} --user=${user} --extension=${extension} --recipient=${recipient}

adding transport_maps:

/^.*@server.example$/ coolscript:

and make separate-sender.bash wrap around msmtp:

#!/bin/bash
recipient=""
while :; do                                                                                                                                                   
    case $1 in                                                                                                                                                
        -f|--recipient)       # Takes an option argument; ensure it has been specified.                                                                       
            if [ "$2" ]; then                                                                                                                                 
                recipient=$2                                                                                                                                  
                shift                                                                                                                                         
            else                                                                                                                                              
                die 'ERROR: "--recipient" requires a non-empty option argument.'                                                                              
            fi                                                                                                                                                
            ;;                                                                                                                                                
        --recipient=?*)
            recipient=${1#*=} # Delete everything up to "=" and assign the remainder.
            ;;
        --recipient=)         # Handle the case of an empty --recipient=
            die 'ERROR: "--recipient" requires a non-empty option argument.'
            ;;
        --)              # End of all options.
            shift
            break
            ;;
<... same thing for sender...>
        -?*)
            printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2
            ;;
        *)               # Default case: No more options, so break out of the loop.
            break
    esac
    shift
done
if [[ "$recipient" == "" ]] ; then "Recipient missing!\n" >&2 ; exit 67; fi

OUT=$(msmtp --host='my.mx.host' --port=587 --tls-starttls=on --from="$sender" "$recipient" 2>&1) rc=$?

MESSAGE=$(printf '%s' "$OUT" | sed -E --quiet '/server message/s/msmtp: server message: (.*)/\1/gp') printf '%s' "$MESSAGE" exit $rc