Installing a Mailserver on Ubuntu 12.04 LTS Part 1

Introduction

Why I wrote this.

I wrote this HOWTO after following many other HOWTOs for Postfix and Exim and finding that parts did not work or did not explain how things worked. In short I spent many hours installing and reinstalling, playing around with settings and generally having fun. (I need to get a life) I wrote this HOWTO as record of what I did to get my own mail server up and running. I can now and in the future follow these steps again and rebuild my own mail server. I hope it is of use to others too.

We will run through the setup of this one step at a time, hopefully not making any huge steps. You will be able to test the parts installed as we go, no huge big bangs. All this as we move gently towards our goal of a professional quality mail server running on Ubuntu Server.

There are some holes in the security of this server. e.g No firewall.

Note: You are strongly recommended to take backup copies of your system and all files before you start and as we progress through the HOWTO.

Feedback.

Feedback is most certainly welcome for this HOWTO. Send your comments, criticisms and suggestions for additions or changes using the comment options below or via email using the link. I will try to reply as needed.
What This HOWTO Will Be Building.
Overview of the system.

The mail server this HOWTO will be building is called mailserver and will be running Ubuntu Server edition. mailserver will run as a Virtual Box guest which allows for simple backups if nothing else. mailserver will be part of the example.com domain with a sister domain example.net.

mailserver.example.com local IP 192.168.0.11
internet IP 1.2.3.4

Services provided on mailserver

The server called mailserver will end up running the following servers and services. Once all the parts of this series posts are completed.

  • Postfix mail server.
    • Delivering email to one or more local users.
    • Email recipients will not have to have a local Linux account.
    • Forwarding mail to remote users, from a lookup list only
    • Relaying emails to the outside world
    • Authentication and encryption TLS/SSL
  • MySQL Database

Install Ubuntu Server Edition.

We are starting from a minimal install of Ubuntu Server with no other software installed. During the installation process there will be a menu asking what other servers should be installed. Do not select any at this time.

See my HOWTO: Install Ubuntu Server as a VirtualBox guest For step by step instructions on how to set this up.

After the install is done make sure it is all up to date with the latest patches and security updates.

sudo apt-get update
sudo apt-get dist-upgrade

Install and setup ssh. You can then ssh to mailserver. Copy and paste will work better and you can make the terminals bigger. The bigger terminals make editing much easier. ❗

HOWTO: Install and Configure ssh

Install nfs and autofs. These make transferring files simpler. I used these mappings a lot while writing this HOWTO as I installed the complete system a number of times. If at first you don’t succeed, go and have another beer.

HOWTO:Set up NFS sharing

HOWTO Setup and Configure Autofs

Network interface. Get this sorted out so mailserver has a static IP address.

Make sure that the fully qualified domain name is setup and displayed correctly.

hostname --fqdn

The command above should be displaying the following for mailserver.

mailserver.example.com

It is does not the problem can be solved by editing the hosts file as follows.

sudo nano /etc/hosts
192.168.0.11 mailserver.example.com mailserver

Note that the FQDN is first in the list and the short name without the domain part is not.

This would be a good backup point!
You can always restore back to this point if you mess up on the way.

MySQL

How Postfix talks to MySQL

We are going to create a bunch of map files that tell Postfix how to get the information out of the MySQL database. They are fairly simple and I am sure you will work out how they do their mapping without explanation. In each file change mysqlpasswd to be the password you use for your MySQL user mail. Also, when setting the hosts value do not use localhost, Use the IP address 127.0.0.1, which although it is also localhost it will force postfix to use TCP/IP and not a local socket. This will allow you to run Postfix chrooted if you so wish and is slightly more secure.
Installing MySQL

Installing Postfix and MySQL we need Postfix and dovecot, along with the MySQL server and packages to connect to each. These will be installed with the following command.

sudo apt-get install postfix postfix-mysql dovecot-core dovecot-imapd dovecot-pop3d \
dovecot-lmtpd dovecot-mysql mysql-server

While these packages are installing you will be asked some questions:

MySQL Password, just make one up and remember it!
General type of mail configuration: Internet Site
System mail name: example.com

When the installation process starts you will be asked for a MySQL root password. This is the password for the root user of MySQL this is not the same as the root user on the Linux system.
Simple MySQL Security Measures

Run the script mysql_secure_installation to remove unnecessary users and the test database. It will also allow you to setup a password for the root MySQL user. But you already did that, didn’t you.

mysql_secure_installation

If you did not set a password when the MySQL server was installed the password will be blank, so you can press return. Otherwise enter the password you have already created. You will be asked a number of questions, the first one will be asking if you want to enter a new password. If you have not already set one enter ‘y’ and enter one now.

For the remaining questions you can press return to accept the default:

Remove anonymous users?
Disallow root login remotely?
Reload privilege tables now?

Configuring MySQL

We will edit the system MySQL my.cnf file to check on access and get some logging to happen.

sudo nano /etc/mysql/my.cnf

We want to bind to 127.0.0.1 not localhost. This a means there can be no connections from remote machines, which means that we have a security advantage in that only users already logged in to mailserver can access the MySQL database. It should already be set, as it is the default.

bind-address = 127.0.0.1

I find it is helpful to see what the mysql DB is doing especially in the early stages. Use these options to start the logging of any queries or requests that are made to MySQL. It is probably commented out.

general_log_file = /var/log/mysql/mysql.log
general_log = 1

Then in a few weeks when all is running correctly comment those out again, as the logging slows mysql down.

Restart the MySQL daemon.

sudo service mysql restart

Creating the Database

To create a MySQL database is very simple from the command line. We will be calling our database ‘postfix’ as it is for Postfix and I like to keep things simple. 🙂 We need to login as the user root and tell the command to ask for a password. We do that with the following command:

mysqladmin -u root -p create postfix

When you run the command above you will be asked for a password. It is the MySQL password for root, it is the one you entered when you installed MySQL server or entered when securing the MySQL installation. There is no feedback in the way of text output to say the database was created. If you want to check you can login to the database using the mysql command and issue the show databases command. If all went well you will see a line with postfix.

mysql -u root -p postfix
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| postfix            | -- This is the one we are looking for
+--------------------+
4 rows in set (0.00 sec)

The other way to monitor what is going on behind the scenes with MySQL is to watch the mysql log file. Open a new terminal and use the following command to follow the end of the log file as it is written.

tail -fn90 /var/log/mysql/mysql.log

Creating our MySQL User

We will be needing a user with restricted permissions to access the tables for lookups. This user will only need to SELECT data never INSERTing or UPDATEing.

mysql -u root -p postfix

and enter this SQL command when you see the mysql> prompt:

GRANT SELECT ON postfix.* TO mail@localhost IDENTIFIED BY 'mysqlpasswd';

This will create a new user called mail who just has SELECT access to our database. To get these new permissions noticed by Mysql you need to flush them. So before you exit the mysql prompt use the following command.

flush privileges;
SELECT user, password FROM mysql.user where user = 'mail';
Query OK, 0 rows affected (0.00 sec)

Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed

+------+-------------------------------------------+
| user | Password                                  |
+------+-------------------------------------------+
| mail | *E18AD7C50020B1483DHD5OP0D92C2AA45DDDD123 |
+------+-------------------------------------------+
1 row in set (0.00 sec)

Creating the tables

We will be using three tables to interface between Postfix and MySQL. The way I create them it to add the SQL commands to a text file and then load them in via the mysql command. This saves a lot of typing. It also means that when you are testing and trying out different options it is easy to delete all the data and start again.

USE postfix;

DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS alias;
DROP TABLE IF EXISTS domain;

