Set Up SMTP Relay Between 2 Postfix SMTP Servers on CentOS/RHEL

Previously we discussed setting up Postfix SMTP relay with mailjet, which is useful when you have to use a commercial SMTP relay service. This tutorial will be showing you how to set up SMTP relay between 2 Postfix SMTP servers on CentOS/RHEL.

Use Case

Let’s say there are two servers: server A and server B.

  • You have set up a full-featured mail server on server A with Postfix as the SMTP server. You can use it to send emails directly to recipients, because port 25 isn’t blocked.
  • Later you use server B to set up a website, which needs to send notification emails to users.

You can set up another mail server on server B, but it’s a waste of time and hardware resources. A more sensible solution is to install Postfix SMTP server on server B and configure it to send emails via server A, which can relay emails from server B to the final recipients. Server A has built up its IP reputation, so you don’t have to build IP reputation for server B.

If you run WordPress on your own Linux server, I recommend you follow this tutorial to set up Postfix SMTP relay. This way, you can get rid of SMTP plugins in WordPress. WordPress plugins slow down your site and they can be vulnerable, such as the vulnerability found in the Easy WP SMTP plugin, which allows unauthorized users to modify WordPress options and execute malicious code. My site has been compromised once, because of a vulnerability in WordPress plugin. So I get rid of as many plugins as I can, when I can implement the same functionality with the underlying operating system.

Without further ado, let’s get started.

Step 1: Install Postfix SMTP Server on Server B

Run the following commands to install Postfix from the default CentOS/RHEL repository. The Cyrus SASL library is required to make SASL authentication work.

sudo dnf update

sudo dnf install postfix cyrus-sasl cyrus-sasl-plain -y

Once it’s installed, start Postfix SMTP server.

sudo systemctl start postfix

And enable auto-start at boot time.

sudo systemctl enable postfix

Step 2: Configure Postfix on Server B

Setting the Postfix hostname

By default, Postfix SMTP server uses the OS’s hostname to identify itself when communicating with other SMTP server. However, the OS hostname might change, so it’s a good practice to set the hostname directly in Postfix configuration file with the following command. Note that it’s not recommended to use the main domain (yourdomain.com) as the hostname.

sudo postconf -e "myhostname = www.yourdomain.com"

Setting $mydomain Parameter

The $mydomain parameter specifies the local internet domain name. The default is to use $myhostname minus the first component. You can display the current value of $mydomain with:

postconf mydomain

It should be your apex domain name, like

linuxbabe.com

If it’s not displaying your apex domain name, then set the $mydomain parameter with:

sudo postconf -e "mydomain = yourdomain.com"

Setting $myorigin Parameter

The $myorigin parameter specifies the default domain name that is appended to sender and recipient addresses that have no @domain part. The default is to use the value of $myhostname, as can be seen with:

postconf myorigin

Output:

myorigin = $myhostname

You can change its value to yourdomain.com.

sudo postconf -e "myorigin = yourdomain.com"

Setting $mydestination Parameter

The $mydestination parameter specifies the list of domains that your server considers itself the final destination for. You can display the current value of $mydestination with:

postconf mydestination

Output

mydestination = $myhostname, localhost.$mydomain, localhost

The default value allows your Postfix SMTP server to receive emails coming for someone@mail.yourdomain.com, someone@localhost.yourdomain.com and someone@localhost. Note that the value of mydestination should not include your main domain name like linuxbabe.com, because that will make server B as a destination for your main domain name, which means emails generated from server B for admin@yourdomain.com will be sent to server B itself, instead of server A.

Restarting Postfix

Finally, we need to restart Postfix for the changes to take effect.

sudo systemctl restart postfix

Step 3: Postfix SMTP Relay via port 587

Run the following command on server B to set the relayhost parameter. Replace mail.linuxbabe.com with the hostname of your mail server.

sudo postconf -e "relayhost = [mail.linuxbabe.com]:587"

Then edit the Postfix main configuration file on server B.

sudo nano /etc/postfix/main.cf

Add the following lines to the end of this file to configure SASL authentication. We specify that the /etc/postfix/sasl_password file contains 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

Save and close the file. Next, you should create a dedicated email account on your mail server, so server B can use this email account to login via port 587. After that, create the /etc/postfix/sasl_passwd file on server B.

sudo nano /etc/postfix/sasl_passwd

Add the SMTP relay host and SMTP credentials to this file like below. Replace these values with the hostname of your own mail server, the email account and password. Notice that there’s a colon between the email account and password.

[mail.linuxbabe.com]:587  account@linuxbabe.com:password

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

From now on, Websites on server B can use Postfix to send emails, which will be relayed through your mail server. Note that many web applications provides two email-sending modes:

  • SMTP
  • Sendmail

SMTP usually refers to the SMTP relay function in the web application itself and sendmail refers to using the SMTP server on the underlying operating system. You need to choose the sendmail option in order to use Postfix SMTP relay. If you installed SMTP plugin on your WordPress site, remove the SMTP plugin and WordPress will use Postfix SMTP relay.

If You Have iRedMail on Server A

If you used iRedMail to set up mail server on server A, then the iRedAPD policy daemon will likely to reject email relay from server B, because the sender is not same as SMTP authenticate username. To solve this problem, we need to add the SMTP authentication username to the allowed list.

Edit the iRedAPD configuration file.

sudo nano /opt/iredapd/settings.py

Add the following line at the end of the file. Replace the red text as necessary.

ALLOWED_LOGIN_MISMATCH_SENDERS = ['account@yourdomain.com']

Save and close the file. Then restart iRedAPD for the change to take effect.

