... because from time to time I'm a web developer, too
About me
Projects
Contact
Links

I’m building mail server

November 3, 2009 | linux, other, tools
author: Karol Zielinski | comments: 0 | views: 1428
Tags: , , , , ,

I want to build mail server on my VPS (ubuntu). What I want to have is: multiple domains and users; users’ accounts in MySQL database; Courier package to control my pop and imap access to the emails. So.. let’s do it.

Setting the hostname

Check your hostname:

hostname -f

If it’s ok – skip this step. If it’s not:

sudo vim /etc/hostname

Replace the hostname with your mail server hostname.

sudo vim /etc/hosts

replace your current hostname to new one.

Now

sudo reboot

and check hostname again. It should be ok right now.

Set Reverse DNS / RDNS

It’s some kind of unique. Each VPS has its own procedure for setting RDNS.

First… check your actual RDNS:

dig -x YOUR_IP

There should be your hostname. If it’s not – you need to set it. More about Reverse DNS you can find here.

Create user and mailboxes

Now, we will create user ‘vmail’. Using this name is a common way of identifying the system user where the mail is physically located.

sudo groupadd -g 5000 vmail
sudo useradd -s /usr/sbin/nologin -g vmail -u 5000 vmail -d /home/vmail -m

The second command creates the ‘vmail’ user, ensures they can’t login (it is not a normal account), adds them to the ‘vmail’ group and creates the home directory.

Install Postfix and MySQL

sudo apt-get install postfix postfix-mysql mysql-server postfix-tls libsasl2-2 libsasl2-modules libsasl2-modules-sql sasl2-bin libpam-mysql openssl telnet mailx

For MySQL: you will need to set new password for root.
For Postfix: Choose ‘Internet Site’ for type of mail condfiguration and set your new hostname as a system mail name.

Creating MySQL database

mysql -u root -p

use your MySQL’s root password to log in.

CREATE DATABASE mail;
CREATE USER 'mailadmin'@'localhost' IDENTIFIED BY 'newpassword';
FLUSH PRIVILEGES;
GRANT SELECT, INSERT, UPDATE, DELETE ON `mail` . * TO 'mailadmin'@'localhost';
FLUSH PRIVILEGES;

Do replace ‘newpassword’ with a password of your choosing.

Now we have new database (mail) and new user (mailadmin) with privileges (GRANT SELECT, INSERT, UPDATE, DELETE).

Next…

USE mail;

and create some tables in our database…

for domains:

CREATE TABLE domains (
domain varchar(50) NOT NULL,
PRIMARY KEY (domain)
)
TYPE=MyISAM;

for users:

CREATE TABLE users (
email varchar(80) NOT NULL,
password varchar(20) NOT NULL,
PRIMARY KEY (email)
)
TYPE=MyISAM;

for forwards:

CREATE TABLE forwards (
source varchar(80) NOT NULL,
destination TEXT NOT NULL,
PRIMARY KEY (source)
)
TYPE=MyISAM;

Leave your MySQL console.

Configuring Postfix

To enable Postfix to use the MySQL database we need to create some text files.

sudo vim /etc/postfix/mysql-domains.cf

and add there:

user = mailadmin
password = newpassword
dbname = mail
query = SELECT domain AS virtual FROM domains WHERE domain='%s'
hosts = 127.0.0.1
sudo vim /etc/postfix/mysql-forwards.cf

and add there:

user = mailadmin
password = newpassword
dbname = mail
query = SELECT destination FROM forwards WHERE source='%s'
hosts = 127.0.0.1
sudo vim /etc/postfix/mysql-mailboxes.cf

and add there:

user = mailadmin
password = newpassword
dbname = mail
query = SELECT CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') FROM users WHERE email='%s'
hosts = 127.0.0.1
sudo vim /etc/postfix/mysql-email.cf

and add there:

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

Set the permissions on the files…

sudo chmod o= /etc/postfix/mysql-*
sudo chgrp postfix /etc/postfix/mysql-*

Now… the hardest part: configure main.cf.

sudo vim /etc/postfix/main.cf

My file looks like this:

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

append_dot_mydomain = no

readme_directory = no

smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_authenticated_header = yes
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_use_tls = yes
smtpd_tls_cert_file = /etc/ssl/certs/mailcert.pem
smtpd_tls_key_file = $smtpd_tls_cert_file

myhostname = HERE_IS_MY_HOSTNAME
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination =
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all

virtual_alias_domains =
virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-forwards.cf, mysql:/etc/postfix/mysql-email.cf
virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-domains.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-mailboxes.cf
virtual_mailbox_base = /home/vmail
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000

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

Replace HERE_IS_MY_HOSTNAME by your hostname.

I won’t describe each option… for me – it works good enough. All the informations about these parameters you can find here.

