Scripts

------

http://www.htt-consult.com/Centos7-mailserver.html

yum install httpd mod_ssl php mariadb-server php-mysql telnet

yum install dovecot dovecot-mysql dovecot-pigeonhole policycoreutils

yum install perl-MIME-EncWords perl-MIME-Charset php-imap

yum install perl-Email-Valid perl-Test-Pod

yum install perl-Mail-Sender imapsync offlineimap

yum install roundcubemail php-mcrypt php-enchant aspell-en

yum install spamassassin amavisd-new clamav clamav-devel perl-Convert-BinHex

yum install clamav-server clamav-update clamav-server-systemd clamav-scanner

http://sourceforge.net/projects/postfixadmin/

Let's assume that the current version you downloaded is: 3.2.  Place it in /usr/share.

cd /usr/share

wget https://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-3.2/postfixadmin-3.2.tar.gz

tar -xzvf postfixadmin-3.2.tar.gz

mv postfixadmin-3.2/ postfixadmin

rm -f postfixadmin-3.2*

chown -R root:root postfixadmin

chmod 700 postfixadmin/templates/

chown apache:apache postfixadmin/templates/

http://php.net/date.timezone

sed -i -e "s';date.timezone ='date.timezone = $date_timezone'w /dev/stdout" /etc/php.ini

mkdir /home/vmail

chmod 770 /home/vmail

useradd -r -u 101 -g mail -d /home/vmail -s /sbin/nologin -c "Virtual mailbox" vmail

chown vmail:mail /home/vmail

chcon -Rv --type=mail_home_rw_t /home/vmail/

Setting up MariaDB

systemctl enable mariadb

systemctl start mariadb

mysql_secure_installation <<EOF || exit 1

y

$Mysql_Root_Password

$Mysql_Root_Password

y

y

y

y

EOF

 postfixadmin.

mysql -u root -p$Mysql_Root_Password <<EOF || exit 1

CREATE DATABASE postfix;

CREATE USER postfix@localhost IDENTIFIED BY "$Postfix_Database_Password";

GRANT ALL PRIVILEGES ON postfix.* TO postfix@localhost;

EOF

Roundcube database.

mysql -u root -p$Mysql_Root_Password <<EOF || exit 1

CREATE DATABASE roundcubemail;

CREATE USER roundcube@localhost IDENTIFIED BY "$Roundcube_Database_Password";

GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost;

FLUSH PRIVILEGES;

EOF

mysql -u root -p$Mysql_Root_Password roundcubemail < /usr/share/roundcubemail/SQL/mysql.initial.sql

Setting up Apache

bind 'set disable-completion on'

cat <<EOF>/etc/httpd/conf.d/00-init.conf || exit 1

ServerAdmin $admin_email

ServerName $your_host_tld

<VirtualHost *:80>

<Directory "/var/www/html">

Options Indexes FollowSymLinks

AllowOverride None

Require all granted

</Directory>

</VirtualHost>

<VirtualHost *:443>

SSLEngine On

SSLCertificateFile /etc/pki/tls/certs/$your_host_tld.crt

SSLCertificateKeyFile /etc/pki/tls/private/$your_host_tld.key

<Directory "/var/www/html">

Options Indexes FollowSymLinks

AllowOverride None

Require all granted

</Directory>

</VirtualHost>

EOF

bind 'set disable-completion off'

sed -i -e "s/all granted/ip 192.168.0.0\/16/gw /dev/stdout" /etc/httpd/conf.d/00-init.conf

postfixadmin's Apache conf file. 

bind 'set disable-completion on'

cat <<EOF>/etc/httpd/conf.d/postfixadmin.conf || exit 1

alias /mailadmin /usr/share/postfixadmin/public

<Directory "/usr/share/postfixadmin/public">

AllowOverride AuthConfig

Require all granted

</Directory>

EOF

bind 'set disable-completion off'

Postfixadmin is a Security Risk; Postfixadmin access can be restricted to your IP addresses.  Finer control can be added into a /usr/share/postfixadmin/.htaccess file.

sed -i -e "s/all granted/ip 192.168.0.0\/16/gw /dev/stdout" /etc/httpd/conf.d/postfixadmin.conf

Postfixadmin access is via 'http://your_host_tld/mailadmin'.

cp -b /etc/httpd/conf.d/roundcubemail.conf /etc/httpd/conf.d/roundcubemail.conf.save

bind 'set disable-completion on'

cat <<EOF>/etc/httpd/conf.d/roundcubemail.conf || exit 1

<VirtualHost *:80>

# Alias /roundcubemail /usr/share/roundcubemail

# Alias /webmail /usr/share/roundcubemail

ServerName webmail.$your_domain_tld

ServerAlias webmail

Redirect permanent / https://webmail.$your_domain_tld/

ExpiresDefault "access plus 1 years"

php_admin_flag session.cookie_secure "1"

</VirtualHost>

<VirtualHost *:443>

# Round Cube Webmail is a browser-based multilingual IMAP client

#

# Alias /roundcubemail /usr/share/roundcubemail

# Alias /webmail /usr/share/roundcubemail

ServerName webmail.$your_domain_tld

ServerAlias webmail

SSLEngine On

SSLCertificateFile /etc/pki/tls/certs/webmail.$your_domain_tld.crt

SSLCertificateKeyFile /etc/pki/tls/private/webmail.$your_domain_tld.key

DocumentRoot /usr/share/roundcubemail

<Directory /usr/share/roundcubemail/>

Require ip 192.168.0.0/16

# You can enlarge permissions once configured

# Require all granted

php_admin_flag session.cookie_secure "1"

</Directory>

</VirtualHost>

# Define who can access the installer

# keep this secured once configured

Alias /roundcubemail /usr/share/roundcubemail

<Directory /usr/share/roundcubemail/installer/>

# You may want to restrict the installer to a single IP address

Require ip 192.168.0.0/16

</Directory>

# Those directories should not be viewed by Web clients.

<Directory /usr/share/roundcubemail/bin/>

Require all denied

</Directory>

<Directory /usr/share/roundcubemail/plugins/enigma/home/>

Require all denied

</Directory>

EOF

bind 'set disable-completion off'

Last step for setting up Apache is creating the SSL certificates.  Three certificates are needed.  One for webmail.$your_domain_tld, another for $your_host_tld, and the third for localhost.  Follow how you setup the roundcubemail.conf and how your users will access your server.  The following commands will create the RSA 2048/SHA256 certificates with a 10 years life.

These are self-signed certificates.  You can purchase your certificates from a recognized CA.  You can find instructions on how to create your own CA and issue these certificates from it.  Future work will add a section on using Let's Encrypt certificates.

restore_mask=$(umask -p)

umask 077

cd /etc/pki/tls

commonName=$your_host_tld

openssl req -new -outform PEM -out certs/$commonName.crt -newkey rsa:2048 -nodes -keyout private/$commonName.key -keyform PEM -days 3650 -x509 -extensions v3_req -subj "/countryName=$countryName/stateOrProvinceName=$stateOrProvinceName/localityName=$localityName/organizationName=$organizationName/organizationalUnitName=$organizationalUnitName/commonName=$commonName/emailAddress=$emailAddress"

chmod 640 private/$commonName.key

openssl req -new -outform PEM -out certs/localhost.crt -newkey rsa:2048 -nodes -keyout private/localhost.key -keyform PEM -days 3650 -x509 -extensions v3_req -subj "/countryName=$countryName/stateOrProvinceName=$stateOrProvinceName/localityName=$localityName/organizationName=$organizationName/organizationalUnitName=$organizationalUnitName/commonName=$commonName/emailAddress=$emailAddress"

chmod 640 private/localhost.key

commonName=webmail.$your_domain_tld

openssl req -new -outform PEM -out certs/$commonName.crt -newkey rsa:2048 -nodes -keyout private/$commonName.key -keyform PEM -days 3650 -x509 -extensions v3_req -subj "/countryName=$countryName/stateOrProvinceName=$stateOrProvinceName/localityName=$localityName/organizationName=$organizationName/organizationalUnitName=$organizationalUnitName/commonName=$commonName/emailAddress=$emailAddress"

chmod 640 private/$commonName.key

$restore_mask

openssl x509 -in certs/$commonName.crt -text -nameopt multiline -noout|more

systemctl enable httpd

systemctl start httpd

Configuring Postfix

Now on to configure the actual packages starting with Postfix.

Postfix is a real task to configure.  It will be easier in versions of Postfix beyond 2.10 that is supplied in Centos 7.  The following modifies the existing config files, rather than replacing them.

This is a 'best effort' from reviewing a number of sources. 

The place to start is with main.cf.  Note that message_size_limit limits a message to ~20Meg.  Change this as needed.

cp /etc/postfix/main.cf /etc/postfix/main.cf.save

# postfix config file

# uncomment for debugging if needed

#postconf -e 'soft_bounce=yes'

# postfix main

postconf -e 'delay_warning_time = 4'

# network settings

postconf -e 'inet_interfaces = all'

postconf -e "mydomain = $your_domain_tld"

postconf -e "myhostname = $your_host_tld"

postconf -e 'mynetworks = $config_directory/mynetworks'

postconf -e 'relay_domains = proxy:mysql:/etc/postfix/mysql-relay_domains_maps.cf'

# mail delivery

postconf -e 'recipient_delimiter = +'

postconf -e 'content_filter = amavisfeed:[127.0.0.1]:10024'

# mappings

postconf -e 'alias_maps = hash:/etc/aliases'

postconf -e 'transport_maps = hash:/etc/postfix/transport'

# virtual setup

postconf -e 'virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_alias_maps.cf, regexp:/etc/postfix/virtual_regexp'

postconf -e 'virtual_mailbox_base = /home/vmail'

postconf -e 'virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains_maps.cf'

postconf -e 'virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailbox_maps.cf'

postconf -e 'virtual_minimum_uid = 101'

postconf -e 'virtual_uid_maps = static:101'

postconf -e 'virtual_gid_maps = static:12'

postconf -e 'virtual_transport = dovecot'

postconf -e 'dovecot_destination_recipient_limit = 1'

# authentication

postconf -e 'smtpd_sasl_auth_enable = yes'

# postconf -e 'smtpd_sasl_security_options = noanonymous'

postconf -e 'smtpd_sasl_local_domain = $mydomain'

postconf -e 'broken_sasl_auth_clients = yes'

postconf -e 'smtpd_sasl_type = dovecot'

postconf -e 'smtpd_sasl_path = private/auth'

# tls config

postconf -e 'smtp_use_tls = yes'

postconf -e 'smtp_tls_exclude_ciphers = RC4, aNULL'

postconf -e 'smtp_tls_loglevel = 1'

postconf -e 'smtp_tls_note_starttls_offer = yes'

postconf -e 'smtp_tls_protocols = !SSLv2, !SSLv3'

postconf -e 'smtp_tls_security_level = may'

postconf -e 'smtp_tls_session_cache_database = btree:$data_directory/smtp_tls_session_cache'

postconf -e 'smtpd_tls_cert_file = /etc/pki/tls/certs/$myhostname.crt'

postconf -e 'smtpd_tls_exclude_ciphers = RC4, aNULL'

postconf -e 'smtpd_tls_key_file = /etc/pki/tls/private/$myhostname.key'

postconf -e 'smtpd_tls_loglevel = 1'

postconf -e 'smtpd_tls_mandatory_exclude_ciphers = aNULL, eNULL, EXPORT, DES, RC4, MD5, PSK, aECDH, EDH-DSS-DES-CBC3-SHA, EDH-RSA-DES-CDC3-SHA, KRB5-DE5, CBC3-SHA'

postconf -e 'smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3'

postconf -e 'smtpd_tls_protocols = !SSLv2, !SSLv3'

postconf -e 'smtpd_tls_received_header = yes'

postconf -e 'smtpd_tls_security_level = may'

postconf -e 'smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache'

postconf -e 'smtpd_use_tls = yes'

# rules restrictions

postconf -e 'smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_non_fqdn_sender, reject_non_fqdn_recipient, reject_unknown_recipient_domain'

postconf -e 'smtpd_sender_login_maps = mysql:/etc/postfix/mysql-virtual_alias_maps.cf'

# others

postconf -e 'smtpd_helo_required = yes'

postconf -e 'disable_vrfy_command = yes'

postconf -e 'message_size_limit = 20480000'

postconf -e 'smtpd_data_restrictions = reject_unauth_pipelining'

postconf -e 'smtpd_banner = $myhostname ESMTP'

master.cf is next.

cp /etc/postfix/master.cf /etc/postfix/master.cf.save

bind 'set disable-completion on'

cat <<\EOF>>/etc/postfix/master.cf || exit 1

# ==========================================================================

# service type  private unpriv  chroot  wakeup  maxproc command + args

#               (yes)   (yes)   (yes)   (never) (100)

# ==========================================================================

smtpd     pass  -       -       n       -       -       smtpd

submission inet n       -       n       -       -       smtpd

-o smtpd_recipient_restrictions=

check_policy_service inet:127.0.0.1:12340

relay     unix  -       -       n       -       -       smtp

-o fallback_relay=

maildrop  unix  -       n       n       -       -       pipe

  flags=DRhu user=vmail argv=/usr/local/bin/maildrop -d ${recipient}

uucp      unix  -       n       n       -       -       pipe

  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)

ifmail    unix  -       n       n       -       -       pipe

  flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)

bsmtp     unix  -       n       n       -       -       pipe

  flags=Fq. user=bsmtp argv=/usr/local/sbin/bsmtp -f $sender $nexthop $recipient

#

# spam/virus section

#

amavisfeed unix - - y - 2 lmtp

-o lmtp_data_done_timeout=1200

-o lmtp_send_xforward_command=yes

-o disable_dns_lookups=yes

-o max_use=20

127.0.0.1:10025 inet n - n - - smtpd

-o content_filter=

-o smtpd_delay_reject=no

-o smtpd_client_restrictions=permit_mynetworks,reject

-o smtpd_helo_restrictions=

-o smtpd_sender_restrictions=

-o smtpd_recipient_restrictions=permit_mynetworks,reject

-o smtpd_data_restrictions=reject_unauth_pipelining

-o smtpd_end_of_data_restrictions=

-o smtpd_restriction_classes=

-o mynetworks=127.0.0.0/8

-o smtpd_error_sleep_time=0

-o smtpd_soft_error_limit=1001

-o smtpd_hard_error_limit=1000

-o smtpd_client_connection_count_limit=0

-o smtpd_client_connection_rate_limit=0

-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters

-o local_header_rewrite_clients=

-o smtpd_milters=

-o local_recipient_maps=

-o relay_recipient_maps=

#

# Dovecot LDA

dovecot unix - n n - - pipe

  flags=DRhu user=vmail:mail argv=/usr/libexec/dovecot/deliver -d ${recipient}

#

# Vacation mail

vacation unix - n n - - pipe

  flags=Rq user=vacation argv=/var/spool/vacation/vacation.pl -f ${sender} -- ${recipient}

EOF

bind 'set disable-completion off'

And if you have to support Outlook TLS connections, then

bind 'set disable-completion on'

cat <<EOF>>/etc/postfix/master.cf || exit 1

# Enable only if you have to support Outlook TLS connections

smtps inet n - n - - smtpd

#

EOF

bind 'set disable-completion off'

Next a number of files in /etc/postfix

mynetworks

mysql-virtual_alias_maps.cf

mysql-virtual_domains_maps.cf

mysql-relay_domains_maps.cf

mysql-virtual_mailbox_maps.cf

virtual_regexp

cat <<EOF>/etc/postfix/mynetworks || exit 1

# This specifies the list of subnets that Postfix considers as

# "trusted" SMTP clients that have more privileges than "strangers".

#

# In particular, "trusted" SMTP clients are allowed to relay mail

# through Postfix.

#

# Be sure to add your public ip address block if needed.

#

192.168.0.0/16

10.0.0.0/8

127.0.0.0/8

EOF

cat <<EOF>/etc/postfix/mysql-virtual_alias_maps.cf || exit 1

hosts = localhost

user = postfix

password = $Postfix_Database_Password

dbname = postfix

query = SELECT goto FROM alias WHERE address='%s' AND active = '1'

EOF

cat <<EOF>/etc/postfix/mysql-virtual_domains_maps.cf || exit 1

hosts = localhost

user = postfix

password = $Postfix_Database_Password

dbname = postfix

query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'

EOF

cat <<EOF>/etc/postfix/mysql-relay_domains_maps.cf || exit 1

hosts = localhost

user = postfix

password = $Postfix_Database_Password

dbname = postfix

query = SELECT domain FROM domain WHERE domain='%s' and backupmx = '1'

EOF

cat <<EOF>/etc/postfix/mysql-virtual_mailbox_maps.cf || exit 1

hosts = localhost

user = postfix

password = $Postfix_Database_Password

dbname = postfix

query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'

EOF

touch /etc/postfix/virtual_regexp

Edit /etc/postfix/mynetworks as needed,

The last step for postfix is the Vacation Email Functionality

useradd -r -d /var/spool/vacation -s /sbin/nologin -c "Virtual vacation" vacation

mkdir /var/spool/vacation

chmod 770 /var/spool/vacation

cp /usr/share/postfixadmin/VIRTUAL_VACATION/vacation.pl /var/spool/vacation/

echo "autoreply."$your_domain_tld" vacation:" > /etc/postfix/transport

postmap /etc/postfix/transport

chown -R vacation:vacation /var/spool/vacation

echo "127.0.0.1    autoreply."$your_domain_tld >> /etc/hosts

mkdir /etc/postfixadmin

And finally create /etc/postfixadmin/vacation.conf

cat <<\EOF>/etc/postfixadmin/vacation.conf || exit 1

# ========== begin configuration ==========

$db_type = 'mysql';

$db_username = 'user';

$db_password = 'postfixsqlpassword';    

$db_name     = 'postfix';

$vacation_domain = 'autoreply.change-this-to-your.domain.tld';

EOF

sed -i -e "s/postfixsqlpassword/$Postfix_Database_Password/w /dev/stdout" /etc/postfixadmin/vacation.conf

sed -i -e "s/change-this-to-your.domain.tld/$your_domain_tld/w /dev/stdout" /etc/postfixadmin/vacation.conf

systemctl restart postfix

Dovecot is next.  There are a number of Dovecot conf files to edit.  Instead, this guide uses the local.conf file which is loaded after the default conf files.  By using the default files and local.conf, these modifications should work in future versions of Dovecot.  The files altered by the local.conf are:

dovecot.conf

10-auth.conf

auth-sql.conf.ext

10-mail.conf

10-master.conf

10-ssl.conf

15-lda.conf

20-imap.conf

20-lmtp.conf

20-managesieve.conf

20-pop3.conf

90-acl.conf

90-quota.conf

90-sieve.conf

bind 'set disable-completion on'

cat <<EOF>/etc/dovecot/local.conf || exit 1

# Developed on Dovecot 2.2.36

# dovecot.conf

protocols = imap pop3 lmtp sieve

dict {

sqlquota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext

}

service quota-status {

executable = quota-status -p postfix

inet_listener {

port = 12340

# You can choose any port you want

}

client_limit = 1

}

# 10-auth.conf

!include conf.d/auth-sql.conf.ext

# auth-sql.conf.ext

userdb {

driver = prefetch

}

# 10-mail.conf

mail_location = maildir:/home/vmail/%d/%n

first_valid_uid = 101

first_valid_gid = 12

# Space separated list of plugins to load for all services. Plugins specific to

# IMAP, LDA, etc. are added to this list in their own .conf files.

mail_plugins = $mail_plugins quota

mailbox_list_index = yes

# Avoid spending excessive time waiting for the quota calculation to finish when

# mails' vsizes aren't already cached. If this many mails are opened, finish the

# quota calculation on background in indexer-worker process. Mail deliveries will

# be assumed to succeed, and explicit quota lookups will return internal error.

mail_vsize_bg_after_count = 100

# 10-master.conf

service auth {

unix_listener auth-userdb {

mode = 0666

user = vmail

group = mail

}

unix_listener /var/spool/postfix/private/auth {

mode = 0666

user = postfix

group = postfix

}

}

service dict {

unix_listener dict {

mode = 0666

user = vmail

group = mail

}

}

# 10-ssl.conf

ssl_cert = </etc/pki/tls/certs/$your_host_tld.crt

ssl_key = </etc/pki/tls/private/$your_host_tld.key

# 15-lda.conf

postmaster_address = postmaster@$your_domain_tld

protocol lda {

mail_plugins = quota sieve

}

lda_mailbox_autocreate = yes

lda_mailbox_autosubscribe = yes

# 20-imap.conf

imap_client_workarounds = delay-newmail

protocol imap {

  # Space separated list of plugins to load (default is global mail_plugins).

  mail_plugins = $mail_plugins imap_quota trash

}

# 20-lmtp.conf

lmtp_save_to_detail_mailbox = yes

protocol lmtp {

mail_plugins = sieve

}

# 20-managesieve.conf

service managesieve-login {

inet_listener sieve {

port = 4190

}

service_count = 1

process_min_avail = 0

vsz_limit = 64M

}

# 20-pop3.conf

pop3_client_workarounds = outlook-no-nuls oe-ns-eoh

protocol pop3 {

mail_plugins = quota

}

# 90-acl.conf

plugin {

acl = vfile:/etc/dovecot/global-acls:cache_secs=300

}

# 90-quota.conf

plugin {

        quota = dict:user::proxy::sqlquota

        trash = /etc/dovecot/dovecot-trash.conf.ext

}

plugin {

quota_grace = 10%%

# 10% is the default

quota_status_success = DUNNO

quota_status_nouser = DUNNO

quota_status_overquota = "552 5.2.2 Mailbox is full"

}

# 90-sieve.conf

plugin {

sieve_before = /home/sieve/globalfilter.sieve

}

EOF

bind 'set disable-completion off'

Next the following files are added into /etc/dovecot

dovecot-trash.conf.ext

dovecot-sql.conf.ext

dovecot-dict-sql.conf.ext

Note that the user_query limits an imap mailbox to 30,000 messages.  Change this as needed.

mv /etc/dovecot/dovecot-trash.conf.ext /etc/dovecot/dovecot-trash.conf.ext.save

mv /etc/dovecot/dovecot-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext.save

mv /etc/dovecot/dovecot-dict-sql.conf.ext /etc/dovecot/dovecot-dict-sql.conf.ext.save

bind 'set disable-completion on'

cat <<EOF>/etc/dovecot/dovecot-trash.conf.ext || exit 1

# Spam mailbox is emptied before Trash

1 Spam

# Trash mailbox is emptied before Sent

# 2 Trash

# If both Sent and "Sent Messages" mailboxes exist, the next oldest message

# to be deleted is looked up from both of the mailboxes.

# 3 Sent

# 3 Sent Messages

EOF

cat <<EOF>/etc/dovecot/dovecot-sql.conf.ext || exit 1

driver = mysql

connect = host=/var/lib/mysql/mysql.sock dbname=postfix user=postfix password=$Postfix_Database_Password

default_pass_scheme = $cryptsha-CRYPT

# following should all be on one line.

password_query = SELECT username as user, password, concat('/home/vmail/', maildir) as userdb_home, concat('maildir:/home/vmail/', maildir) as userdb_mail, 101 as userdb_uid, 12 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'

# following should all be on one line

user_query = SELECT concat('/home/vmail/', maildir) as home, concat('maildir:/home/vmail/', maildir) as mail, 101 AS uid, 12 AS gid, CONCAT('*:messages=30000:bytes=', quota) as quota_rule FROM mailbox WHERE username = '%u' AND active = '1'

EOF

cat <<EOF>/etc/dovecot/dovecot-dict-sql.conf.ext || exit 1

connect = host=/var/lib/mysql/mysql.sock dbname=postfix user=postfix password=$Postfix_Database_Password

map {

pattern = priv/quota/storage

table = quota2

username_field = username

value_field = bytes

}

map {

pattern = priv/quota/messages

table = quota2

username_field = username

value_field = messages

}

EOF

bind 'set disable-completion off'

Now create the sieve filter for SPAM filtering

bind 'set disable-completion on'

mkdir /home/sieve

cat <<EOF>/home/sieve/globalfilter.sieve || exit 1

require "fileinto";

if anyof

(

header :contains "X-Spam-Flag" "YES",

header :contains "subject" "***SPAM***"

)

{

fileinto "Spam";

}

EOF

bind 'set disable-completion off'

sievec /home/sieve/globalfilter.sieve

chown -R vmail:mail /home/sieve

chcon -Rv --type=mail_home_rw_t /home/sieve/

SELinux needs a policy to allow Dovecot to access the mysql unix socket.  As of Feb 5, 2019, this policy has been rolled into Fedora 28 and up, and in time will be included in CentOS.

bind 'set disable-completion on'

cat <<\EOF>dovecot_mysql.te || exit 1

policy_module(dovecot_mysql,1.0.0)

gen_require(`

type dovecot_t;

')

mysql_read_config(dovecot_t)

mysql_stream_connect(dovecot_t)

EOF

bind 'set disable-completion off'

make -f /usr/share/selinux/devel/Makefile dovecot_mysql.pp

semodule -i dovecot_mysql.pp

systemctl enable dovecot

systemctl start dovecot

Configuring Amavis and Clamav

These two packages work together, along with Spamassassin, to provide anti-spam and anti-virus protection.  Their configuration is simple.

With some guidance from https://ismailyenigul.wordpress.com/2015/01/05/install-clamav-on-centos-7/

And more from http://forums.sentora.org/showthread.php?tid=1132

We can get clamav working with the following:

cp /etc/clamd.d/scan.conf /etc/clamd.d/scan.conf.save

cp /etc/freshclam.conf /etc/freshclam.conf.save

sed -i -e "s/^Example/#Example/w /dev/stdout" /etc/freshclam.conf

sed -i -e "s/^Example/#Example/w /dev/stdout" /etc/clamd.d/scan.conf

sed -i -e "s/clamd.scan /clamd.amavisd /w /dev/stdout" /etc/clamd.d/scan.conf

sed -i -e "s/^#LocalSocket /LocalSocket /w /dev/stdout" /etc/clamd.d/scan.conf

sed -i -e "s/^FRESHCLAM_DELAY/#FRESHCLAM_DELAY/w /dev/stdout" /etc/sysconfig/freshclam

setsebool -P antivirus_can_scan_system 1

setsebool -P clamd_use_jit 1

freshclam

Next edit /etc/amavisd/amavisd.conf.

cp /etc/amavisd/amavisd.conf /etc/amavisd/amavisd.conf.save

cat <<\EOF>>/etc/amavisd/amavisd.conf || exit 1

$mydomain = 'your_domain_tld';

$myhostname = 'your_host_tld'; #  must be a fully-qualified domain name!

$log_level = 1; # set the log level to one

$sa_tag_level_deflt = -99; # I want to see the headers so change to -99

$sa_tag2_level_deflt = 5.0; # start with 5

$sa_kill_level_deflt = 9;

$sa_dsn_cutoff_level = 9;

$sa_quarantine_cutoff_level = 50;

$notify_method = 'smtp:[127.0.0.1]:10025';

$forward_method = 'smtp:[127.0.0.1]:10025';

$final_banned_destiny = D_BOUNCE;

$final_spam_destiny = D_PASS;

@mynetworks = qw( 127.0.0.0/8 [::1] [FE80::]/10 [FEC0::]/10

10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 your_ipv4_address_block);

@lookup_sql_dsn =

( ['DBI:mysql:database=postfix;host=localhost;mysql_socket=/var/lib/mysql/mysql.sock', 'postfix', 'postfixsqlpassword'] );

$sql_select_white_black_list = undef;

$sql_select_policy = 'SELECT "Y" as local, 1 as id FROM domain WHERE CONCAT("@",domain) IN (%k)';

1;  # insure a defined return value

EOF

sed -i -e "s/your_domain_tld/$your_domain_tld/w /dev/stdout" /etc/amavisd/amavisd.conf

sed -i -e "s/your_host_tld/$your_host_tld/w /dev/stdout" /etc/amavisd/amavisd.conf

sed -i -e "s/your_ipv4_address_block/$your_ipv4_address_block/w /dev/stdout" /etc/amavisd/amavisd.conf

sed -i -e "s/postfixsqlpassword/$Postfix_Database_Password/w /dev/stdout" /etc/amavisd/amavisd.conf

Finally start it all:

gpasswd -a clamscan amavis

sa-update

systemctl enable amavisd

systemctl enable spamassassin

systemctl stop postfix

systemctl start spamassassin

systemctl start amavisd # This will also run ClamAV

systemctl start postfix

A simple test of clamav is

clamdscan -c /etc/clamd.d/scan.conf /etc/hosts

Test the amavis connection with

telnet localhost 10024

ehlo localhost

quit

telnet localhost 10025

ehlo localhost

quit

Configuring Postfixadmin

Postfixadmin is the email domain and email account management tool.

Create a base /usr/share/postfixadmin/config.local.php

bind 'set disable-completion on'

cat <<\EOF>/usr/share/postfixadmin/config.local.php || exit 1

<?php

/**

 * Contains configuration options that override the default config file

 */

/*****************************************************************

 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

 * You have to set \$CONF['configured'] = true; before the

 * application will run!

 * Doing this implies you have changed this file as required.

 * i.e. configuring database etc; specifying setup.php password etc.

 */

$CONF['configured'] = true;

// In order to setup Postfixadmin, you MUST specify a hashed password here.

// To create the hash, visit /postfixadmin/setup.php in a browser and type a password into the field,

// on submission it will be echoed out to you as a hashed value.

$CONF['setup_password'] = 'changeme';

$CONF['database_password'] = 'postfixsqlpassword';

// Default Aliases

// The default aliases that need to be created for all domains.

$CONF['default_aliases'] = array (

'abuse' => 'abuse@change-this-to-your.domain.tld',

'hostmaster' => 'hostmaster@change-this-to-your.domain.tld',

'postmaster' => 'postmaster@change-this-to-your.domain.tld',

'webmaster' => 'webmaster@change-this-to-your.domain.tld'

);

$CONF['admin_email'] = 'postfixadmin_email';

$CONF['dovecotpw'] = "/usr/bin/doveadm pw";

$CONF['page_size'] = '20';

$CONF['aliases'] = '50';

$CONF['mailboxes'] = '50';

$CONF['maxquota'] = '100';

$CONF['transport'] = 'YES';

$CONF['vacation'] = 'YES';

$CONF['vacation_domain'] = 'autoreply.change-this-to-your.domain.tld';

$CONF['special_alias_control'] = 'YES';

$CONF['footer_text'] = 'Return to change-this-to-your.domain.tld';

$CONF['footer_link'] = 'http://change-this-to-your.domain.tld';

$CONF['create_mailbox_subdirs']=array('Drafts','Spam','Sent','Trash');

$CONF['create_mailbox_subdirs_host']='localhost';

$CONF['create_mailbox_subdirs_prefix']='';

$CONF['quota'] = 'YES';

$CONF['used_quotas'] = 'YES';

$CONF['new_quota_table'] = 'YES';

// $CONF['create_mailbox_subdirs_hostoptions']=array('notls');

$CONF['create_mailbox_subdirs_hostoptions']=array('novalidate-cert','norsh');

$CONF['encrypt'] = 'dovecot:cryptsha-CRYPT';

$CONF['dovecotpw'] = "/usr/bin/doveadm pw ";

//

// END OF CONFIG FILE

//

?>

EOF

bind 'set disable-completion off'

sed -i -e "s/postfixadmin_email/$admin_email/w /dev/stdout" /usr/share/postfixadmin/config.local.php

sed -i -e "s/postfixsqlpassword/$Postfix_Database_Password/w /dev/stdout" /usr/share/postfixadmin/config.local.php

sed -i -e "s/cryptsha/$cryptsha/w /dev/stdout" /usr/share/postfixadmin/config.local.php

sed -i -e "s/change-this-to-your.domain.tld/$your_domain_tld/gw /dev/stdout" /usr/share/postfixadmin/config.local.php

SELinux seems to be a problem for Postfixadmin (and Roundcubemail which needs the setsebool).

chcon -R -t httpd_sys_content_rw_t /usr/share/postfixadmin/templates

setsebool -P httpd_can_network_connect on

Now go to host/mailadmin/setup.php

Configuring Roundcubemail

chown root:apache /etc/roundcubemail

chmod 775 /etc/roundcubemail

Roundcubemail is written in php and a couple php defaults may not be right for Roundcubemail, particularly the file upload size and message size maximums.  The following will comment out the defaults and add new maximums.  Change them as you need.

sed -i -e "/^upload_max_filesize/s/^/#/w /dev/stdout" /etc/php.ini

sed -i -e '/^#upload_max_filesize/ a upload_max_filesize = 5M' /etc/php.ini

sed -i -e "/^post_max_size/s/^/#/w /dev/stdout" /etc/php.ini

sed -i -e '/^#post_max_size/ a post_max_size = 20M' /etc/php.ini

http://*FQDN*/roundcubemail/installer

If in your system 0 quota means no limit

cat <<\EOF>>/etc/roundcubemail/config.inc.php || exit 1

$config['quota_zero_as_unlimited'] = true;

EOF

To allow browser-autocompletion of username and host on login form.

cat <<\EOF>>/etc/roundcubemail/config.inc.php || exit 1

$config['login_autocomplete'] = 1;

EOF

To directly delete messages in Junk instead of moving to Trash.

cat <<\EOF>>/etc/roundcubemail/config.inc.php || exit 1

$config['delete_junk'] = true;

EOF

This quide uses 'Spam' for the 'Junk' folder.  To force Roundcubemail to display 'Spam', rather than 'Junk' as default.

cat <<\EOF>>/etc/roundcubemail/config.inc.php || exit 1

$config['show_real_foldernames'] = true;

EOF

Apache is configured to redirect to secure connections.  Roundcubemail can check and redirect if the Apache configuration is wrong with:

cat <<\EOF>>/etc/roundcubemail/config.inc.php || exit 1

$config['force_https'] = true;

EOF

Now we set up the manage sieve plugin.

cp /usr/share/roundcubemail/plugins/managesieve/config.inc.php.dist /usr/share/roundcubemail/plugins/managesieve/config.inc.php

For the password plugin:

cp /usr/share/roundcubemail/plugins/password/config.inc.php.dist /usr/share/roundcubemail/plugins/password/config.inc.php

cat <<\EOF>>/usr/share/roundcubemail/plugins/password/config.inc.php || exit 1

$config['password_db_dsn'] = 'mysql://postfix:postfixsqlpassword@localhost/postfix';

$config['password_query'] = 'UPDATE mailbox SET password=%c WHERE username=%u limit 1;';

EOF

sed -i -e "s/postfixsqlpassword/$Postfix_Database_Password/w /dev/stdout" /usr/share/roundcubemail/plugins/password/config.inc.php

systemctl restart httpd

For more on Dovecot testing see

http://wiki.dovecot.org/TestInstallation

For anti-virus testing, find sample.tar.gz.compl (check the version of amavisd-new) and change to that folder and untar it

cd /usr/share/doc/amavisd-new-2.11.1/test-messages

perl -pe 's/./chr(ord($&)^255)/sge' <sample.tar.gz.compl | zcat | tar xvf -

Then send the following emails.  virus-sample should be dropped, GTUBE should be moved to Spam, and README should end up in INBOX.

sendmail -i useremail < sample-virus-simple.txt

sendmail -i useremail < sample-spam-GTUBE-junk.txt

sendmail -i useremail < README

Updated 06/19/2019

-----