Mail server
# Config in distributor VPS web
Set Reverse DNS on VPS
mail.{domain}
Config SELinux
sudo nano /etc/selinux/config
SELINUX=disabled
Config HOSTNAME
sudo nano /etc/hosts
{IP_VPS} mail.{domain} mail
Config NetworkManager
sudo nano /etc/sysconfig/network
HOSTNAME=mail.{domain}
Restart NetworkManager service
sudo systemctl restart NetworkManager
Config DNS record
A @ 3600 {IP}
A mail 3600 {IP}
MX @ 3600 mail.{domain}
TXT @ 3600 "v=spf1 +a +mx +ip4:{IP} ~all"
TXT _dmarc 3600 "v=DMARC1; p=quarantine; pct=100; rua=mailto:{admin_email}; sp=none; aspf=r;"
TXT default._domainkey 3600 "v=DKIM1; k=rsa; p={dkim_token};"
Test HOST
host {domain}
{domain} has address {IP}
{domain} mail is handled by {priority} mail.{domain}
Test nslookup
nslookup
> mail.{domain}
Name: mail.{domain}
Address: {IP}
> exit
Test dig
dig {domain}
{domain}. {number} IN A {IP}
dig {domain} MX
{domain}. {number} IN MX 10 mail.{domain}.
Test ping
ping mail.{domain}
# Install Postfix
Install Postfix
sudo dnf install -y postfix postfix-mysql
Enable and start Postfix service
sudo systemctl enable --now postfix
# Install Dovecot
Install Dovecot
sudo dnf install -y dovecot dovecot-mysql
Enable and start Dovecot service
sudo systemctl enable --now dovecot
# Create mail database
Login MySQL
mysql -u root -p
Create database
CREATE DATABASE {db_mail};
Create user MySQL
CREATE USER {user_mail}@localhost IDENTIFIED BY '{password_mail}';
Grand permission user with database
GRANT ALL PRIVILEGES ON {db_mail}.* TO {user_mail}@localhost;
Apply privileges
FLUSH PRIVILEGES;
Use database
USE {db_mail};
Create table domain
CREATE TABLE tbl_domains (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
active INT NOT NULL DEFAULT 1,
PRIMARY KEY (id),
UNIQUE KEY name (name))
ENGINE=InnoDB DEFAULT CHARSET=utf8;
Create table user
CREATE TABLE tbl_users (
id INT NOT NULL AUTO_INCREMENT,
email VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
full_name VARCHAR(255) NOT NULL,
department VARCHAR(255) NOT NULL,
active INT NOT NULL DEFAULT 1,
domain_id INT NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY email (email),
FOREIGN KEY (domain_id) REFERENCES tbl_domains(id) ON DELETE CASCADE)
ENGINE=InnoDB DEFAULT CHARSET=utf8;
Create table alias
CREATE TABLE tbl_aliases (
id INT NOT NULL AUTO_INCREMENT,
source VARCHAR(255) NOT NULL,
destination TEXT NOT NULL,
active INT NOT NULL default 1,
domain_id INT NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY source (source),
FOREIGN KEY (domain_id) REFERENCES tbl_domains (id))
ENGINE=InnoDB DEFAULT CHARSET=utf8;
Insert data to table
INSERT INTO tbl_domains (name, active) VALUES ('{domain}', '1');
INSERT INTO tbl_users (email, password, full_name, department, domain_id) VALUES ('{email}', ENCRYPT('{password}'), '{full_name}', '{department}', '1');
INSERT INTO tbl_aliases (source, destination, domain_id) VALUES ('{alias}@{domain}', '{email}', '1');
Test database
SELECT * FROM tbl_domains;
SELECT * FROM tbl_users;
SELECT * FROM tbl_aliases;
exit;
# Config Postfix
main.cf
sudo nano /etc/postfix/main.cf
myhostname = mail.{domain}
mydomain = {domain}
myorigin = $mydomain
inet_interfaces = all
mydestination = localhost, localhost.localdomain
mynetworks = 127.0.0.0/8
relayhost =
recipient_delimiter = +
smtpd_banner = $myhostname ESMTP $mail_name
biff = no
Move end of file
# Config SASL Authentication
# Enabling SMTP for authenticated users, and handing off authentication to Dovecot
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_authenticated_header = yes
virtual_transport = lmtp:unix:private/dovecot-lmtp
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated permit_inet_interfaces reject_unauth_destination
# Config Virtual mailbox settings
# Virtual domains, users, and aliases
virtual_alias_domains =
virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, mysql:/etc/postfix/mysql-virtual_email2email.cf
virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf
virtual_mailbox_base = /home/{user_mail}
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_create_maildirsize = yes
virtual_maildir_extended = yes
proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $virtual_mailbox_limit_maps
# SSL-TLS parameters
smtpd_use_tls = yes
smtpd_tls_auth_only = yes
smtp_tls_security_level = may
smtpd_tls_security_level = may
smtpd_tls_cert_file = /etc/letsencrypt/live/{domain}/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/{domain}/privkey.pem
smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_tls_security_options = noanonymous
# Integrate OpenDKIM with Postfix
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = $smtpd_milters
milter_default_action = accept
# Integrate Amavis-new with Postfix
content_filter=smtp-amavis:[127.0.0.1]:10024
mysql-virtual_domains.cf
sudo nano /etc/postfix/mysql-virtual_domains.cf
user = {user_db}
password = {password_db}
dbname = {db_name}
query = SELECT name FROM tbl_domains WHERE name='%s' AND active=1
hosts = 127.0.0.1
mysql-virtual_forwardings.cf
sudo nano /etc/postfix/mysql-virtual_forwardings.cf
user = {user_db}
password = {password_db}
dbname = {db_name}
query = SELECT destination FROM tbl_aliases WHERE source='%s' AND active=1
hosts = 127.0.0.1
mysql-virtual_mailboxes.cf
sudo nano /etc/postfix/mysql-virtual_mailboxes.cf
user = {user_db}
password = {password_db}
dbname = {db_name}
query = SELECT CONCAT(SUBSTRING_INDEX(email, '@', -1), '/', SUBSTRING_INDEX(email, '@', 1), '/') FROM tbl_users WHERE email='%s' AND active=1
hosts = 127.0.0.1
mysql-virtual_email2email.cf
sudo nano /etc/postfix/mysql-virtual_email2email.cf
user = {user_db}
password = {password_db}
dbname = {db_name}
query = SELECT email FROM tbl_users WHERE email='%s' AND active=1
hosts = 127.0.0.1
Assign permission for mysql-virtual_*
sudo chmod o= /etc/postfix/mysql-virtual_*
sudo chgrp postfix /etc/postfix/mysql-virtual_*
Test connection
sudo postmap -q {domain} mysql:/etc/postfix/mysql-virtual_domains.cf
{domain}
sudo postmap -q {email} mysql:/etc/postfix/mysql-virtual_mailboxes.cf
{domain}/{email_name}
sudo postmap -q {alias}@{domain} mysql:/etc/postfix/mysql-virtual_forwardings.cf
{email}
Create group and assign permission
sudo groupadd -g 5000 {user_mail}
sudo useradd -g {user_mail} -u 5000 {user_mail} -d /home/{user_mail} -m
master.cf
sudo nano /etc/postfix/master.cf
smtp inet n - n - - smtpd
-o content_filter=spamassassin
submission inet n - n - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
-o smtpd_reject_unlisted_recipient=no
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
smtps inet n - n - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
-o content_filter=spamassassin
Move end of file
dovecot unix - n n - - pipe flags=DRhu user={user_mail}:{user_mail} argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}
spamassassin unix - n n - - pipe flags=R user=spamd argv=/usr/bin/spamc -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}
smtp-amavis unix - - n - 2 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
-o disable_dns_lookups=yes
127.0.0.1:10025 inet n - n - - smtpd
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8
-o strict_rfc821_envelopes=yes
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000
Restart Postfix service
sudo systemctl restart postfix
Add service to Firewall
sudo firewall-cmd --permanent --add-service=smtp
sudo firewall-cmd --permanent --add-service=smtps
Reload Firewall service
sudo firewall-cmd --reload
# Config Dovecot
dovecot.cf
sudo nano /etc/dovecot/dovecot.conf
protocols = imap pop3 lmtp
listen = *
10-mail.conf
sudo nano /etc/dovecot/conf.d/10-mail.conf
mail_location = maildir:/home/{user_mail}/%d/%n/maildir
mail_privileged_group = mail
10-auth.conf
sudo nano /etc/dovecot/conf.d/10-auth.conf
disable_plaintext_auth = no (SMTP) yes (TLS)
auth_mechanisms = plain login
!include auth-sql.conf.ext
auth-sql.conf.ext
sudo nano /etc/dovecot/conf.d/auth-sql.conf.ext
userdb {
driver = static
args = uid=5000 gid=5000 home=/home/{user_mail}/%d/%n allow_all_users=yes
}
dovecot-sql.conf.ext
sudo nano /etc/dovecot/dovecot-sql.conf.ext
driver = mysql
connect = host=127.0.0.1 dbname={db_name} user={user_db} password={password_db}
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email AS user, password FROM tbl_users WHERE email='%u' AND active=1;
Assign permission for dovecot-sql.conf.ext
sudo chgrp dovecot /etc/dovecot/dovecot-sql.conf.ext
sudo chmod o= /etc/dovecot/dovecot-sql.conf.ext
10-master.conf
sudo nano /etc/dovecot/conf.d/10-master.conf
service imap-login {
inet_listener imap {
port = 143
}
inet_listener imaps {
port = 993
ssl = yes
}
}
service pop3-login {
inet_listener pop3 {
port = 110
}
inet_listener pop3s {
port = 995
ssl = yes
}
}
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0660
user = postfix
group = postfix
}
}
service auth {
unix_listener auth-userdb {
mode = 0600
user = {user_mail}
}
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
user = dovecot
}
service auth-worker {
user = {user_mail}
}
10-ssl.conf
Mail no SSL/TLS
sudo nano /etc/dovecot/conf.d/10-ssl.conf
ssl = no
#ssh_cert = ...
#ssh_key = ...
Mail with SSL/TLS
sudo nano /etc/dovecot/conf.d/10-ssl.conf
ssl = required
ssh_cert = </etc/letsencrypt/live/{domain}/fullchain.pem
ssh_key = </etc/letsencrypt/live/{domain}/privkey.pem
Restart Dovecot service
sudo systemctl restart dovecot
Restart Postfix service
sudo systemctl restart postfix
Add service to Firewall
sudo firewall-cmd --permanent --add-service=pop3
sudo firewall-cmd --permanent --add-service=pop3s
Reload Firewall service
sudo firewall-cmd --reload
# Test Postfix
Test SMTP
telnet mail.{domain} smtp
220 mail.{domain} ESMTP Postfix
ehlo mail.{domain}
250 mail.{domain}
...
quit
Test POP3
telnet mail.{domain} pop3
+OK Dovecot ready
quit
View log mail
sudo tail -f /var/log/maillog
# Roundcube
Download current release
wget https://github.com/roundcube/roundcubemail/releases/download/1.6.8/roundcubemail-1.6.8-complete.tar.gz
Extract file
tar xvf roundcubemail-1.6.8-complete.tar.gz
Rename folder
mv roundcubemail-1.6.8 webmail
Copy to Apache
sudo cp -rf webmail /var/www/html
Login MySQL
mysql -u root -p
Create database
CREATE DATABASE {db_roundcube};
Create user MySQL
CREATE USER {user_roundcube}@localhost IDENTIFIED BY '{password_roundcube}';
Grand permission user with database
GRANT ALL PRIVILEGES ON {db_roundcube}.* TO {user_roundcube}@localhost;
Apply privileges
FLUSH PRIVILEGES;
exit;
Init database
mysql -u {user_roundcube} -p {db_roundcube} < /var/www/webmail/SQL/mysql.initial.sql
Change timezone
sudo nano /etc/php.ini
date.timezone = Asia/Ho_Chi_Minh
Restart php-fpm service
sudo systemctl restart php-fpm
Access installer
https://mail.{domain}/installer
IMAP host
ssl://mail.{domain}:993
SMTP server
tls://mail.{domain}:587
ssl://mail.{domain}:465
Tick plugins and save config
Save as config.inc.php under /var/www/webmail/config/ directory
Give ownership to the folder
sudo chown -R apache:apache /var/www/html/webmail/temp
sudo chown -R apache:apache /var/www/html/webmail/logs
Grant write permissions to the directory
sudo chmod -R 755 /var/www/html/webmail/temp
sudo chmod -R 755 /var/www/html/webmail/logs
Restart httpd service
sudo systemctl restart httpd
Test send email and remove installer directory
# SpamAssassin
Install SpamAssassin
sudo dnf install -y spamassassin
Config SpamAssassin
sudo nano /etc/mail/spamassassin/local.cf
required_score 5
Assign permission for SpamAssassin
sudo groupadd -g 5555 spamd
sudo useradd -u 5555 -g spamd -s /bin/false -d /var/log/spamassassin spamd
sudo chown spamd:spamd /var/log/spamassassin
Enable and start SpamAssassin service
sudo systemctl enable --now spamassassin
Restart Dovecot service
sudo systemctl restart dovecot
Restart Postfix service
sudo systemctl restart postfix
Send email with SPAM title from another email to email config
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
# OpenDKIM
Install OpenDKIM
sudo dnf --enablerepo=epel,crb -y install opendkim opendkim-tools
Create public and private key
sudo opendkim-genkey -D /etc/opendkim/keys -d {domain}
ls -la /etc/opendkim/keys
Config OpenDKIM
sudo nano /etc/opendkim.conf
Mode sv
Socket inet:8891@127.0.0.1
Umask 022
Canonicalization relaxed/simple
Domain {domain}
# KeyFile ...
KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
InternalHosts refile:/etc/opendkim/TrustedHosts
ls -la /etc/opendkim
sudo nano /etc/opendkim/KeyTable
default._domainkey.{domain} {domain}:default:/etc/opendkim/keys/default.private
sudo nano /etc/opendkim/SigningTable
*@{domain} default._domainkey.{domain}
sudo nano /etc/opendkim/TrustedHosts
# ::1
{domain}
mail.{domain}
Restart Dovecot service
sudo systemctl restart dovecot
Restart Postfix service
sudo systemctl restart postfix
Enable and start OpenDKIM service
sudo systemctl enable --now opendkim
Copy OpenDKIM key in config and paste to DNS default._domainkey record
sudo nano /etc/opendkim/keys/default.txt
Send email to verify
check-auth@verifier.port25.com
# Check virus
Install Amavisd
sudo dnf install -y clamav clamav-update amavisd-new
Config Amavisd
sudo nano /etc/amavisd/amavisd.conf
$mydomain = '{domain}';
$myhostname = 'mail.{domain}';
$notify_method = 'smtp:[127.0.0.1]:10025';
$forward_method = 'smtp:[127.0.0.1]:10025';
Enable and start Amavisd service
sudo systemctl enable --now amavisd
Restart Postfix service
sudo systemctl restart postfix
Send email to another email and go to "Show original" and find X-Virus-Scanned