Postfix (with smtp.gmail.com as relayhost)

Updated: Apr 22, 2023

Most of us forget that postfix not only acts like a mail-server, but it can act like a smtp-client (like thunderbird, evolution).

This post is all about configuring postfix to work as mail-server for my local domain (drunkenmonk.org) at the same time forward any outside domain mails to smtp.google.com with my gmail account credentials. If you are curious about drunkenmonk.org, read my previous articles about Dnsmasq for Home User and Virtual Home Network (with Dnsmasq , Bridge, TUN/TAP, Qemu). These two articles will explain how I setup my home network.

First things first, lets install postfix (Well I’m using sabayon)

$ sudo equo install mail-mta/postfix

BASIC MAIL SERVER

Postfix configuration is pretty simple and straight forward. You have to configure following parameters inside /etc/postfix/main.cf

mydomain = drunkenmonk.org
myorigin = $mydomain
inet_interfaces = all
mydestination = localhost, localhost.$mydomain, $myhostname, $mydomain, mail.$mydomain
mynetworks_style = subnet

mydomain tells postfix that it should serve as mail server for drunkenmonk.org domain.

myorigin tells that postfix should append drunkenmonk.org to any incoming mail’s address if the address don’t have domain part. Which means, when you do mail someuser from commandline, postfix will append drunkenmonk.org so that To address will become someuser@drunkenmonk.org.

inet_interfaces tells postfix to listen on all network interfaces.

mydestination tells postfix that it should be the final destination for localhost, localhost.drunkenmonk.org, mokka.drunkenmonk.org, drunkenmonk.org and mail.drunkenmonk.org

mynetworks_style tells postfix that my local network is a subnet type.

Thats all needed for postfix to get start. We can restart postfix with this configurations to send/receive mails between local users. However we want a little bit more from postfix. Lets configure it to use STARTTLS for its communication with its clients

BASIC MAIL SERVER WITH STARTTLS

If you wonder what is STARTTLS, its a simple method to establish communication in a secure way. Your server application (like Postfix listening on port 25) says Hey client I have TLS support, If you want, we can communicate each other in TLS secure way within port 25 itself, If you don't want, we can continue with plain-text, what you say?, then your client (like Evolution or Thunderbird) will tell OOh!! you offer TLS, then lets do TLS!!. So the packets going between server and client will be encrypted using TLS.

Before STARTTLS, people used different port for secure smtp which is smtps(port 465). But nowadays it is changing, the regular smtp port itself been used for both plain-text and SSL/TLS communication.

We have to configure Postfix to talk in SSL/TLS way, for that we need Self Signed SSL certificate. Lets create one,

$ cd /etc/ssl/postfix
$ sudo mkdir oldcerts
$ sudo mv * oldcerts
$ sudo openssl genrsa -out server.key.password -des3 1024
Generating RSA private key, 1024 bit long modulus
.............................++++++
..........................++++++
e is 65537 (0x10001)
Enter pass phrase for server.key.password:
Verifying - Enter pass phrase for server.key.password:
$

Here you have to give a pass phrase to generate RSA private key, but having a key with pass phrase is asking for trouble. You have to manually type this password everytime postfix access this key. The following command will remove pass phrase from a RSA key

$ sudo openssl rsa -in server.key.password -out server.key
Enter pass phrase for server.key.password:
writing RSA key
$

Now you have a RSA private key file server.key without pass phrase. Its time to create certificate request,

$ sudo openssl req -out server.csr -new -key server.key
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:IN
State or Province Name (full name) [Some-State]:TamilNadu
Locality Name (eg, city) []:Chennai
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DrunkenMonk Pvt Ltd
Organizational Unit Name (eg, section) []: Pattasarayam Generating Unit
Common Name (e.g. server FQDN or YOUR name) []:MokkaPandi
Email Address []:webmaster@drunkenmonk.org

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Don’t give any password when creating certificate request. Finally create a self signed ssl certificate using following command,

