Mail Server Setup

This is how I set up my mail server on

  • Ubuntu 12.04 Precise Pangolin
  • Dovecot 2.0.19
  • Postfix 2.9.6
  • Postfix Admin 2.3.6
  • Squirrel Mail 1.4.22
  • MySQL 5.5.34
  • PHP 5.3.10

Supporting Packages to Install

  • postfix-mysql
  • dovecot-core
  • dovecot-postfix
  • dovecot-mysql
  • dovecot-imapd
  • php5-mysql

Server configuration

vmail user configuration

uid=5000(vmail) gid=5000(vmail) groups=5000(vmail)

Postfix configuration

/etc/postfix/main.cf

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 = no
 
# TLS parameters
smtpd_tls_cert_file = /etc/ssl/certs/ssl-mail.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-mail.key
smtpd_tls_loglevel = 1
smtpd_tls_security_level = may
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
tls_random_source = dev:/dev/urandom
tls_random_bytes = 32
tls_random_reseed_period = 3600s
#
home_mailbox = Maildir/
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/dovecot-auth
smtpd_sasl_authenticated_header = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname
broken_sasl_auth_clients = yes
smtpd_use_tls = yes
smtpd_tls_received_header = yes
smtpd_tls_mandatory_protocols = SSLv3, TLSv1
smtpd_tls_mandatory_ciphers = medium
#smtpd_tls_auth_only = yes
#
smtp_tls_cert_file=/etc/postfix/ssl/smtpd.pem
smtp_tls_key_file=$smtp_tls_cert_file
smtp_tls_loglevel = 1
smtp_tls_security_level = may
smtp_tls_note_starttls_offer = yes
smtp_use_tls = yes
#
 
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
 
myhostname = example.org
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
#mydestination = example.org, www.example.org, example.cc, www.example.cc, myserverhostname, localhost.localdomain, localhost
mydestination =
relayhost = smtp-server.example.com
# This was commented out as it gives a "unused parameter" warning on Precise - works on Hardy
#relay_domain = $mydestination
mynetworks_style = subnet
#mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_command = /usr/lib/dovecot/deliver -c /etc/dovecot/conf.d/01-mail-stack-delivery.conf -m "${EXTENSION}"
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
owner_request_special = no
message_size_limit = 32768000
#
# Virtual Mailbox Domain Settings
virtual_alias_maps = mysql:/etc/postfix/mysql/alias_maps.cf, mysql:/etc/postfix/mysql/alias_alias_maps.cf
virtual_mailbox_domains = mysql:/etc/postfix/mysql/domains_maps.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql/mailbox_maps.cf, mysql:/etc/postfix/mysql/mailbox_alias_maps.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 = virtual
# Additional for quota support
# This was commented out as it gives a "unused parameter" warning on Precise - works on Hardy
#virtual_create_maildirsize = yes
#virtual_mailbox_extended = yes
#virtual_mailbox_limit_maps = mysql:/etc/postfix/mysql/mailbox_limit_maps.cf
#virtual_mailbox_limit_override = yes
#virtual_maildir_limit_message = Sorry, the your maildir has overdrawn your diskspace quota, please free up some of spaces of your mailbox try again.
#virtual_overquota_bounce = yes
#
# Spam reduction parameters. May be aggresive for some, but seems to work well.
access_map_reject_code = 554
invalid_hostname_reject_code = 554
maps_rbl_reject_code = 554
multi_recipient_bounce_reject_code = 554
non_fqdn_reject_code = 554
plaintext_reject_code = 554
reject_code = 554
relay_domains_reject_code = 554
unknown_local_recipient_reject_code = 550
unknown_address_reject_code = 550
unknown_client_reject_code = 550
unknown_hostname_reject_code = 550
unknown_relay_recipient_reject_code = 550
unknown_virtual_alias_reject_code = 550
unknown_virtual_mailbox_reject_code = 550
unverified_recipient_reject_code = 550
unverified_sender_reject_code = 550
#
default_process_limit = 20
smtpd_client_connection_count_limit = 10
# Value of 60 should translate to 1 per second limit
smtpd_client_connection_rate_limit = 60
smtpd_client_message_rate_limit = 60
smtpd_client_new_tls_session_rate_limit = 60
#
smtpd_helo_required = yes
smtpd_delay_reject = yes
address_verify_map = btree:${data_directory}/verify_cache
smtpd_reject_unlisted_sender=yes
#
smtpd_recipient_restrictions =
    check_client_access hash:/etc/postfix/white_lists,
    permit_sasl_authenticated,
    permit_mynetworks,
