Mail Server with Postfix, Dovecot and MySQL on Ubuntu 10.04 LTS using Virtual Domain

posted in: Computers | 3

=== Install Packages ===
Let’s start by installing the corresponding packages needed for a virtual domain mail server in Ubuntu 10.04 by issuing the following install commands:

apt-get install postfix postfix-mysql postfix-doc mysql-client mysql-server dovecot-common dovecot-imapd dovecot-pop3d
apt-get install libsasl2-2 libsasl2-modules libsasl2-modules-sql sasl2-bin libpam-mysql

First set proper server hostname with its FQDN (Fully Qualified Domain Name).
hostname -f unpatti.inherent-dikti.net

=== MySQL: Create Database, Tables and Users ====
Login to MySQL and create corresponding database, tables and users:

CREATE DATABASE mail;
USE mail;

GRANT SELECT, INSERT, UPDATE, DELETE ON mail.* TO 'mailadmin'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE, DELETE ON mail.* TO 'mailadmin'@'localhost.localdomain' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;

CREATE TABLE domains (domain varchar(50) NOT NULL, PRIMARY KEY (domain) );
CREATE TABLE forwardings (source varchar(80) NOT NULL, destination TEXT NOT NULL, PRIMARY KEY (source) );
CREATE TABLE users (email varchar(80) NOT NULL, password varchar(20) NOT NULL, PRIMARY KEY (email) );
CREATE TABLE transport ( domain varchar(128) NOT NULL default '', transport varchar(128) NOT NULL default '', UNIQUE KEY domain (domain) );
quit;

=== Create Configuration files ===

nano /etc/postfix/mysql-virtual_domains.cf
Copy and paste the following contents, change somepassword to an appropriate one.

user = mailadmin
password = somepassword
dbname = mail
query = SELECT domain AS virtual FROM domains WHERE domain='%s'
hosts = 127.0.0.1

nano /etc/postfix/mysql-virtual_forwardings.cf
Copy and paste the following contents, change somepassword to an appropriate one.

user = mailadmin
password = somepassword
dbname = mail
query = SELECT destination FROM forwardings WHERE source='%s'
hosts = 127.0.0.1

nano /etc/postfix/mysql-virtual_mailboxes.cf
Copy and paste the following contents, change somepassword to an appropriate one.

user = mailadmin
password = somepassword
dbname = mail
query = SELECT CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') FROM users WHERE email='%s'
hosts = 127.0.0.1

nano /etc/postfix/mysql-virtual_email2email.cf
Copy and paste the following contents, change somepassword to an appropriate one.

user = mailadmin
password = somepassword
dbname = mail
query = SELECT email FROM users WHERE email='%s'
hosts = 127.0.0.1

Set proper permissions and ownership for these configuration files by issuing the following commands:
chmod o= /etc/postfix/mysql-virtual_*.cf
chgrp postfix /etc/postfix/mysql-virtual_*.cf

create a user and group for mail handling. All virtual mailboxes will be stored under this user’s home directory.

groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /home/vmail -m

Issue the following commands to complete the remaining steps required for Postfix configuration, be sure to replace “unpatti.inherent-dikti.net” with the fully qualified domain name for your system mail name.

postconf -e 'myhostname = unpatti.inherent-dikti.net'
postconf -e 'mydestination = '
mynetworks = 127.0.0.0/8 [::1]/128
postconf -e 'message_size_limit = 30720000'
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 'virtual_create_maildirsize = yes'
postconf -e 'virtual_maildir_extended = 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'
postconf -e virtual_transport=dovecot
postconf -e dovecot_destination_recipient_limit=1

Example of my Postfix main.cf contents are shown below.
=================== Example of MAIN.CF =====

# See /usr/share/postfix/main.cf.dist for a commented, more complete version
# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = /usr/share/doc/postfix

# TLS parameters
smtpd_tls_cert_file = /etc/postfix/smtpd.cert
smtpd_tls_key_file = /etc/postfix/smtpd.key
smtpd_use_tls = yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

myhostname = unpatti.inherent-dikti.net
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination =
relayhost =
mynetworks = 127.0.0.0/8 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
#inet_protocols = all

# Virtual Mailbox Domain Settings

virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, mysql:/etc/postfix/mysql-virtual_email2email.cf
virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf
virtual_mailbox_limit = 51200000
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_mailbox_base = /home/vmail
virtual_transport = dovecot

smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
inet_protocols = all
message_size_limit = 30720000
virtual_alias_domains =
smtpd_sasl_authenticated_header = yes
virtual_maildir_extended = yes
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
dovecot_destination_recipient_limit = 1
html_directory = /usr/share/doc/postfix/html

=================== End of Example of MAIN.CF =====

Create an SSL Certificate for Postfix ===
Issue the following commands to create the SSL certificate:

cd /etc/postfix
openssl req -new -outform PEM -out smtpd.cert -newkey rsa:2048 -nodes -keyout smtpd.key -keyform PEM -days 365 -x509

Enter the appropriate information for your server, remember to use a FQDN mail name for Common Name line in the place of unpatti.inherent-dikti.net

Country Name (2 letter code) [AU]:ID
State or Province Name (full name) [Some-State]:Maluku
Locality Name (eg, city) []:Ambon
Organization Name (eg, company) [Internet Widgits Pty Ltd]:UNPATTI
Organizational Unit Name (eg, section) []:INHERENT
Common Name (eg, YOUR name) []:unpatti.inherent-dikti.net
Email Address []:postmaster@unpatti.inherent-dikti.net

Set proper permissions for the key file by issuing the following command:
chmod o= /etc/postfix/smtpd.key

=== Configure saslauthd to use MySQL ===

Create a directory for saslauthd:
mkdir -p /var/spool/postfix/var/run/saslauthd

Make a backup copy of the /etc/default/saslauthd:
cp -a /etc/default/saslauthd /etc/default/saslauthd.bak

Edit the file /etc/default/saslauthd to match the configuration shown below.
nano /etc/default/saslauthd

Copy and paste the following contents.

START=yes
DESC="SASL Authentication Daemon"
NAME="saslauthd"
MECHANISMS="pam"
MECH_OPTIONS=""
THREADS=5
OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd -r"

Create the file /etc/pam.d/smtp and copy in the following two lines. Be sure to change “mailadmin_password” to the password you chose for your mail administration of MySQL user.
nano /etc/pam.d/smtp

Copy and paste the following contents.

auth required pam_mysql.so user=mailadmin passwd=somepassword host=127.0.0.1 db=mail table=users usercolumn=email passwdcolumn=password crypt=1
account sufficient pam_mysql.so user=mailadmin passwd=somepassword host=127.0.0.1 db=mail table=users usercolumn=email passwdcolumn=password crypt=1

Create a file named /etc/postfix/sasl/smtpd.conf with the following contents. Be sure to change “somepassword” to the password you chose for your mail administration of MySQL user.
nano /etc/postfix/sasl/smtpd.conf

Copy and paste the following contents, change somepassword to an appropriate one.

pwcheck_method: saslauthd
mech_list: plain login
allow_plaintext: true
auxprop_plugin: mysql
sql_hostnames: 127.0.0.1
sql_user: mailadmin
sql_passwd: somepassword
sql_database: mail
sql_select: select password from users where email = '%u'

Set proper permissions and ownership for these configuration files:
chmod o= /etc/pam.d/smtp
chmod o= /etc/postfix/sasl/smtpd.conf

Add the Postfix user to the sasl group and restart Postfix and saslauthd by issuing the following commands:
adduser postfix sasl
service postfix restart
service saslauthd restart

=== Configure Dovecot ===
Edit the file /etc/postfix/master.cf
nano /etc/postfix/master.cf

Add the dovecot service content to the bottom of the file.

dovecot   unix  -       n       n       -       -       pipe
flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -d ${recipient}

Make a backup copy of /etc/dovecot/dovecot.conf file.
cp -a /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.bak

Edit /etc/dovecot/dovecot.conf file.
nano /etc/dovecot/dovecot.conf

Replace the contents of the file with the following example, substituting your system’s domain name to replace unpatti.inherent-dikti.net
Copy and paste the following contents.

protocols = imap imaps pop3 pop3s
log_timestamp = "%Y-%m-%d %H:%M:%S "
mail_location = maildir:/home/vmail/%d/%n/Maildir

ssl_cert_file = /etc/ssl/certs/dovecot.pem
ssl_key_file = /etc/ssl/private/dovecot.pem

namespace private {
separator = .
prefix = INBOX.
inbox = yes
}

protocol lda {
log_path = /home/vmail/dovecot-deliver.log
auth_socket_path = /var/run/dovecot/auth-master
postmaster_address = postmaster@unpatti.inherent-dikti.net
mail_plugins = sieve
global_script_path = /home/vmail/globalsieverc
}

protocol pop3 {
pop3_uidl_format = %08Xu%08Xv
}

auth default {
user = root

passdb sql {
args = /etc/dovecot/dovecot-sql.conf
}

userdb static {
args = uid=5000 gid=5000 home=/home/vmail/%d/%n allow_all_users=yes
}

socket listen {
master {
path = /var/run/dovecot/auth-master
mode = 0600
user = vmail
}

client {
path = /var/spool/postfix/private/auth
mode = 0660
user = postfix
group = postfix
}
}
}

MySQL will be used to store password information, so /etc/dovecot/dovecot-sql.conf must be edited.
Make a backup copy of the existing file.

