W tym tutorialu opiszę konfigurację Postfixa z Dovecot w połączeniu z bazą MYSQL dla systemu Debian lub Ubuntu.
Ważne jest by iptables firewall nie blokował standardowych portów dla poczty (25, 465, 587, 110, 995, 143, and 993).
Oczywiście nie muszę tłumaczyć konfiguracji domeny w której należy dodać wpisy MX jak w przykładzie poniżej:

example.com         MX      10      example.com
example.com         MX      10      12.34.56.78
mail.example.com    MX      10      12.34.56.78

1. Certyfikaty

Dovecot oferuje certyfikaty self-signed czyli podpisane przez siebie, który jest certyfikatem darmowym. Jednak użytkownicy będą otrzymywać ostrzeżenia o certyfikacie w momencie  zakładania konta e-mail. Opcjonalnie można zakupić i skonfigurować komercyjny certyfikat SSL w celu uniknięcia ostrzeżeń.

2. Instalujemy paczki

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

3. MYSQL

Możemy użyć phpmyadmin lub kolejno użyć poleceń:

a) zakładamy nową bazę (zostaniemy poproszeni o podanie nazwy użytkownika i hasła):

mysqladmin -p create mailserver

b) łączymy się za bazą:

mysql -p mailserver

c) tworzymy użytkownika i nadajemy mu nazwę, hasło (mailuser i mailuserpass zastępujemy swoimi wartościami):

GRANT SELECT ON mailserver.* TO 'mailuser'@'127.0.0.1' IDENTIFIED BY 'mailuserpass';

d) potwierdzamy zmiany:

FLUSH PRIVILEGES;

e) tworzymy tabelę dla domen:

CREATE TABLE `virtual_domains` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

f) tworzymy tabelę dla użytkowników:

