As this section will detail how to configure the Postfix server to receive email from the network and store it into virtual mailboxes, mailboxes not belonging to system users, we must first decide where we are going to store this email. Given that the quantity of mail we receive could be quite large, especially if we are going to try and keep up with services like Google Mail, it is probably a good idea to create a separate partition or logical volume to use for this purpose. We shall not detail how to create this storage area however we shall assume that such an area has been created and formatted with a suitable filesystem.
Once we have created and mounted our mail store we can begin to configure the Postfix server to receive and store mail there but before we do so we need to perform one more task. As our mail will be received on behalf of non-system users, and consequently they will not have a user id or group id to be used for permission settings, we shall create a user and group for this purpose and ensure that the mail store is owned and has permissions configured correctly for this user and group. We can achieve this end using the example commands given below.
Now that we have somewhere for any mail we receive to be stored we can continue the configuration process by creating some database records for a domain and a mail box. To do this we shall need to use the psql application which we used to create the tables in the previous section.
Using the psql application enter the SQL commands shown in the example below to create a domain entry for the hacking.co.uk domain and the spamcatcher mailbox. You will, as always, need to modify these values so that they reflect the domain which you are using and the name of a suitable mail box.
postgres=# INSERT INTO domains(name) VALUES('hacking.co.uk');
INSERT 0 1
postgres=# INSERT INTO mailboxes(domain_id, username, password) VALUES(1, 'spamcatcher', '$1$/g$hfp5Tly0QAzcqhfMUuRwS.');
INSERT 0 1
With our mail store created and our database records entered all which remains is to configure the Postfix server to actually use the database and message store location which we have so painstakingly created. The first part of this task requires us to revisit the Postfix configuration file and add the following configuration parameters.
virtual_mailbox_base = /mnt/mailstore
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_mailbox_domains = pgsql:/etc/postfix/pgsql/pgsql-virtual-domains.cf
virtual_mailbox_maps = pgsql:/etc/postfix/pgsql/pgsql-virtual-mailmaps.cf
As you can see the parameters we set in the above example are all fairly self explanatory. The first line configures the base directory of our mail store. All mail paths are relative to this base path which should always be configured. The second group, consisting of three lines, sets the user and group which should be used to access the mail store for a particular mailbox, in this case we are using the static mapper to always return 5000 as it makes little sense to use a different user and group for each mailbox when using a purely virtual configuration, and the minimum allowed uid which is essentially a safety net against misconfiguration if we were using table lookups for user and group values.
The final two line stanza configures Postfix to use the pgsql mapper to perform database lookups for the virtual domains which we are hosting on this server and the mappings of addresses to mailboxes. As you can see each of these entries contains a path to a configuration file which will be used to configure the pgsql mapper.
So that our pgsql mapper configuration is separated from the main Postfix configuration we shall create a new directory, under the directory already used by the Postfix daemon, and the create our pgsql specific files there.
The first file we need to create will be used to configure the pgsql mapper to access the list of domains which we are hosting on this server. As you can see from the example configuration below the syntax is very similar to that of the main Postfix configuration files consisting of variable names and their values.
hosts = database
dbname = mail
user = mail_server
password = mail_server_password
query = SELECT domain FROM active_primary_domains WHERE domain = '%s'
As usual with files of this type the configuration parameters are mostly self explanatory. The first four lines configure the database hosts which should be queried, the database name to connect to and the user name and password to connect with. The final line configures the SQL query which will be used by the pgsql mapper to determine if the domain passes the required tests to be considered as locally hosted.
Now that we have created a configuration file for the pgsql mapper which allows the Postfix daemon to map domains we need only create one more configuration file, to allow the Postfix daemon to map email addresses at those domains to mailboxes, and we are done.
The configuration example below uses the active_mailbox_maps database view we created earlier to greatly simplify the task of writing this query. It also uses two special escape sequences which the pgsql mapper will replace at runtime. It should be obvious from the SQL below that the %u sequence will be expanded to the user name portion of the email address while the %d sequence will be expanded to the domain name portion of the email address and that the query returns the path to the mailbox should it succeed.
hosts = database
dbname = mail
user = mail_server
password = mail_server_password
query = SELECT maildir FROM active_mailbox_maps WHERE username = '%u' AND domain = '%d'
With the configuration complete all that remains is to signal the Postfix server to reload its configuration using the provided script. This can be done using the command below.
Now our configuration has been loaded by Postfix we can perform another simple test, this time to see if mail is correctly accepted, queued for delivery and delivered to our virtual mailbox. We shall use the telnet application as before to connect to our server and simulate a simple mail transaction.
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.hacking.co.uk ESMTP Postfix
MAIL FROM: someone@example.com
250 2.1.0 OK
RCPT TO: spamcatcher@hacking.co.uk
250 2.1.5 OK
DATA
354 End data with <CR><LF>.<CR><LF>
To: spamcatcher@hacking.co.uk
Subject: Test Message
This is a test piece of mail.
.
250 2.0.0 OK: queued as A943D2D02
QUIT
221 2.0.0 Bye
Connection closed by foreign host.
We can now check that the mail was actually delivered using the command below.
total 4
-rw------- 1 vmail vmail 615 2008-04-07 16:18 1207592291.V811I6M569230.mail
Once we are confident that the Postfix server is correctly receiving mail on behalf of our users we can move on to the final step in this section and configure the operation of mailbox quotas so that our users do not receive more mail than we can reasonably store.
We begin by creating a new configuration file in which we shall store the parameters necessary to configure the pgsql mapper so that it is able to read the quota information from our database.
As you can see, from the configuration example below, the file is almost identical to those we used in the previous sections to configure the Postfix daemon to access our databases to look up our active domains and mailbox mappings. The only difference is the query which looks up the quota we assigned our mailbox from the authentication_view view.
hosts = database
dbname = mail
user = mail_server
password = mail_server_password
query = SELECT quota FROM authentication_view WHERE username = '%u' AND domain = '%d'
Now we have created a configuration file for the mapping of quotas to email addresses we can configure the Postfix daemon to use this file by adding the configuration settings shown below to our existing configuration. As usual we have divided our configuration into sub-sections to make it easier to see which pieces of the configuration are related.
The first section of our example contains the configuration settings required to enable quotas. The first line of this section configures the maximum mailbox size which shall be allowed if no quota is set for the user in the mailboxes table. In this instance we have decided on a limit of 1GB. The second line of this section configures the Postfix server to look for the quota assigned to a user in the database as configured in the file we created a moment ago.
The second section of the example configures some extensions to the maildir format which can greatly improve the performance of quota enforcement on large mailboxes. The first line of this section instructs the Postfix daemon to create a file to assist in the calculation of the size of the mail directory while the second line enables the use of the extended maildir format which also helps to reduce the time taken to calculate the size of a mail directory.
The third and final section controls what the Postfix daemon shall do in the event that a user's mailbox is over its assigned quota. The first line instructs the server to "bounce" the message causing a failure notification to be sent to the sender of the mail informing them of the reason it was undeliverable. The second line configures the contents of this message.
virtual_mailbox_limit = 1073741824
virtual_mailbox_limit_maps = pgsql:/etc/postfix/pgsql/pgsql-virtual-mailquotas.cf
virtual_create_maildirsize = yes
virtual_maildir_extended = yes
virtual_overquota_bounce = yes
virtual_maildir_limit_message = Sorry, the recipient's mailbox is currently full. Please try again later.
With the configuration complete all that remains is to instruct the Postfix daemon to reload its configuration so that our changes take effect. This can be performed using the command below.