#   permit_tls_clientcerts,
    reject_invalid_hostname,
    reject_non_fqdn_hostname,
    reject_non_fqdn_sender,
    reject_non_fqdn_recipient,
    reject_unknown_sender_domain,
    reject_unknown_recipient_domain,
    reject_unverified_sender,
    reject_unauth_destination,
    reject_rbl_client zen.spamhaus.org,
    reject_rbl_client cbl.abuseat.org,
    check_client_access hash:/etc/postfix/white_lists,
    permit
smtpd_data_restrictions =
    permit_sasl_authenticated,
    permit_mynetworks,
    reject_unauth_pipelining,
    permit
# Added for trying to send email from PDA
smtpd_client_restrictions =
    permit_sasl_authenticated
smtpd_helo_restrictions =
    check_helo_access hash:/etc/postfix/check_helo_access,
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_non_fqdn_hostname,
    reject_invalid_hostname,
    permit
#

/etc/postfix/mailname

mailname
example.org

Client TLS Support

Follow this for Postfix Client TLS Support setup

Postfix MySql (maps) configuration

  • Create directory /etc/postfix/mysql
  • Please the following files under /etc/postfix/mysql
mysql_uid.cf
user=<mysql_db_user>
password=<mysql_db_password>
dbname=<mysql_db_name>
table=mailbox
select_field=username
where_field=username
hosts=127.0.0.1:<mysql_db_port>
mysql_gid.cf
user=<mysql_db_user>
password=<mysql_db_password>
dbname=<mysql_db_name>
table=mailbox
select_field=username
where_field=username
hosts=127.0.0.1:<mysql_db_port>
mailbox_maps.cf
user=<mysql_db_user>
password=<mysql_db_password>
dbname=<mysql_db_name>
table=mailbox
select_field=maildir
where_field=username
hosts=127.0.0.1:<mysql_db_port>
additional_conditions = and active = 1
mailbox_limit_maps.cf
user=<mysql_db_user>
password=<mysql_db_password>
dbname=<mysql_db_name>
table=mailbox
select_field=quota
where_field=username
hosts=127.0.0.1:<mysql_db_port>
additional_conditions = and active = 1
alias_maps.cf
user=<mysql_db_user>
password=<mysql_db_password>
dbname=<mysql_db_name>
table=alias
select_field=goto
where_field=address
hosts=127.0.0.1:<mysql_db_port>
additional_conditions = and active = 1
domains_maps.cf
user=<mysql_db_user>
password=<mysql_db_password>
dbname=<mysql_db_name>
table=domain
select_field=domain
where_field=domain
hosts=127.0.0.1:<mysql_db_port>
additional_conditions = and backupmx = 0 and active = 1
relay_domains.cf
user=<mysql_db_user>
password=<mysql_db_password>
dbname=<mysql_db_name>
table=domain
select_field=domain
where_field=domain
hosts=127.0.0.1:<mysql_db_port>
additional_conditions = and active = 1 and backupmx = 1

The below two settings (alias_alias_maps.cf & mailbox_alias_maps.cf) are for alias domains:

alias_alias_maps.cf
user=<mysql_db_user>
password=<mysql_db_password>
dbname=<mysql_db_name>
hosts=127.0.0.1:<mysql_db_port>
query = SELECT goto FROM alias,alias_domain
  WHERE alias_domain.alias_domain = '%d'
  AND alias.address=concat('%u', '@', alias_domain.target_domain)
  AND alias.active = 1 AND alias_domain.active = 1
mailbox_alias_maps.cf
user=<mysql_db_user>
password=<mysql_db_password>
dbname=<mysql_db_name>
hosts=127.0.0.1:<mysql_db_port>
query = SELECT maildir FROM mailbox, alias_domain
  WHERE alias_domain.alias_domain = '%d'
  AND mailbox.username=concat('%u', '@', alias_domain.target_domain )
  AND mailbox.active = 1 AND alias_domain.active = 1

Dovecot Configuration

Change the following files at /etc/dovecot & /etc/dovecot/conf.d

The files in /etc/dovecot need NO changes from default

  • dovecot.conf
  • dovecot-db.conf.ext
  • dovecot-dict-sql.conf.ext
  • dovecot-sql.conf.ext

File(s) requiring change

dovecot-sql.conf.ext
driver = mysql
connect = host=127.0.0.1 port=3306 user=root password=rootpassword dbname=postfixadmindbname
default_pass_scheme = CRAM-MD5
user_query = \
 SELECT \
        concat('/home/vmail/', maildir) as home, \
        5000 as uid, 5000 as gid \
        FROM mailbox \
        WHERE username = '%u' AND active = '1'
password_query = \
 SELECT username as user, password, \
        concat('/home/vmail/', maildir) as userdb_home, \
        concat('maildir:/home/vmail/', maildir) as userdb_mail, \
        5000 as userdb_uid, 5000 as userdb_gid \
        FROM mailbox \
        WHERE username = '%u' AND active = '1'