sudo systemctl restart iredapd

Preventing Spammers on Server B

Since the Postfix SMTP server on server B is only used for sending transactional emails to users, we can make it listens on localhost only, so bad actors can’t send spam to it. Run the following command on server B to make Postfix listen on localhost only.

sudo postconf -e "inet_interfaces = loopback-only"

Restart Postfix for the change to take effect.

sudo systemctl restart postfix

Setting the From Address, From Name and Return-Path

By default, the From address and From name are the same as the email account that is used to authenticate login, and the return-path will be something like www-data@postfix-hostname. You can set custom From address, From name and Return-Path in your web application.

Let’s use WordPress as an example. You can add the following lines in your WordPress theme’s functions.php file to override the default From address, From name and return-path. Replace the red text as necessary. You should create the From email address on your mail server to prevent send failure.

// Function to change From email address
function wpb_sender_email( $original_email_address ) {
    return 'notifications@linuxbabe.com';
}

// Function to change sender name
function wpb_sender_name( $original_email_from ) {
    return 'LinuxBabe';
}

// Set return-path the same as From address
function fix_my_email_return_path( $phpmailer ) {
    $phpmailer->Sender = $phpmailer->From;
}

// Hooking up our functions to WordPress filters
add_filter( 'wp_mail_from', 'wpb_sender_email' );
add_filter( 'wp_mail_from_name', 'wpb_sender_name' );
add_action( 'phpmailer_init', 'fix_my_email_return_path' );

Save the file and you are done.

Checking Email Sender Score

Now you should go to https://www.mail-tester.com and send an email from the website on server B to the mail tester address. Check your sender score and see if SPF, DKIM and DMARC would pass. As you can see, I got a perfect score.

spam test result

If There Are Multiple Websites on Server B

If you have multiple websites running on server B, then you need to use different relay host for each domain name. Edit the Postfix main configuration file on server B.

sudo nano /etc/postfix/main.cf

Add the following line in the file, which tells Postfix that we want to use different relayhosts for each sender domain.

sender_dependent_relayhost_maps = hash:/etc/postfix/relay_by_sender

Then create the file.

sudo nano /etc/postfix/relay_by_sender

Add parameters like below. The lefthand side are the sender domains. The righthand side are the hostnames of the mail servers and the port number.

@domain1.com    mail.domain1.com:587
@domain2.com    mail.domain2.com:587

Save and close the file. Then edit the SASL authentication file.

sudo nano /etc/postfix/sasl_passwd

Add login credentials like below.

mail.domain1.com         account@domain1.com:password
mail.domain2.com         account@domain2.com:password

Save and close the file. Then create the hash db file.

sudo postmap /etc/postfix/relay_by_sender

sudo postmap /etc/postfix/sasl_passwd

Restart Postfix SMTP server for the changes to take effect.

sudo systemctl restart postfix

From here on out, emails with domain1.com in the Envelope From address will be relayed via mail.domain1.com and emails with domain2.com in the Envelope From address will be relayed via mail.domain2.com. Emails with other domains names in the Envelope From address will be relayed via the host specified for relayhost parameter.

Mail.domain1.com and mail.domain2.com can point to the same IP address, which means the two domain names are using the same mail server. You can check one of the following tutorials to host multiple domains on a single mail server.

You can also host emails on different servers for the two domain names. If you have multiple WordPress sites on server B, you should also change each functions.php file in your WordPress themes to set custom From address and names for each domain name.

Removing Sensitive Information from Email Headers

By default, Postfix SMTP server will add a Received: email header, recording the IP address of server B, which can leak the IP address of your website (If it’s behind CDN). You can tell Postfix to ignore it. Create a header check file on server A.

sudo nano /etc/postfix/smtp_header_checks

Put the following lines into the file.

/^Received:/            IGNORE

Save and close the file. Then edit the Postfix main configuration file.

sudo nano /etc/postfix/main.cf

Add the following line at the end of the file.

smtp_header_checks = regexp:/etc/postfix/smtp_header_checks

Save and close the file. Then run the following command to rebuild hash table.

sudo postmap /etc/postfix/smtp_header_checks

Reload Postfix for the change to take effect.

sudo systemctl reload postfix

Now Postfix won’t include those sensitive information in email headers. Note that some folks may also like removing the MIME-Version header. I don’t recommend it, because this will cause DKIM verification failure.

Troubleshooting

If Postfix on server B can’t send emails and you find the following error in the mail log (/var/log/maillog),

warning: SASL authentication failure: No worthy mechs found

you need to install the Cyrus SASL library.

sudo dnf install postfix cyrus-sasl cyrus-sasl-plain -y

Then restart Postfix.

sudo systemctl restart postfix

Conclusion

I hope this tutorial helped you set up SMTP relay between 2 Postfix SMTP servers. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care 🙂

Rate this tutorial
[Total: 0 Average: 0]

2 Responses to “Set Up SMTP Relay Between 2 Postfix SMTP Servers on CentOS/RHEL

  • AlephGamma
    4 days ago

    I tried to change the From Address, From Name and Return-Path using:

    /etc/postfix/smtp_header_checks

    It all worked except for Return-Path. Any ideas?

    • AlephGamma
      3 seconds ago

      I figured out how to change the

      Return-Path

      and more. Create an smtp_generic_map
      Contents of generic…

       user-b@server-b.domain-b    no-reply@server-a.domain-a

      Hash generic using postmap. Update main.cf

      smtp_generic_maps = hash:/etc/postfix/generic

      Restart postfix.
      Good enough for now. So far great series.

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.


The maximum upload file size: 2 MB.
You can upload: image.