Use Postfix Transport Map and Relayhost Map For Flexible Email Delivery

In previous tutorials we discussed how to quickly set up a full-featured mail server using iRedMail or Modoboa, and we also learned how to set up SMTP relay with Postfix SMTP server to bypass port 25 blocking or IP blacklists. However, you might not want to set up your entire email server to use relay host. We can configure Postfix transport map and relay map so that some emails are delivered via relay host, other emails are sent directly to recipients.

There are many SMTP relay services. In this tutorial, I use Mailjet, which allows you to send 6000 emails per month for free. SMTP relay services maintain good IP reputation. They stop the bad senders and grow the good ones, so using SMTP relay service will increase the chance of hitting into the inbox.

Use Postfix Transport Map and Relay Map For Flexible Email Delivery

How to Use Postfix Transport Map

The transport map defines mappings from recipient address to transport method. By default, the value of the transport_maps parameter in Postfix is not set, as can be checked with:

postconf transport_maps

Sample output:

transport_maps =

iRedMail and Modoboa uses MySQL/MariaDB database to store transport maps. If you used iRedMail to set up your mail server, then the output should be like:

transport_maps = proxy:mysql:/etc/postfix/mysql/transport_maps_user.cf proxy:mysql:/etc/postfix/mysql/transport_maps_domain.cf

If you used Modoboa to set up your mail server, then the output should be like:

transport_maps = proxy:mysql:/etc/postfix/sql-transport.cf proxy:mysql:/etc/postfix/sql-spliteddomains-transport.cf

The transport_maps parameter points to one or more transport lookup tables. You can edit the Postfix main configuration file.

sudo nano /etc/postfix/main.cf

And set a value by adding the following line at the end of the file. The /etc/postfix/transport file will contain the lookup table.

transport_maps = hash:/etc/postfix/transport

If you use iRedMail, you can find the transport_maps parameter and set the value to

transport_maps =
    hash:/etc/postfix/transport
    proxy:mysql:/etc/postfix/mysql/transport_maps_user.cf
    proxy:mysql:/etc/postfix/mysql/transport_maps_domain.cf

If you use Modoboa, you can find the tranport_maps parameter and set the value to:

transport_maps =
        hash:/etc/postfix/transport
        proxy:mysql:/etc/postfix/sql-transport.cf
        proxy:mysql:/etc/postfix/sql-spliteddomains-transport.cf

Lookup table can be a file, or in the form of MySQL/MariaDB database tables. Lookup tables will be searched in the specified order until a match is found.

Save and close the Postfix main configuration file. Next, we need to create the lookup table file.

sudo nano /etc/postfix/transport

In this file, we can define mappings from recipient addresses to transport method. For example, I found that many .pl (Poland) domains are using a particular blacklist that blocks my mail server’s IP address. I can add the following line in this file so that emails sent to .pl domains will be relayed through Mailjet.

.pl                relay:[in-v3.mailjet.com]:587

Some people find that it’s hard to get into the inbox of Microsoft mailboxes (hotmail.com, outlook.com, etc). It’s very likely that you email will be put in spam folder. Well, you can try using Mailjet to deliver emails to Microsoft mailbox users. Mailjet even allows you to see if the recipient opened or clicked links in your email. So I put the following lines in the file.

hotmail.com        relay:[in-v3.mailjet.com]:587
hotmail.co.uk      relay:[in-v3.mailjet.com]:587
hotmail.fr         relay:[in-v3.mailjet.com]:587
hotmail.de         relay:[in-v3.mailjet.com]:587
outlook.com        relay:[in-v3.mailjet.com]:587
outlook.de         relay:[in-v3.mailjet.com]:587
outlook.fr         relay:[in-v3.mailjet.com]:587
outlook.be         relay:[in-v3.mailjet.com]:587
outlook.in         relay:[in-v3.mailjet.com]:587
live.com           relay:[in-v3.mailjet.com]:587

If you want to use relay host to deliver emails to a particular recipient, but send emails directly to all other recipients in the same domain, then you can add a line like below.

[email protected]  relay:[in-v3.mailjet.com]:587

If a certain SMTP server doesn’t use the default SMTP port 25, but uses a different port such as 2525 to receive incoming emails, you can add the following line

example.com        smtp:[mail.example.com]:2525

You can also add your own domain name in this file like below.

your-domain.com    local

This tells Postfix that emails sent to your own domain should be delivered locally, which is the default behavior.

If you just put the following two lines in the file and don’t add other lines, this will make all emails, excluding emails sent to your own domain, delivered via the relay host. The asterisk (*) is a wild-card character that represent any email address.

your-domain.com       local
*                     relay:[in-v3.mailjet.com]:587

We can also have the following configuration, which means that emails sent to your own domain are delivered locally. Email sent to gmail.com are delivered normally by performing MX lookup and all other emails are delivered via the relay host.

your-domain.com       local 
gmail.com             smtp
*                     relay:[in-v3.mailjet.com]:587

Save and close the file. Then run the following command to build the index file.

sudo postmap /etc/postfix/transport

Restart Postfix for the changes to take effect.

sudo systemctl restart postfix

Sender Dependent Relay Maps

The transport map defines defines mappings from recipient address to transport method. If you want to define mappings from sender address to relay hosts, use the sender_dependent_relay_maps parameter. By default, its value is empty, as can be seen with:

postconf sender_dependent_relayhost_maps

Output:

sender_dependent_relayhost_maps =

iRedMail uses MySQL/MariaDB database to store sender dependent relayhost maps. If you used iRedMail to set up your mail server, then the output should be like:

