I have a server with postfix MTA installed that accepts mail for my domain, hereinafter @example.com. I need to setup forwarding for certain [email protected] to other emails . e.g. @gmail.com and this needs to be done using SMTP transport via SES.
I have SES production access and login/password pair, that is active and has IAM permissions, I checked. I have confirmed certain From: address at SES. If I send email with these SMTP username/password directly via SES from a PHP script, everything works fine. This means that the login/password pair and From: are alright.
Now I need to rewrite From: for the emails that are going from outside and need to be forwarded. For example, an email is sent from @gmail.com -> [email protected]. The entry user is set up in virtual_alias_maps and should go to another @gmail.com. In order to rewrite From: header, the following smtp_header_checks
is used:
smtp_header_checks = pcre:/etc/postfix/header_checks
the content of /etc/postfix/header_checks
is following:
/^From:(.*)/ REPLACE From: "$1" <[email protected]>
[email protected] is confirmed at SES. This is the same email I'm using when testing with PHP script that uses SES directly, i.e. with no header rewrite.
When I send something from @gmail to [email protected], here is what's going on in the logs:
Apr 8 15:04:05 ip-10-191-106-25 postfix/smtpd[32545]: connect from mail-wg0-f42.google.com[74.125.82.42]
Apr 8 15:04:06 ip-10-191-106-25 postfix/smtpd[32545]: 3252A2415D: client=mail-wg0-f42.google.com[74.125.82.42]
Apr 8 15:04:06 ip-10-191-106-25 postfix/cleanup[32550]: 3252A2415D: message-id=<CADLOpCq4ZFR5=xqTNxPO73-tVkF63urLt_9ueGBDrLSggy29MQ@mail.gmail.com>
Apr 8 15:04:06 ip-10-191-106-25 postfix/qmgr[32192]: 3252A2415D: from=<[email protected]>, size=1687, nrcpt=1 (queue active)
Apr 8 15:04:06 ip-10-191-106-25 postfix/smtpd[32545]: disconnect from mail-wg0-f42.google.com[74.125.82.42]
Apr 8 15:04:07 ip-10-191-106-25 postfix/smtp[32551]: 3252A2415D: replace: header From: "User" <[email protected]>: From: " "User" <[email protected]>" <[email protected]>
Apr 8 15:04:07 ip-10-191-106-25 postfix/smtp[32551]: 3252A2415D: to=<[email protected]>, orig_to=<[email protected]>, relay=email-smtp.us-west-2.amazonaws.com[54.149.142.243]:25, delay=1.3, delays=0.22/0.03/0.57/0.43, dsn=5.0.0, status=bounced (host email-smtp.us-west-2.amazonaws.com[54.149.142.243] said: 554 Message rejected: Email address is not verified. (in reply to end of DATA command))
Apr 8 15:04:07 ip-10-191-106-25 postfix/cleanup[32550]: 7FD75243F8: message-id=<[email protected]>
Apr 8 15:04:07 ip-10-191-106-25 postfix/qmgr[32192]: 7FD75243F8: from=<>, size=3700, nrcpt=1 (queue active)
Apr 8 15:04:07 ip-10-191-106-25 postfix/bounce[32552]: 3252A2415D: sender non-delivery notification: 7FD75243F8
Apr 8 15:04:07 ip-10-191-106-25 postfix/qmgr[32192]: 3252A2415D: removed
Apr 8 15:04:08 ip-10-191-106-25 postfix/smtp[32551]: 7FD75243F8: to=<[email protected]>, relay=email-smtp.us-west-2.amazonaws.com[54.69.81.169]:25, delay=0.67, delays=0.01/0/0.59/0.07, dsn=5.0.0, status=bounced (host email-smtp.us-west-2.amazonaws.com[54.69.81.169] said: 501 Invalid MAIL FROM address provided (in reply to MAIL FROM command))
Apr 8 15:04:08 ip-10-191-106-25 postfix/qmgr[32192]: 7FD75243F8: removed
That gives me an idea that the From: header was not actually rewritten. However, the line:
Apr 8 15:04:07 ip-10-191-106-25 postfix/smtp[32551]: 3252A2415D: replace: header From: "User" <[email protected]>: From: " "User" <[email protected]>" <[email protected]>
tells us it actually has been.
I realize that I need to view the rewritten whole mail body before it's sent to AWS server, but I have no idea how to debug it.
Here is the main.cf contents:
# See /usr/share/postfix/main.cf.dist for a commented, more complete version
# Debian specific: Specifying a file name will cause the first
# line of that file to be used as the name. The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname
smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no
# appending .domain is the MUA's job.
append_dot_mydomain = no
# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h
readme_directory = no
# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = example.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = example.com, ip-10-191-106-25.ec2.internal, localhost.ec2.internal, localhost, domain2.example.com
relayhost = email-smtp.us-west-2.amazonaws.com
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
default_transport = smtp
relay_transport = relay
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_password
smtp_use_tls = yes
smtp_tls_security_level = encrypt
smtp_tls_note_starttls_offer = yes
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtp_header_checks = pcre:/etc/postfix/header_checks
virtual_alias_maps = hash:/etc/postfix/virtual
sender_canonical_maps = hash:/etc/postfix/canonical
#debug_peer_list=email-smtp.us-west-2.amazonaws.com 127.0.0.1
#debug_peer_level=5
Looks like your initial goal with
header_checks
is preserving original sender and replace it with allowed sender of Amazon SES.The problem of your approach above is the From: header become non-standard because of multiple quotes in there.
Daniel R. Tobias mentioned this issue in his article: Dan's Mail Format Site | Headers | From/To/CC/BCC
So you can rely on this nonstandard header to bypass Amazon SES checker.
One approach to solve this problem is split the two goals above in two header_checks,
header_checks
andsmtp_header_checks
. The first header_checks will preserve the original sender in another custom header (for example X-Original-From). The second one will replace the From: header.Because of this schema, X-Original-From: header will be added in every incoming email. But replacing action will be executed on outgoing email only.
Another way is using pcre to exclude quote in the original From: header. Unfortunately, I don't have any time to test some ideas right now. Maybe later... I'll update this answer with other workaround.
The envelope sender address rewriting
The above parts is still half-journey. To pass amazon SES, you need rewrite the envelope sender address too.
See the differences between Envelope Address vs. Message Header Address in this article.
I've explained some steps to rewrite the sender in this similar threads: AWS SES: "Email address is not verified" error with Postfix relay. Basically you need put this parameter in
main.cf
In /etc/postfix/sender_canonical, add
In /etc/postfix/sender_access, add
The
/etc/postfix/sender_access
is used to preserved the original envelope sender address.following this step its working for me able to fordward the email from inside the server to customer ->
In
/etc/postfix/sender_canonical
addIn
/etc/postfix/sender_access
add