The following files in /etc/dovecot/conf.d do NOT require change as well

  • 01-mail-stack-delivery.conf
  • 10-director.conf
  • 10-master.conf
  • 10-ssl.conf
  • 15-lda.conf
  • 20-imap.conf
  • 20-managesieve.conf
  • 20-pop3.conf
  • 90-acl.conf
  • 90-plugin.conf
  • 90-quota.conf
  • 90-sieve.conf
  • auth-deny.conf.ext
  • auth-master.conf.ext
  • auth-passwdfile.conf.ext
  • auth-static.conf.ext
  • auth-vpopmail.conf.ext

File(s) requiring change

10-logging.conf
auth_verbose = yes
auth_debug = yes
plugin {
  # Events to log. Also available: flag_change append
  #mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename
  # Available fields: uid, box, msgid, from, subject, size, vsize, flags
  # size and vsize are available only for expunge and copy events.
  #mail_log_fields = uid box msgid size
}
10-auth.conf
auth_mechanisms = plain cram-md5
!include auth-system.conf.ext
auth-system.conf.ext
passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
  # [session=yes] [setcred=yes] [failure_show_msg=yes] [max_requests=<n>]
  # [cache_key=<key>] [<service name>]
  #args = dovecot
}
userdb {
  # <doc/wiki/AuthDatabase.Passwd.txt>
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
  # [blocking=no]
  #args =
}
10-mail.conf
mail_location = maildir:/home/vmail/%d/%u
mail_uid = vmail
mail_gid = vmail
maildir_copy_with_hardlinks = yes

Postfix Admin

All changes from the default go in config.local.php

config.local.php
$CONF['postfix_admin_url'] = 'http://pfa.example.org';
 
$CONF['domain_path'] = 'YES';
 
$CONF['database_type'] = 'mysql';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'upostfixadmin';
$CONF['database_password'] = 'somepassword';
$CONF['database_name'] = 'postfixadmin';
 
$CONF['admin_email'] = 'postmaster@example.com';
 
$CONF['smtp_server'] = 'smtp-server.example.com';
 
$CONF['encrypt'] = 'dovecot:CRAM-MD5';
 
$CONF['dovecotpw'] = "/usr/bin/doveadm pw";
 
$CONF['page_size'] = '100';
 
$CONF['default_aliases'] = array (
    'abuse' => 'abuse@example.com',
    'hostmaster' => 'hostmaster@example.com',
    'postmaster' => 'postmaster@example.com',
    'webmaster' => 'webmaster@example.com'
);
 
$CONF['aliases'] = '10000';
$CONF['mailboxes'] = '10000';
$CONF['maxquota'] = '10000';
 
$CONF['transport'] = 'YES';
 
$CONF['vacation_domain'] = 'autoreply.example.com';
 
$CONF['user_footer_link'] = "http://example.com/";
$CONF['footer_text'] = 'Return to example.com'; 
$CONF['footer_link'] = 'http://example.com';
 
$CONF['create_mailbox_subdirs_prefix']='';
$CONF['new_quota_table'] = 'YES';

Migration from Courier to Postfix

If you are moving to a new machine make sure that you tar and untar files to preserver permissions and most importantly timestamps. Or all your old mail will have the same date/time!

Resource

Command

/home/vmail/courier-dovecot-migrate.pl --to-dovecot --recursive --convert --overwrite /home/vmail/example.org/

Sample output:

Converting to Dovecot format
Finding maildirs under /home/vmail/example.org/

Total: 70 mailboxes / 38 users
       0 errors
46 dovecot-uidlist files written

WARNING: Badly done migration will cause your IMAP and/or POP3 clients to re-download all mails. Read http://wiki.dovecot.org/Migration carefully.

Folder between courier and dovecot

One way to get the courier subfolders to show up in dovecot is to add this to the configuration:

10-mail.conf
namespace private {
  prefix = INBOX.
  separator = .
  inbox = yes
}

Alternatively, I created the subfolders (from squirrel mail) and then delete the newly created folders from the Linux file folders and renamed the existing file folders to the name I just deleted. So here goes for example:

mv .INBOX.SomeSubFolder/ junk
mv .SomeSubFolder .INBOX.SomeSubFolder

Here I moved the newly created folder to a “junk” location (an alternative to just deleting it). Then renamed the original folder to the new folder name.

Squirrel Mail configuration

Follow this link.

Some dovecot commands

dovecot --build-options
find /usr/lib/dovecot/modules/
doveconf -a

Post Configuration Steps

white_lists file

To avoid error that there is no white list file.

The check_helo_access allows helo specific white lists. For e.g. use when you an error such as Helo command rejected: Host not found;.

cd /etc/postfix
touch white_lists
postmap white_lists
#
touch check_helo_access
postmap check_helo_access

Restart

service postfix restart
service dovecot restart

QR Code
QR Code tech:linux:mail_server_setup (generated for current page)