sender_dependent_relayhost_maps = proxy:mysql:/etc/postfix/mysql/sender_dependent_relayhost_maps.cf

The sender_dependent_relayhost_maps parameter points to one or more lookup tables. You can edit the Postfix main configuration file.

sudo nano /etc/postfix/main.cf

And set a value by adding the following line at the end of the file. The /etc/postfix/relay_by_sender file will contain the lookup table.

sender_dependent_relayhost_maps = hash:/etc/postfix/relay_by_sender

If you use iRedMail, you can find the sender_dependent_relayhost_maps parameter and set the value to

sender_dependent_relayhost_maps =
    hash:/etc/postfix/relay_by_sender
    proxy:mysql:/etc/postfix/mysql/sender_dependent_relayhost_maps.cf

Lookup table can be a file, or in the form of MySQL/MariaDB database tables. Lookup tables will be searched in the specified order until a match is found.

Save and close the Postfix main configuration file. Next, we need to create the lookup table file.

sudo nano /etc/postfix/relay_by_sender

Add rules like below, this will make emails sent from [email protected] delivered via the relay host specified on the right side.

[email protected]           [in-v3.mailjet.com]:587

Let’s say if you have a Linux server that hosts two websites and each website have its own mail server running on two separate hosts, then you can add the following two lines to make each website uses its own mail server.

domain1.com                     [mail.domain1.com]:587
domain2.com                     [mail.domain2.com]:587

Save and close the file. Then build the index file.

sudo postmap /etc/postfix/relay_by_sender

Restart Postfix for the changes to take effect.

sudo systemctl restart postfix

Set Up SMTP Authentication

Now we need to set up SMTP authentication so that the Postfix SMTP client can use the relay host. Edit the Postfix main configuration file.

sudo nano /etc/postfix/main.cf

Add the following lines at the end of this file. The /etc/postfix/sasl_password will contain the username and password.

# outbound relay configurations
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = may
header_size_limit = 4096000

If you have set the relayhost parameter, then I recommend giving it an empty value like below, because we are now using transport maps and sender dependent relayhost maps.

relayhost =

Save and close the file. Then create the /etc/postfix/sasl_passwd file.

sudo nano /etc/postfix/sasl_passwd

Add the SMTP relay host and SMTP credentials to this file like below. Replace api-key and secret-key with your real Mailjet API key and secret key.

in-v3.mailjet.com:587  api-key:secret-key

Save and close the file. Then create the corresponding hash db file with postmap.

sudo postmap /etc/postfix/sasl_passwd

Now you should have a file /etc/postfix/sasl_passwd.db. Restart Postfix for the changes to take effect.

sudo systemctl restart postfix

By default, sasl_passwd and sasl_passwd.db file can be read by any user on the server.  Change the permission to 600 so only root can read and write to these two files.

sudo chmod 0600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db

Testing

Now you can send test email to the recipients defined in transport maps, or send an email from the address specified in sender dependent relayhost maps. Then check the mail log (/var/log/mail.log or /var/log/maillog) to see if it’s working.

Note that if you are using a third-party SMTP relay service like Mailjet, then it’s likely that you are required to validate your domain name in your account and edit SPF and DKIM record.

Troubleshooting

If your email wasn’t delivered and you found the following message in the mail log (/var/log/maillog),

Relay access denied (in reply to RCPT TO command))

then you might need to edit the /etc/postfix/sasl_passwd file and remove the port number after the hostname like below.

in-v3.mailjet.com    api-key:secret-key

Save and close the file. Then build the index file again.

sudo postmap /etc/postfix/sasl_passwd

Restart Postfix for the changes to take effect.

sudo systemctl restart postfix

Now you can flush the email queue (attempt to deliver the previous emails).

sudo postqueue -f

Wrapping Up

I hope this tutorial helped you use Postfix transport maps and sender dependent relayhost maps. As always, if you found this post useful,  subscribe to our free newsletter to get more tips and tricks. Take care 🙂

Rate this tutorial
[Total: 1 Average: 4]

3 Responses to “Use Postfix Transport Map and Relayhost Map For Flexible Email Delivery

  • BangkokBob
    2 months ago

    This is a great tutorial! As usual! I have been waiting for this. I only have one question remaining, I use iRedmail. The transport maps are where expected. How do I edit the mysql database to redirect a domain. Is it done in the cf file or directly to the db? What is the format?
    Many thanks

    • iRedAdmin Pro users can easily manage transport maps in the admin panel. If you use the free version of iRedAdmin, you need to log into MySQL/MariaDB and use SQL command to add transport maps. More details can be found at https://docs.iredmail.org/per-account.transport.html

      You can still create transport maps on iRedMail server with the plain text file /etc/postfix/transport, if the parameter is set to:

      transport_maps =
              hash:/etc/postfix/transport
              proxy:mysql:/etc/postfix/sql-transport.cf
              proxy:mysql:/etc/postfix/sql-spliteddomains-transport.cf
      
  • Markus Fischer
    4 weeks ago

    Thanks for this tutorial… I use the sender_dependent_relayhost_maps and it works – but only for recipient domains, which are not local mail domains. This is the postfix standard and might be usefull in most cases.
    Is there an option to change this behaviour? To always use the SMTP relay insted of local delivery even if sender and recipient are on the same server?
    The use case is that the SMTP Relay Server manages archiving for example…

Leave a Comment

  • Comments with links are moderated by admin before published.
  • Your email address will not be published.
  • Use <pre> ... </pre> HTML tag to quote the output from your terminal/console.
  • Please use the community (https://community.linuxbabe.com) for questions unrelated to this article.
  • I don't have time to answer every question. Making a donation would incentivize me to spend more time answering questions.