Introduction
Alright, this is a quick guide for the impatient but otherwise experienced linux admin/hacker/hobbyist. Some past postfix experiences might be advantageous for general understanding and troubleshoooting.
Why would I want a local postfix and relay to another smtp anyway? Simple: When my application code needs to send an e-mail, there is an SMTP server ready to accept the e-mail from me. It will then take care of everything else like re-delivery, dealing with being grey-listed and many other things. Also, if connectivity to the SES SMTP happens to be interrupted it's no big deal because here too, the local postfix will handle re-sending for me. Nice, huh?
The documentation for setting up postfix as an SMTP relay to Amazon SES is correct but seems incomplete and I had to hunt a few bits of extra information so below is my complete config that I use on my EC2 instances and my development notebook.
Configuration (EC2)
So let's make this quick, here are the configs:
main.cf
This is just condensed and stripped to the bare minimum. We only acceppt connections from the localhost, this ensures we don't relay e-mail from any party.
## ## default config (condensed, no coments) ## queue_directory = /var/spool/postfix command_directory = /usr/sbin daemon_directory = /usr/libexec/postfix mail_owner = postfix inet_interfaces = localhost mydestination = $myhostname, localhost.$mydomain, localhost unknown_local_recipient_reject_code = 550 alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases debug_peer_level = 2 sendmail_path = /usr/sbin/sendmail.postfix newaliases_path = /usr/bin/newaliases.postfix mailq_path = /usr/bin/mailq.postfix setgid_group = postdrop html_directory = no manpage_directory = /usr/share/man sample_directory = /usr/share/doc/postfix-2.3.3/samples readme_directory = /usr/share/doc/postfix-2.3.3/README_FILES ## ## some extras ## inet_interfaces = loopback-only masquerade_domains = $mydomain ## ## use amazon ses via smtp with starttls ## relayhost = email-smtp.us-east-1.amazonaws.com:25 smtp_sasl_auth_enable = yes smtp_sasl_security_options = noanonymous smtp_sasl_tls_security_options = noanonymous smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd smtp_use_tls = yes smtp_tls_security_level = encrypt smtp_tls_note_starttls_offer = yes smtp_tls_CAfile = /etc/ssl/certs/ca-bundle.crt
master.cf
The only change to the default config is to comment out the fallback line just below smtp and the rest of the master.cf is unchanged
smtp unix - - n - - smtp -v # When relaying mail as backup MX, disable fallback_relay to avoid MX loops relay unix - - n - - smtp # -o fallback_relay= # -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
Configuration (Development)
When applying the configuration to my development machine I've had to copy the ca-bundle.crt file. So for my development machine the last line of the main.cf file looks like this:
smtp_tls_CAfile = /etc/ssl/certs/amazon-aws-ca-bundle.crt
Also, the path daemon_directory is different on my notebook. You can figure out the correct path by checking where your package manager installs all the postfix binaries, that's your daemon_directory. (or just look at the distro's config before overwriting it)
daemon_directory = /usr/lib/postfix
And that's all that's different between my EC2 and development hosts.
Amazon SES Credentials
Amazon requires sending systems to authenticate against their SMTP, so you need to first create an SES user and password in the AWS SES Console. Those will be generated by Amazon for you and you have 1 (one) opportunity to see/download those credentials. Put them in the file /etc/postfix/sasl_passwd as you can see here:
email-smtp.us-east-1.amazonaws.com:25 <user>:<password> ses-smtp-prod-335357831.us-east-1.elb.amazonaws.com:25 <user>:<password>
Then run "postmap hash:/etc/postfix/sasl_passwd" and remove the file.
Verify your sender address
Amazon SES only allows you to send from a verified address. So head on over to the AWS Console and add a sender address, wait for the E-Mail and verify the sender address.
Note: If you're in sandbox mode, the recipient must also be a verified address, otherwise SES will bounce the e-mail!! For test/dev this is usually good enough, if you need to be able to send e-mails anywhere then it's time to request production access in the AWS Console.
Sending some test e-mails
This was my biggest pitfall when setting SES up. Sendmail must be invoked in a special way so it behaves nicely and the mail will actually be sent. The first line is the shell command, and the rest is typed into the console.
root@remote:/tmp$ sendmail -t -f verifiedsender@example.com To: recipient@example.com Subject: Testing postfix relay via Amazon SES Hey there, this is a test E-Mail!! .
Note the line with a single dot and nothing else on it. This tells sendmail the body of the e-mail has ended and the e-mail will be sent.
And that's it already. If you know what you're doing it'll take you 10mins tops to set this up and get it running. If you're doing it for the first time like I did it's more like 2-3hrs with troubleshooting. Anyway, I hope this will save some folks some time so they can concentrate on more important matters!
Troubleshooting
If you want some debugging Information from postfix, you can append "-v" on the smtp line in the master.cf and restart postfix. The postfix log is /var/log/maillog on most systems. You need to read the log carefully but it'll tell you everything you need to find most if not all problems.
I would like to add one more step I needed to work through.
ReplyDeleteOn a new install of postfix, you need to generate the aliases.db with "newaliases". It wouldn't work for me until I set the default MTA to be postfix, using "alternatives --config mta".
What distro are you on? I recently set up another pc with kubuntu and didn't have to run newaliases myself. And postfix apparently being the only/default mta here, I didn't run into the second issue either (or forgot about it).
DeleteThanks for the heads-up
We've been noticing a strange issue. Our Postfix server has:
ReplyDeletemydestination = xyz.abc.com, localhost.localdomain, localhost in the configuration file.
When Postfix relays an email say to efg@hij.com via SES, SES returns the email as Recipient address rejected: User unknown in local recipient table. Does postfix try and send the efg@hij.com email to xyz.abc.com? How can we fix this?