$ sudo openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
Signature ok
subject=/C=IN/ST=TamilNadu/L=Chennai/O=DrunkenMonk Pvt Ltd/OU= Pattasarayam Generating Unit/CN=MokkaPandi/emailAddress=webmaster@drunkenmonk.org
Getting Private key
$

Ok, thats it. You will have two files, one is /etc/ssl/postfix/server.crt and another is /etc/ssl/postfix/server.key, Now configure postfix to use these two for SSL/TLS communication, Add the following lines at the end of /etc/postfix/main.cf

# TLS Support
smtpd_tls_cert_file = /etc/ssl/postfix/server.crt
smtpd_tls_key_file = /etc/ssl/postfix/server.key
smtpd_tls_security_level = may

Finally, start postfix

$ sudo eselect rc restart postfix

Check if postfix can operate with STARTTLS,

$ sudo openssl s_client -connect localhost:25 -starttls smtp

Above command will show the server certificate and all SSL stuffs. After this, whatever you send will be encrypted, now check if it can send mail,

250 DSN
EHLO drunkenmonk.org
250-mokka.drunkenmonk.org
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
mail from: root@drunkenmonk.org
250 2.1.0 Ok
rcpt to: webmaster@drunkenmonk.org
250 2.1.5 Ok
data
354 End data with .
Subject: test mail
test mail
.
250 2.0.0 Ok: queued as E0E352C0091
quit
221 2.0.0 Bye
closed

Now see if root got a test mail

$ sudo mail
>N  8 root@drunkenmonk  Tue Aug  7 16:50   14/533   test mail
&p
From root@drunkenmonk.org  Tue Aug  7 16:50:23 2012
X-Original-To: webmaster@drunkenmonk.org
Subject: test mail
Date: Tue,  7 Aug 2012 16:49:48 +0530 (IST)
From: root@drunkenmonk.org

test mail

&q
$

We are not done yet. There is one more part. Lets make postfix to forward mails to gmail.

MAIL FORWARDER

Till now, postfix can send/receive mails within drunkenmonk.org domain. But if someone from your subnet want to send a mail to a person who have mail address outside drunkenmonk.org domain (let say stuid@yahoo.com), then your current postfix will try to contact mail server of yahoo.com. But, yahoo’s mail server will reject your mail because drunkenmonk.org is not a vaild registered domain.

But, If you have a gmail account, you can forward the mail first to smtp.gmail.com with your account credentials so that gmail will send your mail to stupid@yahoo.com with your gmail account credentials. The person who owns stupid@yahoo.com will receive a mail with from address as yours irrespective of whoever send within your local network.

To make postfix to know your credentials, we need to create a credential db with gmail account credentials, For that we need to add following line at the end of /etc/postfix/saslpass file

# run following command to generate hash password db
# that can be used inside postfix's main.cf
#
# command:
# postmap hash:saslpass
#
#
#file content format:
#remotehost username:password
smtp.gmail.com foouser:barpassword

Now run the following command to create saslpass.db

$ cd /etc/postfix
$ sudo postmap hash:saslpass

Now you can see saslpass.db created as a Berkeley DB file. We can now use this file inside main.cf to inform postfix about your gmail account credential. Before doing that, please remove /etc/postfix/saslpass file or change its access to 0600 for root. Because your credentials are in plaintext. We need to add following lines at the end of main.cf

# gmail
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/saslpass
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
smtp_tls_mandatory_ciphers = high
smtp_tls_verify_cert_match = hostname, nexthop, dot-nexthop
relayhost = smtp.gmail.com:587

Here hash:/etc/postfix/saslpass actually makes postfix to access /etc/postfix/saslpass.db file. You can remove /etc/postfix/saslpass which have your gmail password as plaintext. It will not affect postfix and postfix doesn’t need it.

Thats it, we are done. Once you restart postfix, It becomes capable of sending mail to outside world but with your gmail account’s credentials. Thanks for reading all the way down to this line. Have a nice day!!