CREATE TABLE `virtual_users` (
  `id` int(11) NOT NULL auto_increment,
  `domain_id` int(11) NOT NULL,
  `password` varchar(106) NOT NULL,
  `email` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`),
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

g) i jeszcze tabela dla aliasów:

CREATE TABLE `virtual_aliases` (
  `id` int(11) NOT NULL auto_increment,
  `domain_id` int(11) NOT NULL,
  `source` varchar(100) NOT NULL,
  `destination` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

h) dodajemy domeny do tabeli, przy czym ważne jest ID domen – będzie to nam potrzebne przy tworzeniu maili i aliasów:

INSERT INTO `mailserver`.`virtual_domains`
  (`id` ,`name`)
VALUES
  ('1', 'example.com'),
  ('2', 'hostname.example.com'),
  ('3', 'hostname'),
  ('4', 'localhost.example.com');

i) dodajemy użytkowników – adresy mailowe, przypisując właśnie odpowiednie ID przypisane dla domeny, password zastępujemy oczywiście własnym hasłem:

INSERT INTO `mailserver`.`virtual_users`
  (`id`, `domain_id`, `password` , `email`)
VALUES
  ('1', '1', ENCRYPT('password', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'email1@example.com'),
  ('2', '1', ENCRYPT('password', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'email2@example.com');

j) opcjonalnie dodajemy aliasy również pamiętając by zmienić na odpowiednie domain_id:

INSERT INTO `mailserver`.`virtual_aliases`
  (`id`, `domain_id`, `source`, `destination`)
VALUES
  ('1', '1', 'alias@example.com', 'email1@example.com');

Właściwie to wszystko jeśli chodzi o MYSQL, wylogowujemy się z bazy:

exit

4. Postfix

a) zanim wyedytujemy plik konfiguracyjny postfixa zróbmy mu kopię:

cp /etc/postfix/main.cf /etc/postfix/main.cf.orig

b) edytujemy plik /etc/postfix/main.cf dodając na końcu pliku następujące linijki:

#Transport wiadomosci poprzez lmtp
virtual_transport = lmtp:unix:private/dovecot-lmtp

#Wiztualne domeny i aliasy
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf,
        mysql:/etc/postfix/mysql-virtual-email2email.cf

c) teraz musimy stworzyć 4 pliki obsługujące połączenie z bazą (musimy podać nazwę użytkownika i hasło do połączenia się z bazą):

Plik: /etc/postfix/mysql-virtual-mailbox-domains.cf

user = mailuser
password = mailuserpass
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'

Plik: /etc/postfix/mysql-virtual-mailbox-maps.cf

user = mailuser
password = mailuserpass
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email='%s'

Plik: /etc/postfix/mysql-virtual-alias-maps.cf

user = mailuser
password = mailuserpass
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'

Plik: /etc/postfix/mysql-virtual-email2email.cf

user = mailuser
password = mailuserpass
hosts = 127.0.0.1
dbname = mailserver
query = SELECT email FROM virtual_users WHERE email='%s'

d) zapisujemy pliki i restartujemy postfixa:

service postfix restart

e) zabieramy się za plik master.cf. Robimy mu kopię:

cp /etc/postfix/master.cf /etc/postfix/master.cf.orig

f) edytujemy plik /etc/postfix/master.cf zwracając uwagę na smtps i submission:

#
# Postfix master process configuration file.  For details on the format
# of the file, see the master(5) manual page (command: "man 5 master").
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
smtp      inet  n       -       -       -       -       smtpd
#smtp      inet  n       -       -       -       1       postscreen
#smtpd     pass  -       -       -       -       -       smtpd
#dnsblog   unix  -       -       -       -       0       dnsblog
#tlsproxy  unix  -       -       -       -       0       tlsproxy
submission inet n       -       -       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       -       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

g) ustawiamy właściwe uprawnienia:

chmod -R o-rwx /etc/postfix

h) restartujemy postfixa:

service postfix restart

5. Dovecot

Dovecot pozawala użytkownikom na logowanie się i pobieranie wiadomości poprzez POP i IMAP. Nasza konfiguracja będzie opierać się na zabezpieczeniu połączenia poprzez SSL + logowanie.

a) robimy kopie plików, które będziemy edytować:

cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig
cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf.orig
cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf.orig
cp /etc/dovecot/dovecot-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext.orig
cp /etc/dovecot/conf.d/10-master.conf /etc/dovecot/conf.d/10-master.conf.orig
cp /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl.conf.orig

b) edytujemy plik /etc/dovecot/dovecot.conf:

## Dovecot configuration file

# If you're in a hurry, see http://wiki2.dovecot.org/QuickConfiguration

# "doveconf -n" command gives a clean output of the changed settings. Use it
# instead of copy&pasting files when posting to the Dovecot mailing list.

# '#' character and everything after it is treated as comments. Extra spaces
# and tabs are ignored. If you want to use either of these explicitly, put the
# value inside quotes, eg.: key = "# char and trailing whitespace  "

# Default values are shown for each setting, it's not required to uncomment
# those. These are exceptions to this though: No sections (e.g. namespace {})
# or plugin settings are added by default, they're listed only as examples.
# Paths are also just examples with the real defaults being based on configure
# options. The paths listed here are for configure --prefix=/usr
# --sysconfdir=/etc --localstatedir=/var

# Enable installed protocols
!include_try /usr/share/dovecot/protocols.d/*.protocol
protocols = imap pop3 lmtp

# A comma separated list of IPs or hosts where to listen in for connections. 
# "*" listens in all IPv4 interfaces, "::" listens in all IPv6 interfaces.
# If you want to specify non-default ports or anything more complex,
# edit conf.d/master.conf.
#listen = *, ::

# Base directory where to store runtime data.
#base_dir = /var/run/dovecot/

# Name of this instance. Used to prefix all Dovecot processes in ps output.
#instance_name = dovecot

# Greeting message for clients.
#login_greeting = Dovecot ready.

# Space separated list of trusted network ranges. Connections from these
# IPs are allowed to override their IP addresses and ports (for logging and
# for authentication checks). disable_plaintext_auth is also ignored for
# these networks. Typically you'd specify the IMAP proxy servers here.
#login_trusted_networks =

# Sepace separated list of login access check sockets (e.g. tcpwrap)
#login_access_sockets = 

# Show more verbose process titles (in ps). Currently shows user name and
# IP address. Useful for seeing who are actually using the IMAP processes
# (eg. shared mailboxes or if same uid is used for multiple accounts).
#verbose_proctitle = no

# Should all processes be killed when Dovecot master process shuts down.
# Setting this to "no" means that Dovecot can be upgraded without
# forcing existing client connections to close (although that could also be
# a problem if the upgrade is e.g. because of a security fix).
#shutdown_clients = yes

# If non-zero, run mail commands via this many connections to doveadm server,
# instead of running them directly in the same process.
#doveadm_worker_count = 0
# UNIX socket or host:port used for connecting to doveadm server
#doveadm_socket_path = doveadm-server

# Space separated list of environment variables that are preserved on Dovecot
# startup and passed down to all of its child processes. You can also give
# key=value pairs to always set specific settings.
#import_environment = TZ

##
## Dictionary server settings
##

# Dictionary can be used to store key=value lists. This is used by several
# plugins. The dictionary can be accessed either directly or though a
# dictionary server. The following dict block maps dictionary names to URIs
# when the server is used. These can then be referenced using URIs in format
# "proxy::<name>".

dict {
  #quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
  #expire = sqlite:/etc/dovecot/dovecot-dict-sql.conf.ext
}

# Most of the actual configuration gets included below. The filenames are
# first sorted by their ASCII value and parsed in that order. The 00-prefixes
# in filenames are intended to make it easier to understand the ordering.
!include conf.d/*.conf

# A config file can also tried to be included without giving an error if
# it's not found:
!include_try local.conf

c) zapisujemy plik /etc/dovecot/dovecot.conf

d) otwieramy plik /etc/dovecot/conf.d/10-mail.conf i modyfikujemy poniższe zmienne:

mail_location = maildir:/var/mail/vhosts/%d/%n
...
mail_privileged_group = mail

e) zapisujemy plik

f) ustawiamy odpowiednie prawa dla /var/mail

ls -ld /var/mail

g) tworzymy katalog, w którym będziemy przetrzymywać zawartość kont pocztowych (w moim przypadku wybrałem lokalizację w /home/maile/, gdyż miał on najwięcej wolnej przestrzeni + automatyczna kopia zapasowa tego katalogu)

h) zakładamy katalog dla domeny:

mkdir -p /home/maile/example.com

i) zakładamy użytkownika  vmail w grupie id 5000 obsługującego naszą pocztę

groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /var/mail

j) zmieniamy właściciela dla katalogu:

chown -R vmail:vmail /home/maile

k) edytujemy plik /etc/dovecot/conf.d/10-auth.conf i wyłączamy możliwość łączenia się za pomocą logowaniu przy użyciu hasła opartego na zwykłym tekście

disable_plaintext_auth = yes

l) edytujemy plik /etc/dovecot/conf.d/10-auth.conf wybieramy odpowiedni mechanizm

auth_mechanisms = plain login

m) w tym samym pliku usuwamy komentarz w linijce:

#!include auth-system.conf.ext

n) odkomentujemy linijkę odpowiadającą za połączenie z mysql:

#!include auth-system.conf.ext
!include auth-sql.conf.ext
#!include auth-ldap.conf.ext
#!include auth-passwdfile.conf.ext
#!include auth-checkpassword.conf.ext
#!include auth-vpopmail.conf.ext
#!include auth-static.conf.ext

o) zapisujemy plik /etc/dovecot/conf.d/10-auth.conf

p) edytujemy plik /etc/dovecot/conf.d/auth-sql.conf.ext

passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
  driver = static
  args = uid=vmail gid=vmail home=/home/maile/%d/%n
   }

r) zapisujemy plik /etc/dovecot/conf.d/auth-sql.conf.ext

s) edytujemy plik /etc/dovecot/dovecot-sql.conf.ext i odkomentujemy linie:

driver = mysql
connect = host=127.0.0.1 dbname=mailserver user=mailuser password=mailuserpass
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';

t) zapisujemy plik /etc/dovecot/dovecot-sql.conf.ext

u) zmieniamy prawa:

chown -R vmail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot

w) edytujemy plik /etc/dovecot/conf.d/10-master.conf. Wyłączamy niezaszyfrowane IMAP i POP3 poprzez ustawienie portów protokołów na 0. Wpisy do portu i SSL poniżej wpisów IMAPS i POP3 mają być zakomentowane:

  service imap-login {
inet_listener imap {
  port = 0
}
  inet_listener imaps {
port = 993
ssl = yes
}
  	...
  service pop3-login {
  	  inet_listener pop3 {
      port = 0
  		  }
inet_listener pop3s {
  port = 995
  ssl = yes
}
  ...
  }

znajdujemy sekcję service lmtp w tym samym pliku i edytujemy według:

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 =
    #}
  }

lokalizujemy jeszcze sekcję service auth i edytujemy również:

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/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/auth {
  #  mode = 0666
  #}

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

i jeszcze sekcja service auth-worker

service auth-worker {
  # Auth worker process is run as root by default, so that it can access
  # /etc/shadow. If this isn't necessary, the user should be changed to
  # $default_internal_user.
  user = vmail
}

zapisujemy plik

x) zostały nam certyfikaty. sprawdzamy czy istnieją:

ls /etc/dovecot/dovecot.pem
ls /etc/dovecot/private/dovecot.pem

otwieramy plik /etc/dovecot/conf.d/10-ssl.conf

i odkomentowujemy lub dodajemy:

ssl_cert = </etc/dovecot/dovecot.pem
ssl_key = </etc/dovecot/private/dovecot.pem

odkomentowujemy:

ssl = required

zapisujemy plik i restartujemy dovecota:

service dovecot restart

I to wszystko.