A Linux mail server consists of software packages that can send and receive mail using the SMTP protocol and retreive mail using the standard protocols POP3 and / or IMAP. Since we are about to setup your new Linux mail server, it is important to understand the differences between the various protocols and their purposes. SMTP is typically used to deliver mail from a client to a server or pass messages from one server to another. POP3 (Post-Office Protocol) is an uni-directional protocol, which retrieves mail from the mail server and delivers it to a mail client like Mozilla’s Thunderbird. POP3 differs from IMAP with one significant respect: IMAP synchronizes messages between different d whereas POP3 simply downloads copies of messages.
The default configuration for the mail server software we are going to use to build our server is setup for a single domain. However, it is more useful to create a server that can not only accomodate multiple email addresses, but also multiple domains. The most convenient way to manage these multple domains and email addresses is to use a MySQL database as a backend.
First, let’s prepare the system by installing the required packages:
apt-get install vim postfix postfix-mysql postfix-doc mysql-client mysql-server courier-authdaemon courier-authlib-mysql courier-pop courier-pop-ssl courier-imap courier-imap-ssl libsasl2-2 libsasl2-modules libsasl2-modules-sql sasl2-bin libpam-mysql openssl phpmyadmin apache2 libapache2-mod-php5 php5 php5-mysql libpam-smbpass php5-imap
During installation, you’ll be asked the following questions:
Question 1: What type of server site do you want? Select Internet Site
Question 2: Enter the FQDN (Fully Qualified Domain Name)
This is the full domain name that you will put into in the MX Records. Make sure this has already been entered into the DNS at your registrar / name servers. The example below shows mail.domain.com, but you will want to change it to your legitimate mail server address (or backup MX record).
Question 3: Enter the administrative “root” user password.
Question 4: Create directories for web-based administration?
Question 5: Is not really a question.
It just tells you that you are going to need an SSL certificate. Just click OK.
Question 6: For the Samba server, leave the workgroup name “WORKGROUP”
Question 7: Next, phpMyAdmin will ask you to choose the web server it will use. Select Apache.
Question 8: Configure the database for phpMyAdmin with dbconfig-common? Select Yes.
Question 9: Enter the password for the database administrative user.
Question 10: Next, it will ask you for a password to register with the MySQL server. Enter in the root password you put in for question 3 above.
The installation of the software packages will continue and return you to the prompt. Next, we’ll need to configure the database system so we can support multiple domains and multiple users. The easiest way to do this is to install postfixadmin, and let postfixadmin create the database tables we will use to manage the system.
Edit the /etc/mysql/my.cnf file to ensure that bind-address on line 47 is configured to be 127.0.0.1. If it was not, change the directive to the following:
bind-address = 127.0.0.1
and then restart the MySQL service with this command:
Log into the MySQL client:
msyql -uroot -p
CREATE DATABASE postfix;
GRANT ALL ON postfix.* to 'postfixadmin'@'localhost' IDENTIFIED BY 'changethispassword';
wget -O postfixadmin.tar.gz http://sourceforge.net/projects/postfixadmin/files/latest/download
tar -zxvf postfixadmin.tar.gz
mv -v postfixadmin-2.3.5/ postfixadmin/
Edit config.inc.php, and change line 27 to set $CONF['configured'] to true:
//$CONF['configured'] = false; $CONF['configured'] = true;
Once you have completed the configuration of PostfixAdmin, you can now navigate to the setup script in the browser by going to the IP address of the server /postfix/admin.php.
Once you correct any errors, it will ask you to enter in a setup password. Enter in the password, and click the Generate Password Hash button. Once you do so, it will give you a line configuration that we will enter into config.inc.php.
Copy and paste that configuration line to the end of the config.inc.php, and then refresh the page.
Once the page is refreshed, enter in the setup password, and create a master email account that will serve as the superadmin account. Once you have completed this process, double check to make sure that the setup script has notified you of two events:
Everything seems fine... attempting to create/update database structure Database is up to date
Change directory to /var/www/
wget -O phpmyadmin.tar.gz http://downloads.sourceforge.net/project/phpmyadmin/phpMyAdmin/3.5.2/phpMyAdmin-3.5.2-english.tar.gz?r=http%3A%2F%2Fwww.phpmyadmin.net%2Fhome_page%2Fdownloads.php&ts=1342151305&use_mirror=iweb
tar -zxvf phpmyadmin.tar.gz
mv -v phpMyAdmin-3.5.2-english/ phpMyAdmin/
There are six files that we are going to configure to work with our configuration as we have set it up thus far, which are all located in /etc/postfix/:
This file tells postfix what domains the mail server will be receiving mail for. Here are the contents:
user = postfixadmin password = thepostfixadminpassword dbname = postfix query = SELECT domain AS virtual FROM domain WHERE domain='%s' hosts = 127.0.0.1
This table sets up email forwarding and aliases. Its content should be:
user = postfixadmin password = thepostfixadminpassword dbname = postfix query = SELECT goto FROM alias WHERE address='%s' hosts = 127.0.0.1
This file tells Postfix where in your local mail server’s file system the mail will be kept. The SQL statement parses the email address and turns it into a relative path from the mail root. It’s file contents are:
user = postfixadmin password = thepostfixadminpassword dbname = postfix query = SELECT CONCAT(SUBSTRING_INDEX(username,'@',-1),'/',SUBSTRING_INDEX(username,'@',1),'/') FROM mailbox WHERE username='%s' hosts = 127.0.0.1
This tells Postfix how to find and indentify aliases. It’s contents should consist of:
user = postfixadmin password = thepostfixadminpassword dbname = postfix query = SELECT username FROM mailbox WHERE username='%s' hosts = 127.0.0.1
Postfix needs to be told how to transport emails from the point of receipt to teh final destination. For our purposes (and mostly because we are configuring this server with PostfixAdmin), we are going to use “virtual” as the transport because this server receives mail for virtual hosts. The file contents and configuration for this consist of:
user = postfixadmin password = thepostfixadminpassword dbname = postfix query = SELECT transport FROM domain WHERE domain='%s' hosts = 127.0.0.1
This last configuration file tells Postfix how to limit email accounts based on a quota. Its configuration file should be:
user = postfixadmin password = thepostfixadminpassword dbname = postfix query = SELECT current FROM quota WHERE username='%s' hosts = 127.0.0.1
chmod o= /etc/postfix/mysql-virtual_*.cf chgrp postfix /etc/postfix/mysql-virtual_*.cf
groupadd -g 5000 vmail useradd -g vmail -u 5000 vmail -d /home/vmail -m
postconf -e 'myhostname = changeme.example.com' postconf -e 'mydestination = changeme.example.com, localhost, localhost.localdomain' postconf -e 'mynetworks = 127.0.0.0/8' postconf -e 'virtual_alias_domains =' postconf -e 'virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, mysql:/etc/postfix/mysql-virtual_email2email.cf' postconf -e 'virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf' postconf -e 'virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf' postconf -e 'virtual_mailbox_base = /home/vmail' postconf -e 'virtual_uid_maps = static:5000' postconf -e 'virtual_gid_maps = static:5000' postconf -e 'smtpd_sasl_auth_enable = yes' postconf -e 'broken_sasl_auth_clients = yes' postconf -e 'smtpd_sasl_authenticated_header = yes' postconf -e 'smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination' postconf -e 'smtpd_use_tls = yes' postconf -e 'smtpd_tls_cert_file = /etc/postfix/smtpd.cert' postconf -e 'smtpd_tls_key_file = /etc/postfix/smtpd.key' postconf -e 'transport_maps = proxy:mysql:/etc/postfix/mysql-virtual_transports.cf' postconf -e 'virtual_create_maildirsize = yes' postconf -e 'virtual_maildir_extended = yes' postconf -e 'virtual_mailbox_limit_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailbox_limit_maps.cf' postconf -e 'virtual_mailbox_limit_override = yes' postconf -e 'virtual_maildir_limit_message = "The user you are trying to reach is over quota."' postconf -e 'virtual_overquota_bounce = yes' postconf -e 'proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $virtual_mailbox_limit_maps'
Using the commands below, create a certificate for your server to use to send and receive secure, encrypted mail. (You may, alternatively, purchase one from a certificate authority).
cd /etc/postfix openssl req -new -outform PEM -out smtpd.cert -newkey rsa:2048 -nodes -keyout smtpd.key -keyform PEM -days 365 -x509
Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:GA Locality Name (eg, city) :Atlanta Organization Name (eg, company) [Internet Widgits Pty Ltd]:High Society for Schrödinger's Cat Lovers Organizational Unit Name (eg, section) :Cardboard Box Division Common Name (eg, YOUR name) :yourfqdn.yourdomain.com Email Address :email@example.com
Lastly, button up the permissions of our cryptographically generated key:
chmod o= /etc/postfix/smtpd.key
The Simple Authentication and Security Layer authentication daemon (Saslauthd) is a system service that handles plaintext authentication requests securely by inserting a security layer between the protocol and the connection. In layman’s terms, this provides security for connections that exchange usernames and passwords in plain text such as POP3 and IMAP.
First, we have to give it a place in which to operate. As with most Linux systems, we’re going to use the spool directory under /var/, and create a directory just for use with Postfix, then create another set of directories for saslauthd:
mkdir -p /var/spool/postfix/var/run/saslauthd
Next, we have to tell the saslauthd daemon to use our newly created directory. So, we’ll edit /etc/default/saslauthd, and navigate to the bottom line, and change this line:
OPTIONS="-c -m /var/run/saslauthd"
OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd -r"
auth required pam_mysql.so user=postfixadmin passwd=thepostfixadminpassword host=127.0.0.1 db=postfix table=mailbox usercolumn=username passwdcolumn=password crypt=1 account sufficient pam_mysql.so user=postfixadmin passwd=thepostfixadminpassword host=127.0.0.1 db=postfix table=mailbox usercolumn=username passwdcolumn=password crypt=1
Edit /etc/postfix/sasl/smtpd.conf, and put the following lines in it:
pwcheck_method: saslauthd mech_list: PLAIN LOGIN CRAM-MD5 DIGEST-MD5 NTLM allow_plaintext: true auxprop_plugin: mysql sql_hostnames: 127.0.0.1 sql_user: postfixadmin sql_passwd: thepostfixadminpassword sql_database: postfixv sql_select: select password from mailbox where email = '%u'@'%r'
Now, we’ll add the user postfix to the system, and make it a member of the sasl group so it has permissions to use sasl:
adduser postfix sasl
/etc/init.d/postfix restart /etc/init.d/saslauthd restart
Courier is a separate MTA, which is frequently used in conjuction with Postfix to provide access to mailboxes via a client. Simply put: Postfix sends and receives mail to the server, but Courier provides access so the mail can be downloaded to your email client. Courier provides a number of services such as ESMTP, IMAP, POP3, LDAP, SSL, and HTTP mail connectivity.
IPv6 is the future, but it is a non-implemented future. Courier has already embraced the IPv6 realm and decided that, by default, if you are going to connect to it via SSL, you’ll have to do it via IPv6. For now, that is not very useful for us. So, we have to force it to use the IPV4 address everyone is used to.
To Force Courier to use IPv4 for IMAP, edit /etc/courier/imapd-ssl, and change the SSLADDRESS directive to the IPv4 IP address of the network adapter.
Repeat this process for the pop3d-ssl config file:
By default, Postfix recieves email on port 25. We also want to enable it to receive mail using SSL on port 465 (the default SMTPS Port). To do so, we just need to uncomment the following lines (17-22) from /etc/postfix/master.cf:
smtps inet n - - - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o milter_macro_daemon_name=ORIGINATING
Now, just reload and restart Postfix so the settings will be applied:
postfix reload /etc/init.d/postfix restart
Like all the other services we have configured thus far, we need to tell Courier to use MySQL fr authentication. To do this, edi the following file: /etc/courier/authdaemonrc, and find the authmodulelist directive (on or about line 27). The default is authpam, but we need to change it to authmysql:
Now, let’s configure the MySQL authentication module by editing /etc/courier/authmysqlrc. Delete the existing contents of the file so that we are starting anew. (If you had a working configuration before, consider backing up the file before making this change). The entirety of the file’s contents should be:
MYSQL_SERVER localhost MYSQL_USERNAME postfixadmin MYSQL_PASSWORD thepostfixadminpassword MYSQL_PORT 0 MYSQL_DATABASE postfix MYSQL_USER_TABLE mailbox MYSQL_CRYPT_PWFIELD password #MYSQL_CLEAR_PWFIELD password MYSQL_UID_FIELD 5000 MYSQL_GID_FIELD 5000 MYSQL_LOGIN_FIELD username MYSQL_HOME_FIELD "/home/vmail" MYSQL_MAILDIR_FIELD CONCAT(SUBSTRING_INDEX(username,'@',-1),'/',SUBSTRING_INDEX(username,'@',1),'/') #MYSQL_NAME_FIELD MYSQL_QUOTA_FIELD quota
When you installed Courier, it generated some self-signed SSL certificates for localhost, but that will cause problems with mail delivery on most clients. So, we need to change that server name in the certificates to the fully qualified domain name for this mail server.
Change the IMAP Server Name
Change the POP3 Server Name
Now, we’ll need to delete and re-create the certificates for the IMAP and POP3 servers, and then restart Courier:
cd /etc/courier rm -f /etc/courier/imapd.pem rm -f /etc/courier/pop3d.pem mkimapdcert mkpop3dcert /etc/init.d/courier-authdaemon restart /etc/init.d/courier-imap restart /etc/init.d/courier-imap-ssl restart /etc/init.d/courier-pop restart /etc/init.d/courier-pop-ssl restart
As a side note, I create a script in /usr/local/sbin called restart-courier, which executes all the restarts above in the correct order to facilitate making changes to the system. You can download a copy of restart-courier here.
To be RFC Compliant, (and to ensure we get important system messages), we’ll need to modify the /etc/aliases file to route root and postmaster mail properly.
Edit the /etc/asliases file and ensure that the postmaster: root entry exists. This routes all “postmaster” mail to the “root” user.
Now, let’s route all the “root” mail to your email address (or the system administration address) by modifying the entry for root:
should be changed to:
Now, save the file, and exist the editor. Now, let’s tell Postfix to re-analyze the /etc/aliases file by running: newaliases, and then restart Postfix:
newaliases /etc/init.d/postfix restart
In the example below, you can see the mailbox structure:
SMTP has to be working in order to receive mail. Let’s test to make sure everything is in order:
You should get results like the one below:
If you notice, this configuration does give us a warning that the reverse DNS does not match the SMTP banner. There are two resolutions to this. If you are running a dedicated mail server, and this is the primary mail server, call your ISP and ask them to put a pointer record on your account so the rDNS does, indeed, match up with your domain name. Alternatively, (or if you are running a secondary mail server with multiple hosts), you can just modify main.cf to put your rDNS in the banner:
Your server may be up and running, but we need to confirm that mail can be delivered to a mailbox. We already added a domain and a mailbox to the system above, so now, let’s test and make sure mail can be directly delivered to that mailbox. To do this, we’ll use smtptest (a command line, Windows Program). Once you download and extract the .exe file, use the following syntax to sent a test email directly to your new mail server:
smtptest firstname.lastname@example.org email@example.com server=mail.server.com
Notice that we got a queued as serial number. This indicates that the message was successfully recieved by the system, the mailbox was found, validated, and available, and the message has been queued for delivery.
Testing Mail Retrievability
By now we know:
Now, we need to answer the question: Can I retrieve mail from the server?
To test this functionality, we are going to use www.mail2web.com.
If you have configured everything correctly, it should log in and you’ll see your welcome email and the test email we sent with smtptest. However, if your are getting a failure here, it is easy to debug.
How to Debug Login Failures
In the shell for the mail server, type:
tail -f /var/log/syslog
This will show you a continuous display of the log for the mail server. Once this is running, try to log in again via mail2web. If there are any errors, they will display here.
In the example above, you can see that pop3d and imapd both have an “authentication error: Input/output” error. This means that both of those services are having a hard time talking to MySQL to get information about a user credential. So, we’ll double check our configs for that part of the setup.
In this case, both were correct. So, we’ll need to turn on debugging. In /etc/courier/authdaemonrc, find the DEBUG directive, and set it to “3″
Now, we’ll restart Courier using our restart-courier script, and then re-check the syslog while we log in:
Now, you can see the error is with the SQL query we are using to authenticate users. This is contained in the /etc/courier/authmysqlrc file. Upon closer inspection, we can see that the copy / pasted SQL query contains special characters for single and double quotes. So, we’ll re-type the single and double quotes so that they are the correct, ASCII versions of the character, not a font version of the character.
Once we’ve done that, we’ll save the file and restart courier using our restart-courier script. Now, when we test again, we can log straight in!. Before we complete this part of the debugging process, don’t forget to turn DEBUG_LOGIN back to 0 in the /etc/courier/authdaemonrc file, and restart-courier once more.
Now, let’s configure Thunderbird to make sure that we can send and receive mail (before we tell users and / or clients that they can start setting up their mail accounts!)
If you are finding that you have other errors than the common issues covered in this article, be sure to sign in using your Facebook account, and leave a comment asking for help. But, before you do, make sure that you have used the tail -f /var/log/syslog command to capture the logging output of the mail server because that’s the first thing I’m going to ask for. If you’re feeling especially saucy, you could always Google it before you ask.
Help Us Out. Click +1. The more we get, the more articles we write.