cp -a /etc/dovecot/dovecot-sql.conf /etc/dovecot/dovecot-sql.conf.bak

Replace the contents of the file with the following example, making sure to replace “mailadmin_password” with your mail password.

nano /etc/dovecot/dovecot-sql.conf

driver = mysql
connect = host=127.0.0.1 dbname=mail user=mailadmin password=somepassword
default_pass_scheme = CRYPT
password_query = SELECT email as user, password FROM users WHERE email='%u';

Dovecot has now been configured. You must restart it to make sure it is working properly:
service dovecot restart

Check the /var/log/mail.log to make sure dovecot started without errors.
tail /var/log/mail.log

The log should have lines similar to the following:
Aug 1 22:16:32 unpatti dovecot: Dovecot v1.2.9 starting up (core dumps disabled)
Aug 1 22:16:32 unpatti dovecot: auth-worker(default): mysql: Connected to 127.0.0.1 (mail)

Change the permissions on /etc/dovecot/dovecot.conf to allow the vmail user to access them:

chgrp vmail /etc/dovecot/dovecot.conf
chmod g+r /etc/dovecot/dovecot.conf

Test the POP3 server to make sure it’s running properly
telnet localhost pop3

=== Configure Mail Aliases ===

nano /etc/aliases

Copy and paste the following contents.

postmaster: root
root: postmaster@unpatti.inherent-dikti.net

Run the following commands to update aliases and restart Postfix:

newaliases
service postfix restart

=== Testing Postfix section ===

To test Postfix for SMTP-AUTH and TLS, issue the following command:
telnet localhost 25

While connected to Postfix, issue the following command:
ehlo localhost

Check the output, you should see the line “250-STARTTLS” included.
Issue the command quit to terminate the Postfix connection.

Setting up Domains and Users ===
Login to MySQL to create domain and email user name / address:

mysql -u root -p

USE mail;
INSERT INTO domains (domain) VALUES ('unpatti.inherent-dikti.net');
INSERT INTO users (email, password) VALUES ('admin@unpatti.inherent-dikti.net', ENCRYPT('somepassword'));
INSERT INTO users (email, password) VALUES ('postmaster@unpatti.inherent-dikti.net', ENCRYPT('somepassword'));
INSERT INTO users (email, password) VALUES ('hostmaster@unpatti.inherent-dikti.net', ENCRYPT('somepassword'));
INSERT INTO users (email, password) VALUES ('latunyj@unpatti.inherent-dikti.net', ENCRYPT('mypassword'));
quit;

Replace the above email addresses and passwords that suits your system.

it is needed to send a welcome message to new email accounts before they can be accessed via IMAP or POP3. This is because the mailboxes for new users will not be created until an email is received for them.

=== Check Mail Server Logs ===
After welcome / test mail had been sent the test mail, you’ll want to check your error logs to make sure the mail was delivered. First check your mail.log located in /var/log/mail.log. You should see something similar to the following:

Aug 1 23:45:54 unpatti postfix/cleanup[7383]: 0E631400968: message-id=<5162.180.216.122.76.1312260058.squirrel@localhost>
Aug 1 23:45:54 unpatti postfix/qmgr[7168]: 0E631400968: from=<beta@localhost>, size=1516, nrcpt=1 (queue active)
Aug 1 23:45:55 unpatti postfix/pipe[7384]: 0E631400968: to=<latunyj@unpatti.inherent-dikti.net>, relay=dovecot, delay=2.7, delays=2.6/0.01/0/0.14, dsn=2.0.0, status=sent (delivered via dovecot service)Aug 1 23:45:55 unpatti postfix/qmgr[7168]: 0E631400968: removed

cat /home/vmail/dovecot-deliver.log

Next, check the Dovecot delivery log located in /home/vmail/dovecot-deliver.log. The contents should look similar to the following:

2011-08-01 23:45:55 deliver(latunyj@unpatti.inherent-dikti.net): Info: msgid=<5162.180.216.122.76.1312260058.squirrel@localhost>: saved mail to INBOX

=== Test the Mailbox ===

cd /home/vmail/unpatti.inherent-dikti.net/latunyj/Maildir
find

The output similar to the following should be seen:
.
./new
./new/1312209954.M981760P7385.unpatti.inherent-dikti.net,S=1571,W=1604
./cur
./dovecot.index.log
./dovecot-uidlist
./dovecot-uidvalidity
./tmp
./dovecot-uidvalidity.4e36bc22

Up to this section the mail server using Virtual Domain with Postfix, MySQL and Dovecot is ready. Squirrelmail can be installed to provide a web-based mail access to users.

Reference: http://library.linode.com/email/postfix/dovecot-mysql-ubuntu-10.04-lucid