Postfix 04 - Postfix + Dovecot + SquirrelMail + MailScanner + ClamAV
Postfix Mail Server Learning · Previous: Debian 4 - A mail server for an ISP · Next: Postfix + Cyrus + MySQL
The Slovak original of this document: Postfix 04 - Postfix + Dovecot + SquirrelMail + MailScanner + ClamAV (slovensky).
##################################################################################
## ##
## user17 postfix && dovecot && squirrelmail && mailscanner && clamav ##
## ##
##################################################################################
notes:
- create a new user and group vmail for the settings in postfix and dovecot
#groupadd -g 5000 vmail
#useradd -m -u 5000 -g 5000 -s /bin/bash vmail
- and then change in postfix
#virtual_minimum_uid = 1000
#virtual_uid_maps = static:5000
#virtual_gid_maps = static:5000
##################################################################################
#apt-get install postfix
************************************************************************
#nano /etc/postfix/main.cf
##########################################
## mail server user17 2009 ##
##########################################
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no
append_dot_mydomain = no
#delay_warning_time = 4h
readme_directory = no
# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.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
#mydomain = partner.example
myhostname = mordor.partner.example
#alias_maps = hash:/etc/aliases
#alias_database = hash:/etc/aliases
myorigin = $mydomain
mydestination = localhost
#virtual_alias_domains = partner.example, client24.example, client50.example
#virtual_alias_maps = hash:/etc/postfix/virtual_alias
relayhost =
mynetworks =
127.0.0.0/8
192.168.1.0/24
mailbox_command = procmail -a "$EXTENSION"
home_mailbox = Maildir/
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
## Header check (MailScanner)
#header_checks = regexp:/etc/postfix/header_checks
# This system will be the final destination for the list of domains given in the file virtual_domains
# ---------------------------------------------------------------------------------------------------
virtual_mailbox_domains = /etc/postfix/virtual_domains
# Mapping email->mailbox_file
# ---------------------------
virtual_mailbox_maps = hash:/etc/postfix/virtual
# Location of the virtual mailboxes
# ---------------------------------
virtual_mailbox_base = /var/mail
# Virtual aliases
# ---------------
virtual_alias_maps = hash:/etc/postfix/virtual_alias
# Owner of the mailbox files (uid and gid)
# ----------------------------------------
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
inet_protocols = ipv4
************************************************************************
#touch /etc/postfix/virtual
#nano /etc/postfix/virtual
## -----------------------------
## partner.example
## -----------------------------
info@partner.example partner.example/info/
user17@partner.example partner.example/user17/
user16@partner.example partner.example/user16/
## client25.example
## -----------------------------
info@client25.example client25.example/info/
#postmap /etc/postfix/virtual
************************************************************************
#touch /etc/postfix/virtual_alias
#nano /etc/postfix/virtual_alias
info@partner.example info@partner.example
user17@partner.example user17@partner.example
user16@partner.example user16@partner.example
info@client25.example info@client25.example
#postmap /etc/postfix/virtual_alias
************************************************************************
#touch /etc/postfix/virtual_domains
#nano /etc/postfix/virtual_domains
partner.example
client25.example
************************************************************************
# apt-get install dovecot dovecot-imapd
************************************************************************
#nano /etc/dovecot/dovecot.conf
##################################
## dovecot user17 2009 ##
##################################
base_dir = /var/run/dovecot/
protocols = imap imaps pop3
#mail_extra_groups = mail
first_valid_uid = 5000
last_valid_uid = 5000
protocol imap {
login_executable = /usr/lib/dovecot/imap-login
mail_executable = /usr/lib/dovecot/imap
}
protocol pop3 {
login_executable = /usr/lib/dovecot/pop3-login
mail_executable = /usr/lib/dovecot/pop3
pop3_uidl_format = %08Xu%08Xv
}
disable_plaintext_auth = no
shutdown_clients = yes
## Logging
log_path = /var/log/dovecot.log
info_log_path = /var/log/dovecot.info.log
log_timestamp = "%Y-%m-%d %H:%M:%S "
## SSL settings
#ssl_listen =
#ssl_disable = yes
ssl_cert_file = /etc/ssl/certs/dovecot.pem
ssl_key_file = /etc/ssl/private/dovecot.pem
## Login processes
login_dir = /var/run/dovecot/login
login_chroot = yes
login_user = dovecot
login_greeting = Dovecot ready.
## Mailbox locations and namespaces
# %u - username
# %n - user part in user@domain, same as %u if there's no domain
# %d - domain part in user@domain, empty if there's no domain
# %h - home directory
mail_location = maildir:/var/mail/%d/%n
mail_privileged_group = mail
## Mail processes
#mail_log_prefix = "%Us(%u): "
mmap_disable = no
valid_chroot_dirs = /var/spool/mail
#default_mail_env = maildir:/var/mail/%d/%n
#mail_chroot =
## Maildir-specific settings
#maildir_stat_dirs = no
#maildir_copy_with_hardlinks = no
#maildir_copy_preserve_filename = no
## IMAP specific settings
protocol imap {
#login_executable = /usr/lib/dovecot/imap-login
# mail_executable = /usr/lib/dovecot/rawlog /usr/lib/dovecot/imap
#
# /tmp/gdbhelper.* files:
# mail_executable = /usr/libexec/dovecot/gdbhelper /usr/libexec/dovecot/imap
#
#mail_executable = /usr/lib/dovecot/imap
#imap_max_line_length = 65536
# Support for dynamically loadable plugins. mail_plugins is a space separated
# list of plugins to load.
#mail_plugins =
#mail_plugin_dir = /usr/lib/dovecot/modules/imap
#login_greeting_capability = no
#imap_capability =
#imap_client_workarounds = outlook-idle
}
## POP3 specific settings
protocol pop3 {
#login_executable = /usr/lib/dovecot/pop3-login
#mail_executable = /usr/lib/dovecot/pop3
#pop3_no_flag_updates = no
#pop3_enable_last = no
#pop3_reuse_xuidl = no
#pop3_lock_session = no
# %v - Mailbox's IMAP UIDVALIDITY
# %u - Mail's IMAP UID
# %m - MD5 sum of the mailbox headers in hex (mbox only)
# %f - filename (maildir only)
#
# If you want UIDL compatibility with other POP3 servers, use:
# UW's ipop3d : %08Xv%08Xu
# Courier version 0 : %f
# Courier version 1 : %u
# Courier version 2 : %v-%u
# Cyrus (<= 2.1.3) : %u
# Cyrus (>= 2.1.4) : %v.%u
# Older Dovecots : %v.%u
# tpop3d : %Mf
pop3_uidl_format = %08Xu%08Xv
# POP3 logout format string:
# %t - number of TOP commands
# %p - number of bytes sent to client as a result of TOP command
# %r - number of RETR commands
# %b - number of bytes sent to client as a result of RETR command
# %d - number of deleted messages
# %m - number of messages (before deletion)
# %s - mailbox size in bytes (before deletion)
#pop3_logout_format = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
#mail_plugins =
#mail_plugin_dir = /usr/lib/dovecot/modules/pop3
# Workarounds for various client bugs:
# outlook-no-nuls:
# Outlook and Outlook Express hang if mails contain NUL characters.
# This setting replaces them with 0x80 character.
# oe-ns-eoh:
# Outlook Express and Netscape Mail breaks if end of headers-line is
# missing. This option simply sends it if it's missing.
# The list is space-separated.
#pop3_client_workarounds =
}
## MANAGESIEVE specific settings
protocol managesieve {
#login_executable = /usr/libexec/dovecot/managesieve-login
#mail_executable = /usr/libexec/dovecot/managesieve
#managesieve_max_line_length = 65536
sieve=~/.dovecot.sieve
sieve_storage=~/sieve
# mail_location = mbox:~/mail
#managesieve_implementation_string = Cyrus timsieved v2.2.13
}
##
## LDA specific settings
##
protocol lda {
postmaster_address = info@partner.example
#hostname =
#mail_plugins =
#mail_plugin_dir = /usr/lib/dovecot/modules/lda
#sendmail_path = /usr/lib/sendmail
#auth_socket_path = /var/run/dovecot/auth-master
# mail_plugins = cmusieve
}
## Authentication processes
auth_executable = /usr/lib/dovecot/dovecot-auth
auth_verbose = yes
#auth_debug = no
#auth_debug_passwords = no
#auth_worker_max_count = 30
#auth_gssapi_hostname =
#auth_krb5_keytab =
auth default {
mechanisms = plain digest-md5
userdb passwd-file {
args = /etc/dovecot/users
}
passdb passwd-file {
args = /etc/dovecot/passwd
}
user = root
}
#auth external {
# socket connect {
# master {
# path = /var/run/dovecot/auth-master
# }
# }
#}
## Dictionary server settings
dict {
#quota = mysql:/etc/dovecot-dict-quota.conf
}
## Plugin settings
plugin {
#quota = maildir
#acl = vfile:/etc/dovecot-acls
#convert_mail = mbox:%h/mail
#convert_skip_broken_mailboxes = no
#trash = /etc/dovecot-trash.conf
#lazy_expunge = .EXPUNGED/ .DELETED/ .DELETED/.EXPUNGED/
}
************************************************************************
#touch /etc/dovecot/adddovecotusers
#!/bin/bash
username=${1%%@*}
domain=${1#*@}
# create the user name in the user file
echo "$username@$domain::5000:5000::/var/mail/$domain/$username/:/bin/false::" >> /etc/dovecot/users
# create the maildir directory structure
/usr/bin/maildirmake.dovecot /var/mail/$domain/$username 5000:5000
# add the user to the Postfix virtual map file
echo $1 $domain/$username >> /etc/postfix/virtual
postmap /etc/postfix/virtual
postfix reload
************************************************************************
##for mkdovecotpasswd to work, mkpasswd has to be available (if it is not, it has to be installed)
#touch /etc/dovecot/mkdovecotpasswd
#!/bin/bash
echo "$1:`mkpasswd --hash=md5 $2`" >> /etc/dovecot/passwd
************************************************************************
# chmod a+x /etc/dovecot/adddovecotusers
# chmod a+x /etc/dovecot/mkdovecotpasswd
************************************************************************
## add user
# /etc/dovecot/adddovecotusers info@partner.example
#add passwd
root@server:~# /etc/dovecot/mkdovecotpasswd info@partner.example heslo
# postfix reload
# /etc/init.d/dovecot restart
************************************************************************
## setting up logging /etc/logrotate.d/dovecot
#touch /etc/logrotate.d/dovecot
#nano /etc/logrotate.d/dovecot
/var/log/dovecot*log {
weekly
missingok
rotate 52
compress
delaycompress
notifempty
# Note the odd permissions: this is needed because deliver doesn't know what user it runs under
create 666 root adm
sharedscripts
}
/var/log/dovecot*info {
weekly
missingok
rotate 52
compress
delaycompress
notifempty
# Note the odd permissions: this is needed because deliver doesn't know what user it runs under
create 666 root adm
sharedscripts
}
************************************************************************Current practice (checked 2026-10)
noteThe article above is kept as it was written in 2009. This section lists what has changed since and what to do instead today.
- Dovecot 1.x configuration:
login_dir,login_executable,mail_executable,auth default { ... },ssl_cert_fileand theimapsprotocol name belong to Dovecot 1.x and are not accepted by Dovecot 2.x. Dovecot 2.4 changed the syntax again: the file must start withdovecot_config_version, the certificate settings aressl_server_cert_fileandssl_server_key_file,mail_locationis split into severalmail_*settings,passdb/userdbsections need a name, and%d/%nare written%{user | domain}and%{user | username}. Start from the configuration shipped with your version instead of this file. disable_plaintext_auth = no: this allows logins with the password in clear over an unencrypted connection. The setting is calledauth_allow_cleartextin Dovecot 2.4; leave it off and let clients use TLS.- Password hashes:
mkpasswd --hash=md5produces MD5-CRYPT, which the Dovecot documentation calls weak, and the script takes the password as a command-line argument, where it lands in the shell history and the process list. Generate hashes withdoveadm pw, which prompts for the password, using the strongest scheme your build supports (ARGON2ID, then BLF-CRYPT, then SHA512-CRYPT). mechanisms = plain digest-md5: DIGEST-MD5 cannot be verified against crypt-style hashes, so it never worked with this password file. Offerplain(andloginif needed) and protect them with TLS.- Snakeoil certificate and
smtpd_use_tls:ssl-cert-snakeoil.pemis the self-signed placeholder Debian generates at install time. Use a certificate that clients can validate, and replacesmtpd_use_tls=yes(deprecated as of Postfix 3.9) withsmtpd_tls_security_level = may. - Sending mail: the setup relays only for
mynetworksand has no SMTP AUTH. For users outside the LAN add a submission service on 587 or 465 that authenticates through Dovecot (smtpd_sasl_type = dovecot,smtpd_sasl_path = private/auth). - Root and world-writable files:
user = rootfor the auth process andcreate 666 root admfor the Dovecot logs are not needed. Run delivery under the singlevmailaccount and keep log files writable by their owner only. - Delivery and Sieve: Postfix
virtualwrites the Maildirs here and thecmusieveplugin of Dovecot 1.x is left commented out. Today Postfix hands mail to Dovecot over LMTP (virtual_transport), which is what makes Sieve filtering (Pigeonhole, plugin namesieve) and ManageSieve available. hash:andbtree:tables: both need Berkeley DB, which some distributions are removing; Postfix documents the migration tolmdb:inNON_BERKELEYDB_README.- SquirrelMail, MailScanner, ClamAV: they appear in the title but the notes never configure them. The last stable SquirrelMail release (1.4.22) dates from 2011 and only snapshots have appeared since, so choose a maintained webmail.
$ # doveadm pw -s ARGON2ID
Sources: