How To Setup your own Mail Server with anti-spam configuration in 60 minutes

Flattr the authorTweet about this on TwitterShare on RedditShare on FacebookEmail this to someone


This tutorial will teach you how to set up your own robust email server. We are focusing on a small personal server with up to a few email accounts. After following this guide, you will have a fully functional mail server and you can connect with your favourite client to access, read and send emails. The Anti-Spam configuration will drop unwanted messages.

This tutorial will use as domain name and as hostname for our mail server. The desired email address will be We assume that our server has the IP address

Software and technologies used

  • Postfix v2.9.6 as SMTP server
  • Dovecot v2.0.19 as IMAP server
  • We will use Unix user accounts and tunnel the SASL authentication through TLS
  • Postgrey v1.34 – to reject spam from the beginning
    (more about postgrey)
  • SPF (Sender Policy Framework) validating to reduce spam
    (more aboutSPF)
  • SPF and DMARC DNS entry to prevent spoofing
  • DKIM (Domain Keys Identified Mail) to sign our email messages
    (moreabout DKIM)



Every step will be explained in the tutorial and you will get it running even with minimal Unix knowledge. Nevertheless, you should be used to work on the command-line and know how to use a text editor. Furthermore it takes some Unix skills to administrate the working mail server.
You’re invited to follow the links in this tutorial to learn more about the software and techniques used.


  • A VPS running Ubuntu 12.04 (setup will be similar on any Debian based distribution). (Get a VPS here)
  • Your own FQDN domain name.

We will be working on a root shell and the tutorial will use vim as text editor.

Preparing our system

Setting up the host name

echo > /etc/hostname

Adding our domain to /etc/hosts

vim /etc/hosts

We add and in the first line. localhost

Setting up the mailname

echo > /etc/mailname

That’s the name that will appear on the right side of the ‘@’ in our email address. In this case,

Installing required packages

Updating the system

apt-get update && apt-get upgrade


apt-get install postfix postfix-policyd-spf-perl postgrey dovecot-core dovecot-imapd opendkim opendkim-tools && postfix stop

Choose Internet Site and press ‘ok’ 2 times when asked by the postfix installer.

Setting up DNS

We assume that our domain is already setup in the DNS control panel and we see the default DNS records.
DNS default

Setting up the A record


(There is a ‘dot’ after the domain name)

Setting up the MX record


(There is a ‘dot’ after the domain name)

Setting up the SPF record

We create a new TXT record

"v=spf1 a mx ip4: -all"


The SPF record protects from email spoofing. It will simply tell other mail servers that only our server is authorized to send emails for (more aboutSPF).

Setting up the DMARC record

We create a new TXT record named
(There is a ‘dot’ after the domain name)

"v=DMARC1; p=quarantine;"

Now we will setup the hostname for the PTR record


Our configuration should look similar to this


It will take a while to propagate the new configuration throughout the entire internet.

Generating SSL certificates

There are different ways to generate a SSL certificate. The tutorial will use a self signed certificate but we could also use a CAcert, which can be obtained for free from startssl.
Either ways, the connection from our email client to the mail server will be encrypted.

Creating the certificate

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/mail.yourdomain.key -out /etc/ssl/certs/mail.yourdomain.pem

We will be asked to answer a few questions. It is important that we enter as Common name.

Generating a 2048 bit RSA private key
writing new private key to '/etc/ssl/private/mail.yourdomain.key'
- -----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
- -----
Country Name (2 letter code) [AU]:AT
State or Province Name (full name) [Some-State]:Styria
Locality Name (eg, city) []:Vienna
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []
Email Address []

Postfix Configuration

Backing up the configuration files

cp /etc/postfix/ /etc/postfix/master.cf_orig &&
cp /etc/postfix/ /etc/postfix/main.cf_orig

Configuration in

vim /etc/postfix/

We empty the file and add our configuration

#Base config
myhostname =
myorigin = /etc/mailname
mydestination = $myhostname, $mydomain, localhost, localhost.$mydomain
relayhost =
mynetworks = [::ffff:]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
relay_domains = $mydestination
#Aliases / Recipients
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
local_recipient_maps = proxy:unix:passwd.byname $alias_maps
smtpd_tls_auth_only = yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_tls_protocols = !SSLv2, !SSLv3
#Security and Anti-Spam cinfig
policy-spf_time_limit = 3600s
smtpd_helo_required = yes

smtpd_recipient_restrictions =
check_policy_service unix:private/policy-spf
check_policy_service inet:

smtpd_helo_restrictions =


smtpd_data_restrictions =

milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891

Configuration in

vim /etc/postfix/

This line must be active:

smtp inet n - - - - smtpd

We uncomment the following:

submission inet n - - - - smtpd

and add those 2 lines at the end of the file (there are 2 whitespaces
before the second line).

policy-spf unix - n n - - spawn
user=nobody argv=/usr/sbin/postfix-policyd-spf-perl

More information about the postfix configuration parameters can be found here.

Dovecot Configuration

Backing up the configuration file

cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf_orig

Configuration in dovecot.conf

vim /etc/dovecot/dovecot.conf

We empty the file and add our configuration.

disable_plaintext_auth = no
mail_privileged_group = mail
mail_location = mbox:~/mail:INBOX=/var/mail/%u
userdb {
driver = passwd

passdb {
args = %s
driver = pam
protocols = " imap"

protocol imap {
mail_plugins = " autocreate"
plugin {
autocreate = Trash
autocreate2 = Sent
autosubscribe = Trash
autosubscribe2 = Sent

service auth {
unix_listener /var/spool/postfix/private/auth {
group = postfix
mode = 0660
user = postfix
ssl_cert = </etc/ssl/certs/mail.yourdomain.pem
ssl_key = </etc/ssl/private/mail.yourdomain.key

More information about the dovecot configuration parameters can be found here.

Restarting dovecot

service dovecot restart

Adding our mail user

Now we add the user for our mail account. In this example our email
address will be
We can add as many users/email addresses as we want.

adduser --gecos '' --shell /bin/false yourname

Setting Aliases

vim /etc/aliases

The configuration can be adapted to your needs.
Here we tell postfix to forward all messages addressed to aliases to the mailbox of user: yourname.

mailer-daemon: postmaster
postmaster: root
nobody: root
hostmaster: root
usenet: root
news: root
webmaster: root
www: root
ftp: root
abuse: root
noc: root
security: root
admin: root
root: yourname

Compiling the alias file


Setting up DKIM (Domain Keys Identified Mail)

Creating the directory and files

mkdir /etc/opendkim
vim /etc/opendkim/KeyTable

We enter the following line (all in the first line):
vim /etc/opendkim/SigningTable

We enter the following line:


Generating the key pair

opendkim-genkey -s default -d -D /etc/opendkim

Changing ownership of the private key file

chown opendkim:opendkim /etc/opendkim/default.private

Configuration in opendkim

vim /etc/default/opendkim

We add the line below to the configuration


Configuration in opendkim.conf

vim /etc/opendkim.conf

We fill the file with our configuration

Syslog yes
SyslogSuccess Yes
LogWhy yes

UMask 002

KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
Selector default
X-Header no
SignatureAlgorithm rsa-sha256

Canonicalization relaxed/simple
Mode sv
AutoRestart Yes
AutoRestartRate 5/1h
InternalHosts, localhost,,

OversignHeaders From

Setting the DKIM DNS record

cat /etc/opendkim/default.txt

This is our public key which will be used to verify the signature in our emails.

default._domainkey IN TXT "v=DKIM1; k=rsa;
p=MIGfHL0GCSqGSIb3DQESYJFOA4GNADCBiQKBgQDS+vPyWRs7w32xomf2oZIexmS2TuQAXKPiQ3AXn4j25NOReXdgKxIqAwl3O7dQtgluWw+TH85Mrbmx5UgwaaLenj9cfe2IRvx7hvkj7+6i0XQqrWqZlMw+QAJxAGhfa/GVTYa+/7PFWfXLoqoBW5arE+wO20O2uw5Ik62HjkKZbQIDAQAB" ; ----- DKIM key default for

Now we add a new TXT record:

As ‘name’ we put (there is a ‘dot’ at the end):

As ‘text’ we add (use your public key from /etc/opendkim/default.txt):

"v=DKIM1; k=rsa; p=MIGfHL0GCSqGSIb3DQESYJFOA4GNADCBiQKBgQDS+vPyWRs7w32xomf2oZIexmS2TuQAXKPiQ3AXn4j25NOReXdgKxIqAwl3O7dQtgluWw+TH85Mrbmx5UgwaaLenj9cfe2IRvx7hvkj7+6i0XQqrWqZlMw+QAJxAGhfa/GVTYa+/7PFWfXLoqoBW5arE+wO20O2uw5Ik62HjkKZbQIDAQAB"


It will take a while to propagate the new configuration throughout the entire internet.

Starting postfix and restarting opendkim

postfix start && service opendkim restart

Connecting with a Client

Now we will connect with our email client. In the tutorial we use Thunderbird as client.
Just add a new email account in Thunderbird and it will auto-detect the servers configuration.

The configuration should look like this:



Testing the mail server

It’s time to test our server. Let’s send and receive emails within Thunderbird.
We can observe the ongoing transactions and spot possible errors by monitoring our syslog.

tail -f /var/log/syslog

We can test our SPF and DKIM configuration here and DMARC here.

Some more testing can be done here, or here.

Postgrey in action


May 11 16:26:38 mail postgrey[21408]: action=pass, reason=triplet found,delay=1290,, client_address=,,

Reject at first try:

May 10 12:42:33 mail postgrey[21408]: action=greylist, reason=new,, client_address=,, 10
12:42:33 mail postfix/submission/smtpd[24718]: NOQUEUE: reject: RCPT
from[]: 450 4.2.0 <
: Recipient address rejected: Greylisted, see;
from=<> to=< > proto=ESMTP helo=

DKIM in action

Sending an email:

May 12 06:25:12 mail opendkim[1508]: 423AA62DC2: DKIM-Signature header
added (s=default,

SPF in action


May 10 14:28:47 mail postfix/policy-spf[1085]: Policy action=PREPEND
Received-SPF: pass ( is authorized to
use '' in 'mfrom' identity (mechanism
'a' matched)); identity=mailfrom;
envelope-from="";; client-ip=


May 12 16:15:25 mail postfix/policy-spf[20469]: Policy action=550 Please see;id=someone;ip=;
May 12 16:15:25 mail postfix/submission/smtpd[20463]: NOQUEUE: reject:
RCPT from[]: 550 5.7.1 <yourname@ >: Recipient address rejected: Please see;id=someone%;ip=;;
from=<> to=<> proto=ESMTP


You did it! You setup our own mail server and do not depend anymore on
any email provider.

Our anti-spam setup should filter out 99% of all unwanted messages and
won’t drop a legitimate email. On the other hand, messages from our
server should not be declared as spam as it has a valid SPF record and
we are signing our messages.

Still getting a few spam messages and not tired yet? Go on over here.

Useful for troubleshooting

Verify DNS

Check reverse entry

dig -x +short

Check MX record

dig MX +short

Verify if ports are listening

netstat -tulpen|grep LISTEN

Enable verbose logging for postfix in /etc/postfix/

Just add the v at the end of the smtp line.

smtp inet n - - - - smtpd -v

Check the syslog with

tail -f /var/log/syslog

and observe the logging.

19 thoughts on “How To Setup your own Mail Server with anti-spam configuration in 60 minutes”

  1. Hello,

    sorry, but I spent 4 hours on your guide and did not acheive anything… you promise too much and explain too little. When applying your for postfix, I will get “fatal error: missing ‘=’ ” or something like that;

    And you do not explain the command
    adduser –gecos “” –shell /bin/false yourname

    at all, what does it do? From where are users authenticated?

    1. I assume someone has basic bash knowledge when administrating a server and setting up an e-mail server. If you follow the tutorial under the same setup, without making any mistakes, you will get what I promised.

      Nevertheless you should understand what you are doing.
      Use the man pages of the commands used to understand the options and flags. For example man adduser would have told you what my command does.

      As of for the, copy the config again and make sure that it looks exactly the same. Your are missing whitespaces before the options in the ‘helo’ , ‘client’ and ‘data’ restrictions.

      Please email me and pastebin config files and log output if you need more help.

      From where are users authenticated?

      That’s answered at the beginning of the tutorial.

      We will use Unix user accounts and tunnel the SASL authentication through TLS

  2. Hello,
    thank You for nice setup.
    I found missing config (not complete) parameters in dovecot.conf for using mail server with squirrelmail client.
    I have to fullfill ‘ssl_cert’ and ‘ssl_key’ (end of dovecot.conf file), and now lines look like:

    ssl_cert = </etc/ssl/certs/mail.yourdomain.pem
    ssl_key = </etc/ssl/private/mail.yourdomain.key

    Mail server is ubuntu 14.04

    1. Hi Vladimir,

      I must have lost that some where because my running setup has what you mentioned in the dovecot config file.
      Thank you for seeing that. I just updated the information.

      Did you have any problems following this how to on 14.04 because I never tested under 14.04?


      1. Hi Michael,

        setup for ubuntu 14.04 passed well. I did not have any problem following Your ‘how-to’.
        It seems that 14.04 is same (or very simillar – concerning setup) as 12.04.
        Thanks again for usefull mail server setup.


  3. I would strongly suggest you change using vim to nano. Vim has quite a learning curve and will probably only serve to confuse the Linux great unwashed while they try to execute the other well presented instruction above.

    1. Hi John,

      You can use any text editor you like. It’s just a question of taste. I use “vim” because I like it best. I assume that someone who wants to setup a mail server has already a favourite text editor and will use his choice when working in bash.


  4. Hi Micheal,

    Super great walkthrough, but I’m running into a problem that I don’t know how to fix.

    when I do the last command before setting up the email client,

    postfix start && service opendkim restart

    I get the error:

    postfix start && service opendkim restart

    Do you know why this is?

    Thanks so much.

  5. Hi Harry,

    I’m glad that you figured it out. I’m sorry for the formatting mistake. I saw that the page was showing “&amp” and I have no idea where that came from. Please let me know should you have any more issues.


  6. The shell commands displayed above under ‘Preparing our system’ – ‘Setting up the host name’
    seem to have a typo (two ampersands):

    echo && /etc/hostname

    Did you mean (greater than character instead of the two ampersands)?:

    echo > /etc/hostname


Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>