I spent some time today configuring Postfix so I could send mail from home via SMTPS.
Outgoing mail
Verizon, our ISP, blocks port 25 to external domains, forcing all
outgoing mail through their outgoing.verizon.net
exchange server
(Comcast does the same thing). In order to accept mail,
they also require you authenticate with your Verizon username and
password, so I wanted to use an encrypted connection.
For the purpose of this example, our Verizon username is jdoe
, our
Verizon password is YOURPASS
, you're running a local Postfix server
on mail.example.com
for your site at example.com
, and 12345
is a
free local port.
# cat /etc/postfix/main.cf
myhostname = mail.example.com
relayhost = [127.0.0.1]:12345
smtp_generic_maps = regexp:/etc/postfix/generic
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/saslpass
…
# cat /etc/postfix/generic
/^jdoe@(.*)$/ jdoe@example.com
/^root@(.*)$/ jdoe@example.com
# postmap /etc/postfix/generic
# cat /etc/postfix/saslpass
[127.0.0.1]:12345 jdoe@verizon.net:YOURPASS
# postmap /etc/postfix/saslpass
# cat /etc/stunnel/stunnel.conf
[smtp-tls-wrapper]
accept = 12345
client = yes
connect = outgoing.verizon.net:465
# /etc/init.d/stunnel restart
# postfix reload
Test with:
$ echo 'testing 1 2' | sendmail you@somewhere.com
Here's what's going on:
- You hand an outgoing message to your local Postfix, which decides to
send it via port
12345
on your localhost (127.0.0.1
) (relayhost). - Stunnel picks up the connection from Postfix, encrypts everything,
and forwards the connection to port 465 on
outgoing.verizon.net
(stunnel.conf
). - Postfix identifies itself as
mail.example.com
(myhostname), and authenticates using your Verizon credentials (smtp_sasl_…
). - Because Verizon is picky about the
From
addresses it will accept, we use smtp_generic_maps to map addresses to something simple that we've tested.
And that's it :p. If you're curious, there's more detail about all the Postfix config options in the postconf man page. You might also want to look over the SASL_README and ADDRESS_REWRITING_README.
For the generic mapping, I've used a regexp table, that way I don't have to map a bunch of possible original addresses by hand. By using smtp_generic_maps instead of canonical_maps, we only remap addresses before they head off into the wider world. If we used canonical_maps, we would remap all incoming mail, even mail destined for local delivery.
There's also a blog post by Tim White which I found useful. Because Verizon lacks STARTTLS support, his approach didn't work for me out of the box.
Incoming mail
In case you have trouble with someone blocking your incoming mail, things are a bit trickier. You can always accept mail on different ports (e.g. the submission port 587), with an entry like
submission inet n - n - - smtpd
in /etc/postfix/master.cf
. However, others will not know which port
you selected, because MX records do not allow you to specify
alternate ports. The more modern SRV record allows this, but
mail systems are old-school and don't support SRV. If you have access
to another external server (whose port 25 isn't blocked), you can
point your MX record at that server, and have it forward mail to you
on your strange port.
For the purpose of this example, the remote host has a public IP of
1.2.3.4
, and your local site is example.com
, recieving mail on
port 587. All of the following config files are on the remote host.
# cat /etc/postfix/main.cf
…
proxy_interfaces = 1.2.3.4
relay_domains = example.com
relay_transport = relay:[example.com]:587
…
For futher details (e.g. if you are relaying to more than one target), see the Postfix suggestions for being an MX host for a remote site.