CREATE TABLE domain (
   domain VARCHAR(50) NOT NULL,
   PRIMARY KEY (domain)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 

CREATE TABLE user (
   email VARCHAR(255) NOT NULL,
   domain VARCHAR(50) NOT NULL,
   password VARCHAR(110) NOT NULL,
   PRIMARY KEY (email),
   KEY (domain),
   FOREIGN KEY (domain) REFERENCES domain(domain) ON UPDATE NO ACTION ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 

CREATE TABLE `alias` (
   `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
   `source` varchar(255) NOT NULL,
   `destination` varchar(255) NOT NULL,
   PRIMARY KEY (`id`),
   KEY `source_idx` (`source`),
   KEY `dest_idx` (`destination`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Create an blank file and add the text above to a file called create_postfix_mysql_tables.sql and save it. You can then load that file and issue the commands it contains with the following:

mysql -u root -p postfix < create_postfix_mysql_tables.sql

If you want to see that the tables have now been created use the following.

mysql -u root -p postfix
mysql> show tables;
+-------------------+
| Tables_in_postfix |
+-------------------+
| alias             |
| domain            |
| user              |
+-------------------+
3 rows in set (0.00 sec)
This would be a good backup point!

Postfix

Configuring Postfix

The configuration for postfix is controlled via two files main.cf and master.cf in this part we only need to change main.cf.

sudo nano /etc/postfix/main.cf

Amend, delete or comment out the TLS lines:

Existing lines should be as follows and should be commented out:

#smtpd_tls_cert_file = /etc/ssl/certs/ssl-mail.pem
#smtpd_tls_key_file = /etc/ssl/private/ssl-mail.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

The new lines will want are:

smtpd_tls_cert_file = /etc/ssl/certs/dovecot.pem
smtpd_tls_key_file = /etc/ssl/private/dovecot.pem

# We will let the client end uses STARTTLS, if they want to
# i.e they may use it if they want
# This allows local clients i.e. Squirellmail to connect without fuss
smtpd_tls_security_level = may

Now add the following lines to the end of the file. These are to enable SMTP authenticated users

#Enabling SMTP for authenticated users, and handing off authentication to Dovecot
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/dovecot-auth
smtpd_sasl_auth_enable = yes

smtpd_recipient_restrictions = permit_sasl_authenticated,
           permit_mynetworks,
           reject_unauth_destination

Update, comment out the mydestination value so it reads:

mydestination = localhost

Add a new line to enable Dovercot's LMTP

virtual_transport = lmtp:unix:private/dovecot-lmtp

Save the changes and exit.

This would be a good backup point!

Create Postfix Map Files For MySQL

The Postfix map files are how we tell Postfix to talk to the MySQL database. Each file contains key = value pairs of data telling Postfix how it can connect and send a query to the database and therefore retrieve the data it requires. Once these map files are created we will add them to the Postfix configuration file /etc/postfix/main.cf using the command line tool postconf. The resulting change will automatically be written to the file and the postfix configuration can be reloaded.
Mapping valid Domains

How to find valid domains within our system. The domain table holds one row for each domain that our mailserver will be accepting mail for and that it will deliver to the end user. With an editor create the domain lookup file with the following details. You will need to change the password from mysqlpasswd to whatever you are using as the password for your MySQL user "mail".

sudo nano /etc/postfix/mysql-virtual-mailbox-domains.cf
user = mail
hosts = 127.0.0.1
dbname = postfix
password = mysqlpasswd
query = SELECT domain FROM domain WHERE domain = '%s'

Add the line to /etc/postfix/main.cf from the command line.

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

Mapping Users

As we are intending to use our mailserver to deliver emails to users including but not limited to those that also have Linux accounts. We need to use virtual mappings. This is so Postfix will know where to deliver the email to. It will be a directory on the file system. We certainly do not want to create a user account and home directory for all our email users. We will define a top level directory /var/vmail where the email will be stored. The data held in the mappings in the virtual tables will be used to construct the lower part of the directory tree. The actual location of the mail subdirectory. For each user we will have:

/var/vmail/vhosts//user_name

The domain and user name are derived from their actual email address for fred@example.com we will see this directory structure.

/var/vmail/vhosts/example.com/fred
sudo nano /etc/postfix/mysql-virtual-mailbox-maps.cf
user = mail
hosts = 127.0.0.1
dbname = postfix
password = mysqlpasswd
query = SELECT email FROM user WHERE email='%s'
sudo postconf -e virtual_mailbox_maps=mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf

Mapping aliases to Users

This maps email aliases to real email addresses. This means for one user name or destination we can have many email addresses. In a company all the emails for support@example.com and info@example.com will be delivered to fred@example.com. Harry is the IT administrator and therefore gets mail that is not addressed to anyone in particular. That is Harry will get mail that cannot be delivered anywhere else. Most of which will be spam so he will no doubt work out a better way to deal with it later as he gets more experience :-). This is called a 'catch all email' alias. This can also be used as an effective anti-spam system. Whenever you deal with a new company simply create a new email alias from_company@example.com aliased to your own real email address. If you start getting spam on that address you know they are spamming you or they have sold your address on. Either way you know it's a company you no longer wish to deal with. You can remove the email listing and no more spam from them. If there is no catch all email setup then those spam emails get thrown away.

sudo nano /etc/postfix/mysql-virtual-alias-maps.cf
user = mail
hosts = 127.0.0.1
dbname = postfix
password = mysqlpasswd
query = SELECT destination FROM alias WHERE source = '%s'
sudo postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf

Assuming that all worked as before we can move on to that last mapping.

This mapping table is used as part of the virtual_alias_maps mapping and saves you having to map every user back to themselves. Why would you need to do that? You ask. See below it is to do with the way catch all addresses work.

sudo nano /etc/postfix/mysql-virtual-alias-maps-self.cf
user = mail
hosts = 127.0.0.1
dbname = postfix
password = mysqlpasswd
query = SELECT email FROM user WHERE email = '%s'

The follow should be all on one line with no spaces after the '='.

sudo postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf,
                 mysql:/etc/postfix/mysql-virtual-alias-maps-self.cf
As these lookup table files all contain passwords and in open text. They should not be world readable. We can do that by restricting the group permissions and removing all world read and write permissions.
sudo chgrp postfix /etc/postfix/mysql-*.cf
sudo chmod 640 /etc/postfix/mysql-*.cf
-rw-r----- 1 root postfix 124 2013-11-12 16:46 /etc/postfix/mysql-virtual-alias-maps.cf
-rw-r----- 1 root postfix 116 2013-11-12 16:46 /etc/postfix/mysql-virtual-alias-maps-self.cf
-rw-r----- 1 root postfix 135 2013-11-12 16:45 /etc/postfix/mysql-virtual-mailbox-domains.cf
-rw-r----- 1 root postfix 114 2013-11-12 16:46 /etc/postfix/mysql-virtual-mailbox-maps.cf

Aliases are the mechanism that allows mail to be delivered in a very flexible way with a very simple setup. That is the users get their mail and you don't have too much extra work. 😉

sudo service postfix restart

Creating Some Test Users

To test those MySQL tables and the interface between Postfix and MySQL we will add some test data to the database. We can then test this is working by using the postmap command to read it back.

I also put the SQL required to build up some test data into a file so it can be loaded again when necessary while testing is on going.

USE postfix;

DELETE FROM domain;
DELETE FROM user;
DELETE FROM alias;

INSERT INTO domain (domain) VALUES ('example.com'), ('example.net');

INSERT INTO user (email, domain, password) VALUES
    ('fred@example.com', 'example.com', MD5('mysqlpasswd')),
    ('harry@example.net', 'example.net' MD5('mysqlpasswd'));

INSERT INTO alias (source, destination) VALUES
    ('root', 'fred@example.com'),
    ('bert@example.com', 'fred@example.com'),
    ('postmaster@example.com', 'fred@example.com'),
    ('@example.com', 'harry@example.net');

You can then rebuild your data base with test data with the following command.

mysql -u root -p postfix < insert_test_data.sql
mysql> SELECT * FROM domain;
+-------------+
| domain      |
+-------------+
| example.com |
| example.net |
+-------------+
2 rows in set (0.00 sec)

mysql> SELECT * FROM user;
+-------------------+-------------+----------------------------------+
| email | domain | password |
+-------------------+-------------+----------------------------------+
| fred@example.com | example.com | 63dde79649136fea1db11dec591d2cd3 |
| harry@example.net | example.net | 63dde79649136fea1db11dec591d2cd3 |
+-------------------+-------------+----------------------------------+
2 rows in set (0.00 sec)

mysql> SELECT * FROM alias;
+----+------------------+-------------------+
| id | source | destination |
+----+------------------+-------------------+
| 1 | root | fred@example.com |
| 2 | bert@example.com | fred@example.com |
| 3 | postmaster@example.com | fred@example.com |
| 4 | @example.com | harry@example.net |
+----+------------------+-------------------+
3 rows in set (0.00 sec)

We can now do some very simple tests to check the Postfix-MySQL interface it working. The fist test will lookup example.com to see if it is valid domain for our system. If it is it will return example.com. Also try this with a domain name that is not valid.

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

We can lookup a user to see if they are a real use. This test should return fred@example.com as he is valid.

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

This final test checks that aliases are working bert@example.com is an alias for fred@example.com.

sudo postmap -q bert@example.com mysql:/etc/postfix/mysql-virtual-alias-maps.cf
This would be a good backup point!

Dovecot

Installing Dovecot

To get POP3 and IMAP features from your mail server we will need Dovecot. It should have been installed above.

Creating a vmail user

We are using virtual users on this mailserver. Which means not all users will have a HOME directory in which we can store incoming emails. So we will store all mail in one directory structure as explained above. Look for a silver text box.

The email and directory structure need to be secure. We use a non privileged user vmail Lets create that user and group now.

sudo groupadd -g 6004 vmail
sudo useradd -g vmail -u 6004 vmail -d /var/vmail -m -s /sbin/nologin

To check these have been created okay, we can look in the passwd and group files.

grep vmail /etc/passwd /etc/group
/etc/passwd:vmail:x:6004:6004::/var/vmail:/sbin/nologin
/etc/group:vmail:x:6004:

Create the top level directory where emails will be stored. The remaining structure will be created as required. We also need to change the owner and group.

sudo mkdir -p /var/vmail/vhosts/example.com
sudo chown -R vmail:vmail /var/vmail

ls -dl /var/vmail/vhosts
drwxr-xr-x 3 vmail vmail 4096 Nov 30 09:52 /var/vmail/vhosts/

Configuring Dovecot

Make a copy of all the dovecot config files files before we start.

cd /etc/dovecot
sudo mkdir backup
sudo cp -a [cdR]* backup
sudo nano /etc/dovecot/dovecot.conf

Towards the top you should see the line

!include_try /usr/share/dovecot/protocols.d/*.protocol

Add the following line right after it

protocols = imap pop3 lmtp

Towards the end of the file look for a line like this, add it if necessary

!include conf.d/*.conf

Save the changes and exit.

sudo nano /etc/dovecot/conf.d/10-mail.conf

Add the fiollowing lines, you should be able to find the right place by searching for the variable name. It will most likely be commented out in the file.

mail_location = maildir:/var/vmail/vhosts/%d/%n
mail_privileged_group = vmail

Save the changes and exit.

Again, add the following lines, you should be able to find the right place by searching for the variable name. It will most likely be commented out in the file.

sudo nano /etc/dovecot/conf.d/10-auth.conf
disable_plaintext_auth = yes
auth_mechanisms = plain login
#!include auth-system.conf.ext
!include auth-sql.conf.ext

Save the changes and exit.

Create the authentication file

sudo nano /etc/dovecot/conf.d/auth-sql.conf.ext

The file auth-sql.conf.ext should contain only the following:

passdb {
   driver = sql
   args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
   driver = static
   # The home value should be the same as the mail_location from 10-mail.conf
   args = uid=vmail gid=vmail home=/var/vmail/vhosts/%d/%n
}

Save the changes and exit.

sudo nano /etc/dovecot/dovecot-sql.conf.ext

Now change the following lines after finding them in the original file. There is a password in this one change it as necessary.

    driver = mysql
    connect = host=127.0.0.1 dbname=postfix user=mail password=mysqlpasswd
    default_pass_scheme = MD5
    password_query = SELECT email as user, password FROM user WHERE email='%u';

Save the changes and exit.

sudo nano /etc/dovecot/conf.d/10-master.conf

Disable the protocols for unencrypted IMAP and POP3 by setting the ports to 0.

       service imap-login {
       inet_listener imap {
       port = 0
    }
...
}

service pop3-login {
     inet_listener pop3 {
     port = 0
  }
  ...
}

Add the following to turn on LMTP. replace the existing text block with this:

service lmtp {
   unix_listener /var/spool/postfix/private/dovecot-lmtp {
     mode = 0600
     user = postfix
     group = postfix
   }
   # Create inet listener only if you can't use the above UNIX socket
   #inet_listener lmtp {
      # Avoid making LMTP visible for the entire internet
      #address =
      #port =
   #}
}

Update the service auth block to like like this:

service auth {
    # auth_socket_path points to this userdb socket by default. It's typically
    # used by dovecot-lda, doveadm, possibly imap process, etc. Its default
    # permissions make it readable only by root, but you may need to relax these
    # permissions. Users that have access to this socket are able to get a list
    # of all usernames and get results of everyone's userdb lookups.
    unix_listener /var/spool/postfix/private/dovecot-auth {
       mode = 0666
       user = postfix
       group = postfix
    }

    unix_listener auth-userdb {
       mode = 0600
       user = vmail
       #group =
    }

    # Postfix smtp-auth
    #unix_listener /var/spool/postfix/private/dovecot-auth {
       # mode = 0666
    #}

    # Auth process is run as this user.
    user = dovecot
}

set the user to vmail in the service auth-worker block

user = vmail

Save the changes and exit.

Take the SSL cert and key file into use:

sudo nano /etc/dovecot/conf.d/10-ssl.conf
ssl = required

Save the changes and exit.

Add a default email address for errors and warnings about our mailserver. We created an alias for postmaster@example.com to fred@example.com, fred is our SysAdmin email address so he gets spammed with these 🙂

sudo nano /etc/dovecot/conf.d/15-lda.conf
postmaster_address = postmaster@example.com

Save the changes and exit.

Update the permissions as one of the files contains a password in the open. Restart dovecot to take the changes into use.

cd /etc/dovecot
sudo chown -R vmail:dovecot /etc/dovecot/*
sudo chmod 640 *conf *ext conf.d/*
sudo chmod 750 conf.d

sudo service dovecot restart

Sending Your First Email

Now it's time to send our first email 🙂 Are you sitting down, this is a momentous occasion after all!

Setting up Evolution

At this point we can set up Thunderbird or Evolution or any other email client. Using Evolution it is easy to create a new account that points at our new server. I'm sure you can work this out but here is a very quick and dirty description.

  • Server Type: IMAP+
    • Email address: fred@example.com. Forward button.
    • Server Type: IMAP+
    • Server: mailserver.example.com
    • Port: 993
    • Username: fred@example.com
    • Encryption method: SSL on Dedicated port
    • Authentication: Password
    • Server Type: POP3
      • Email address: fred@example.com. Forward button.
      • Server Type: POP3
      • Server: mailserver.example.com
      • Port: 995
      • Username: fred@example.com
      • Encryption method: SSL on Dedicated port
      • Authentication: Password
      • Server Type: SMTP
        • Server: mailserver.example.com
        • Port: 25
        • TICK, Server requires authentication
        • Encryption Mathod: start TLS after connecting
        • Username: fred@example.com
        • Auth Type: Login

      You should now be able to send and receive emails for fred@example.com YAY!

      If All is working. Now would be a good time to make a full backup of your new server.
      

      Testing from the real world

      Once that is all in place you can test it out with a real world test site. This will test your mail server is configured correctly and is not an open-relay that spammers can use. The site connects to your mail server repeatedly with different parameters and takes about a minute to finish.

      To do this test you need to know the IP address of your router on the internet side. It will not start with 192.168... You will also need to pass any connections to that IP adress on ports 993, 995 and 25 through to the machine you just configured. Use a startpage search to find out how.

      sudo telnet relay-test.mail-abuse.org
      

      You should see a message

      System appeared to reject relay attempts
      

      In Part 2

      In part 2 of this series we will be adding In this part we will be building on this server and adding anti-virus and anti-spam software and a tool to greylist emails to cut down on the work our server has to do. This will be added to postfix via amavis-new.

17 thoughts on “Installing a Mailserver on Ubuntu 12.04 LTS Part 1

  1. Ricardo Jacobs

    Thank you for your guide. I installed it on a production server but I have to wait till my domain-names are moved towards my new server. I hope I did well. Good guide.

    Reply
  2. Yuris Mangolds

    Awesome, thank you.
    You have some typos, the code:
    #Enabling SMTP for authenticated users, and handing off authentication to Dovecot
    ... [ED]

    smtpd_recipient_restrictions = permit_sasl_authenticated,
    permit_mynetworks,
    reject_unauth_destination

    Should be:
    #Enabling SMTP for authenticated users, and handing off authentication to Dovecot
    ...[ED]

    smtpd_recipient_restrictions = permit_sasl_authenticated permit_mynetworks reject_unauth_destination

    Also, the code:
    sudo postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf, \
    mysql:/etc/postfix/mysql-virtual-alias-maps-self.cf

    Should be:
    sudo postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps-self.cf

    Also, the code:
    USE postfix;
    ...[ED]
    INSERT INTO user (email, domain, password) VALUES
    ('fred@example.com', 'example.com', MD5('mysqlpasswd')),
    (''harry@example.net', 'example.net' MD5('mysqlpasswd'));
    Should be:
    USE postfix;
    ...[ED]
    INSERT INTO user (email, domain, password) VALUES
    ('fred@example.com', 'example.com', MD5('mysqlpasswd')),
    ('harry@example.net', 'example.net', MD5('mysqlpasswd'));

    Reply
    1. Richard Post author

      Thanks for the post, sorry about the typos. The last two were a good catch the first one was just bad formatting on my part the two lines with “permit_mynetworks,” and “reject_unauth_destination” can be as you said or I like to put them on seperate lines with leading white space as it makes it easier to read.

      I have updated the posting and shortened your post a little to remove some lines.

      Reply
  3. sairam

    Thanks for the post Richard.
    I’m new to Linux and this post helped me a lot to configure mail server in ubuntu.
    I hope it will work.
    I have to check it tomorrow.

    Reply
  4. Tushar Srivastava

    Hi Friend 🙂 You are very good at explaining whole thing step by step. I have configured Dovecot and Postfix as per the tutorial. It solved the first issue in hand, now I am able to access IMAP Server and I have successfully configured Windows Live connected to my IMAP server.
    Now, talking about problems that arose… Well, I have lost all the connection from outer world. Previously, I was able to send and receive emails, now, I am unable to send or receive any email. :/
    Can you help me with the issue. 🙂

    A very thank you to you already 🙂

    With Regards
    Tushar Srivastava

    Reply
    1. Richard Post author

      Not sure what your problem is as you do not give any useful information. You say you can connect to Windows live, what ever that is, and can connect to your IMAP server. I do not know what Windows live is, I do not do Windows :-). Yet, you also say, you cannot send or receive emails. Which is it?
      The post does not mess with firewall so you should have the same network connectivity as you did before. I would therefore, strongly suggest you put the backup you took before starting, you did make a backup didn’t you! Then do some more reading on the subject.

      Reply
  5. Vinay Noah

    Hey, I followed your tutorials and configured things as you told to do so but at the end I am not able to test if it is working. Also not sure what changes I have to make for MX record or any other DNS records. Is it necessary to have my own DNS server to configure email server ?

    Reply
  6. Cláudia

    Hello, good morning.
    I followed the steps above but as mandated in part of:
    USE postfix;
     
    DROP TABLE IF EXISTS domain;
    CREATE TABLE domain (
       domain VARCHAR (50) NOT NULL,
       PRIMARY KEY (domain)
    ) ENGINE = InnoDB DEFAULT CHARSET = utf8;
     
    DROP TABLE IF EXISTS user;
    CREATE TABLE user (
       email VARCHAR (255) NOT NULL,
       domain VARCHAR (50) NOT NULL,
       password varchar (110) NOT NULL,
       PRIMARY KEY (email)
       KEY (domain),
       FOREIGN KEY (domain) REFERENCES domain (domain) ON UPDATE NO ACTION ON DELETE CASCADE
    ) ENGINE = InnoDB DEFAULT CHARSET = utf8;
     
    DROP TABLE IF EXISTS alias;
    CREATE TABLE `alias` (
       `Id` int (11) unsigned NOT NULL AUTO_INCREMENT,
       `Source` varchar (255) NOT NULL,
       `Destination` varchar (255) NOT NULL,
       PRIMARY KEY (`id`),
       Source_idx KEY “ (`source`),
       Dest_idx KEY “ (`destination`)
    ) ENGINE = InnoDB DEFAULT CHARSET = utf8;

    an error occurs
    Error 1064 (42000): You have an error in your SQL syntax; check the manual que Corresponds to your MySQL server version for the right syntax to use near ‘(domain)) ENGINE = InnoDB DEFAULT CHARSET = utf8;.

    Can someone help me?

    Reply
    1. Richard Post author

      Looks like I missed off a semi-colon, my bad. I have updated the SQL posted and also moved the DROP TABLE statements to the top so the script can be run twice. It works the first time.

      I would strongly suggest you copy and paste from the web page rather than type in the SQL again. You made a number of mistakes with the “alias” table.

      Reply
  7. jb

    Thanks a lot for this tutorial. I’ve been struggling a lot for a few days now and it wasn’t until this day that I got my email server up and running.

    I just got one problem. I couldn’t make my email client to connect to the server (Microsoft Outlook 2007) and didn’t know why until I checked out the mail log (tail -f /var/log/mail.log) and found this:

    Connect failed to database (postfix): Access denied for user ‘mail’@’localhost’ (using password: YES)

    I checked every file where there was the mysqlpasswd and everything seemed just fine, but then I read on some forum that passwords containing characters other than letters and numbers use to give trouble. I was using a password like super!secure!password1 and after changing it to supersecurepassword1 everything worked out just fine.

    Any idea on how I can use characters other than letters and numbers on the password?

    Thanks a lot!

    Reply
    1. Richard Post author

      Hi

      I tried this out with the a password of !£$%^&*() , the top row of numbers shifted without a double quote. Sorry to say that it worked ok for me.
      I think you must have missed a file somewhere, you may be able to find it with the following:


      sudo -i
      cd /etc
      grep -rinH mysqlpasswd *

      It may take some time to run, but any files that contain the string mysqlpasswd will spit out a line to stdout.

      Hope that helps.

      Reply
  8. Chris

    Hi there, I have been trying to get this working for a while now, and can’t even get a connection form mxtoolbox 🙁 I’ve had postfix and exim4 working , at least with mail connections, but I could never get emails to actually work on those. With your guide I’m not even getting mail connections, mxtoolbox just says its dropped the connection and I have no idea why ?? 🙁

    Reply
    1. Richard Post author

      If you are running this on your own pc behind a router/firewall you will need to open the necessary ports so that mxtoolbox can reach your server. This should be the last step after you have it all working locally. Have you run through the tests locally from the tutorial? It is easier to debug when running these rather than using some automated server run by Goddess knows who on the internet. I do all my mail server testing in my test network lab.

      Reply
  9. dale d

    Thanks for the detailed install procedure.

    I am getting an error when attempting to send an Email to the postmaster via telnet command line. I receive 4.3.0 Error: queue file write error
    Any thoughts on what might be generating this?
    Thanks again for all your efforts.
    Dale

    Reply
    1. Richard Post author

      The error message gives a BIG clue, turn the wrods around a bit and you get “write error on queue file”. Look at the log file and change the file permissions on the file or directory that is wrong. It could also be you are running the mail server as the wrong user.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *