Configure Postfix

 Published on 16 Feb 2025 .  Filed in Projects .  506 words

Configure Domain

Postfix receives an email for user1@example1.com and wants to find out if example1.com is a virtual mailbox domain. It will run the below SQL query and replace %s by example1.com. If it finds such a row in the virtual_domains table it will return a 1. Actually it does not matter what exactly is returns as long as there is a result.

Edit the file /etc/postfix/mysql-virtual-mailbox-domains.cf:

user = mailserver
password = x893dNj4stkHy1MKQq0USWBaX4ZZdq
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'

Now you need to make Postfix use this database mapping. The postconf command adds configuration lines to /etc/postfix/main.cf file. It also activates the new setting instantly so you do not have to reload the Postfix process:

  sudo postconf virtual_mailbox_domains=mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf

The test data you created earlier added the domain example1.com as one of your mailbox domains. Let’s ask Postfix if it recognizes that domain:

  sudo postmap -q example1.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf

Configure User

You will now define the virtual_mailbox_maps. It will map a recipient’s email address to the location of the user’s mailbox on your hard disk. Postfix has a built-in transport service called virtual that can receive the email and store it into the recipient’s email directory. That service is pretty limited, so we will delegate that to Dovecot as it allows us better control.

Postfix will forward all emails to Dovecot for further delivery. But we need to make sure that the recipient actually exists before we do that. So Postfix needs to check whether an email address belongs to a valid mailbox.

We need an SQL query that searches for an email address and returns 1 if it is found. To accomplish that please create another configuration file at /etc/postfix/mysql-virtual-mailbox-maps.cf:

user = mailserver
password = x893dNj4stkHy1MKQq0USWBaX4ZZdq
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email='%s'

Tell Postfix that this mapping file is supposed to be used for the virtual_mailbox_maps mapping:

  sudo postconf virtual_mailbox_maps=mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf

Test if Postfix is happy with this mapping by asking it where the mailbox directory of our user1@example.com user would be:

  sudo postmap -q user1@example1.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf

Again you should get 1 back which means that user1@example1.com is an existing virtual mailbox user on your server.

Configure Alias

Here your are going to define virtual_alias_maps mapping which is used for forwarding emails from one email address to one or more others. In the database multiple targets are achieved by using multiple rows.

Create another file at /etc/postfix/mysql-virtual-alias-maps.cf:

user = mailserver
password = x893dNj4stkHy1MKQq0USWBaX4ZZdq
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'

Make Postfix use this database mapping:

  sudo postconf virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf

Test if the mapping file works as expected:

  sudo postmap -q postmaster@example1.com mysql:/etc/postfix/mysql-virtual-alias-maps.cf

You should see the expected destination:

  user1@example1.com

So if Postfix receives an email for postmaster@example1.com it will redirect it to user1@example1.com.

Fix Permissions

We need to make sure that only root and the postfix user can read the .cf files because database password is stored these files:

  chgrp postfix /etc/postfix/mysql-*.cf
  chmod u=rw,g=r,o= /etc/postfix/mysql-*.cf