Saslauthd

Saslauth is “a daemon process that handles plaintext authentication requests on behalf of the SASL library.”

sudo vim /etc/default/saslauthd

Change START variable to ‘yes’:

# Should saslauthd run automatically on startup? (default: no)
START=yes

and OPTIONS variable to:

# Example for postfix users: "-c -m /var/spool/postfix/var/run/saslauthd"
OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd -r"

Now we need to create missing directory:

sudo mkdir -p /var/spool/postfix/var/run/saslauthd

and two other files to allow the authorisation process access to the db holding the relevant data:

sudo vim /etc/pam.d/smtp

add there:

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

and the second file…

sudo vim /etc/postfix/sasl/smtpd.conf

add there:

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

Now we need to add postfix to the sasl group so it can access the saslauthd process we just setup.

sudo adduser postfix sasl

restart postfix and saslauthd

sudo /etc/init.d/postfix restart
sudo /etc/init.d/saslauthd restart

Create SSL certificate

We will need to create a self signed certificate.

It will produce a warning from your mail client, but for your own usage… that’s ok.
Remember that you will need to purchase a valid certificate if other people or clients will use this mail server.

However now we will create self signed certificate…

sudo make-ssl-cert /usr/share/ssl-cert/ssleay.cnf /etc/ssl/certs/mailcert.pem

You will be asked a series of questions regarding the details for the certificate. Don’t be scared… just answer them.

Note is is important the Hostname matches the mail server hostname.

Now we have our certificate in ‘/etc/ssl/certs/mailcert.pem’ (just like we have above in our main.cf).

Courier

First… install it:

sudo aptitude install courier-authdaemon courier-authlib-mysql courier-pop courier-pop-ssl courier-imap courier-imap-ssl

During the installation you will be asked if you wish to create directories for web based administration – select ‘No’.

Now we need to configure Courier to access the MySQL ‘mail’ database for authorisation.

sudo vim /etc/courier/authdaemonrc

and change value of authmodulelist variable to ‘authmysql’, so it should looks like:

authmodulelist="authmysql"

Set the details of the MySQL database:

sudo vim /etc/courier/authmysqlrc

this file should looks like:

MYSQL_SERVER localhost
MYSQL_USERNAME mailadmin
MYSQL_PASSWORD newpassword
MYSQL_PORT 0
MYSQL_DATABASE mail
MYSQL_USER_TABLE users
MYSQL_CRYPT_PWFIELD password
MYSQL_UID_FIELD 5000
MYSQL_GID_FIELD 5000
MYSQL_LOGIN_FIELD email
MYSQL_HOME_FIELD "/home/vmail"
MYSQL_MAILDIR_FIELD CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/')

Restart courier:

sudo /etc/init.d/courier-authdaemon restart
sudo /etc/init.d/courier-imap restart
sudo /etc/init.d/courier-imap-ssl restart
sudo /etc/init.d/courier-pop restart
sudo /etc/init.d/courier-pop-ssl restart

Add domains and users

Log in to your MySQL console:

mysql -u root -p

Next…

USE mail;
INSERT INTO domains (domain) VALUES ('mydomain.com');
INSERT INTO users (email, password) VALUES ('karol@mydomain.com', ENCRYPT('my_super_secret_password'));
quit;

Reload Postfix:

sudo postfix reload

THE END.
Everything should works fine right now.

Test it!

First test

ls /home/vmail

It’s empty, right?
That’s because the correct folders are only created on receipt of the first email.

So… send some mail to your new e-mail address (in my example it’s karol@mydomain.com).

and look again:

ls /home/vmail

there is a new folder named ‘domain.com’, right? Sure, yeah. It works!

Second test

Configure some of your mail program… such as Outlook, Thunderbird or even gmail and check it via ‘standard way’! Receive some mails, send some mails.
Remember that your username is your full e-mail address (in my example it’s karol@domain.com).

Bookmark and Share
Post I’m building mail server to develway Post I’m building mail server to Delicious Post I’m building mail server to Digg Post I’m building mail server to Facebook Post I’m building mail server to Reddit Post I’m building mail server to StumbleUpon

Related news and resources

Write a comment

Karol Zielinski :: Just a tech stuff Hello, I'm Karol Zielinski, internet evangelist, an entrepreneur, project manager and a web developer from Gdynia, Poland. I like creative design, good advertisement, social media and all kind of stuff around the web.

Most popular posts

Much more links

Karol Zielinski    |   contact me
Gdynia, Poland
RSS - Just a tech stuff - python, java blog - web development blog Karol Zielinski on twitter Karol Zielinski on LinkedIn Karol Zielinski on facebook Karol Zielinski on delicious Karol Zielinski on digg Karol Zielinski on flickr Karol Zielinski on stumbleupon Karol Zielinski on technorati