0%

VPSTOOLBOX邮箱进阶篇--Postfix + Dovecot + Spamassassin + Roundcube Webmail + FairEmail 实现自建邮件伺服器,垃圾邮件过滤以及多设备同步

VPSTOOLBOX邮箱进阶篇–Postfix + Dovecot + Spamassassin + Roundcube Webmail + FairEmail 实现自建邮件伺服器,垃圾邮件过滤以及多设备同步

本文是目前为止本博客上技术难度最高的一篇文章,如果你实在看不懂或者测试通不过的话可以选择放弃。

本文将展示从零开始自己搭建一个Postfix + Dovecot + Spamassassin + Roundcube Webmail邮件伺服器,开启垃圾邮件过滤并实现多设备同步以及一些优化的方法。确实,自建邮件伺服器方法很多,因此限于篇幅以及本人的知识水平,我会展示我所学会的,欢迎各位在评论区交流。

本文将分为 FAQ,系统环境需求,搭建环境,搭建Postfix,搭建Dovecot,搭建Roundcube Webmail并配置NGINX HTTPS反向代理,搭建垃圾邮件过滤系统,生成DKIM记录,启动伺服器并测试,设置多设备同步等篇章,你可以选择你感兴趣的阅读,但请注意,本项目是一个整体,每个组件都不能缺少。

本文写于2020.9.7,最新更新于2020.9.7。

本文不打算重复讲解本站已讲解的内容,请自行阅读,包括但不限于邮箱基础篇,NGINX篇等。


一。 FAQ

鉴于邮件相关的问题实在太多,故本文仅选择和本项目有关并且重要的讲解。

问一: Postfix是什么 ?

答: 一个开源SMTP以及SMTP Daemon软件,主要用于收发邮件(raw mode)。

问二: Dovecot是什么 ?

答: 一个开源IMAP/POP3/LMTP软件(a secure and highly configurable IMAP and POP3 server)。

问三: Roundcube Webmail是什么 ?

答: 基于Web的邮件客户端(Roundcube Webmail is a browser-based multilingual IMAP client with an application-like user interface.)。

问四: FairEmail是什么 ?

答: 开源安卓邮件客户端(Fully featured, open source, privacy oriented email app for Android)。

问五: 为什么只使用IMAP而完全不用POP3 ?

答: POP3不支援标记邮件(已读,未读,spam等)而IMAP支援。

问六: 如何辨别垃圾邮件 ?

答: 本项目使用 Spamassassin + opendkim + postfix-policyd-spf-python + opendmarc等以识别垃圾邮件。

问七: 如何分辨我的ip的25端口(往外)是否被阻断 ?

答: telnet gmail-smtp-in.l.google.com 25 如连接超时,则被阻断。

问八: 邮件如何加密 ?

答: 本项目使用let's encrypt的免费tls证书加密邮件,证书申请具体请看本站的NGINX篇。

问九: 为什么我尝试这个项目但是不能通过测试 ?

答: 本项目是目前本博客上技术难度最高的项目,失败是正常的,而且每个人的os/ip环境等都会或多或少的造成影响。

问十: 使用本项目之前我需要什么软件/环境 ?

答: 你需要首先阅读并理解本博客的NGINX,邮件基础篇以及PHP篇,相关内容本文不再重复。

问十一: 为什么不使用简单一点的方案 ?

答: 选择权永远在你自己手里,你可以自行Google其他方案,本方案我个人作为生产环境使用,你可以看你自己喜好而定。

问十二: 本项目是否可以实现多人使用 ?

答: 可以,但是我不需要也懒得管,因此如确实需要多人使用,请自行搜索postfixadmin等相关教程


二。 系统环境需求

我一般不提这个,但由于本项目的特殊性,我选择加上。

OS : Linux Debian10+/Ubuntu18+

CPU : 1c1t 起步

Ram : 最低1g(重要 !)

ip : 独立公网ip(指ip a里面必须就是公网ip) 且 25/80/143/443/465/587/993 等TCP端口必须保证高可用性

磁碟: 最低10g(推荐SSD,不能是Azure钻石盘!)

TLS证书:请自行阅读NGINX篇申请,本文不再详细涉及。


三。 搭建环境

以下正式开始安装,首先我们需要配置Bash环境,安装LEMPS(Linux NGINX MariaDB HTTPS)环境并安装Git等必备软件。NGINX,PHP篇本站已有,故不再重复。

  1. 鉴于我们需要直接覆写配置文件,故apt-get install时不需要配置。
1
export DEBIAN_FRONTEND=noninteractive
  1. 为了方便起见,本项目设置主密码以及域名等主变量(Bash变量),请自行设置,**必须!!!**。
1
2
3
4
5
password1="yourpasswdhere"
domain="example.com"
mailuser="john"
myip="1.1.1.1"
dist="debian"

myip请自行设置为你的公网ip,dist请填写debian或者ubuntu。

  1. 新建邮件专用Unix user以及密码,即user@domain前面的user部分。
1
2
useradd -m -s /sbin/nologin ${mailuser}
echo -e "${password1}\n${password1}" | passwd ${mailuser}
  1. 安装Git等必需品
1
apt-get install sudo git curl xz-utils wget apt-transport-https gnupg lsb-release unzip resolvconf systemd dbus ca-certificates locales iptables software-properties-common cron less -q -y
  1. 安装MariaDB
1
2
3
curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash
apt-get install mariadb-server -y
apt-get install python-mysqldb -y
1
mysql_secure_installation

mysql_secuer_installation请照抄这里,新安装的话是没有root密码的,直接回车就行。

禁止MariaDB外网访问,此项为安全设置,你可以选择不修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    cat > '/etc/mysql/my.cnf' << EOF
# MariaDB-specific config file.
# Read by /etc/mysql/my.cnf

[client]

default-character-set = utf8mb4

[mysqld]

character-set-server = utf8mb4 #默认使用utf8mb4字符组以防止中文字符乱码
collation-server = utf8mb4_unicode_ci
character_set_server = utf8mb4
collation_server = utf8mb4_unicode_ci
# Import all .cnf files from configuration directory
!includedir /etc/mysql/mariadb.conf.d/
bind-address=127.0.0.1 #禁止外网访问

[mariadb]

userstat = 1
#tls_version = TLSv1.2,TLSv1.3
#ssl_cert = /etc/certs/${domain}_ecc/fullchain.cer
#ssl_key = /etc/certs/${domain}_ecc/${domain}.key
EOF

重启MariaDB使配置生效

1
systemctl restart mariadb

MariaDB安装完成!

  1. 设置伺服器/VPS主机名为你的邮件域名(必须!!!)
1
2
hostnamectl set-hostname ${domain}
echo "${domain}" > /etc/hostname
  1. 配置iptables防火墙
1
2
3
4
5
6
7
8
9
10
iptables -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 143 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 465 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 587 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 993 -j ACCEPT
ip6tables -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
ip6tables -A INPUT -p tcp -m tcp --dport 143 -j ACCEPT
ip6tables -A INPUT -p tcp -m tcp --dport 465 -j ACCEPT
ip6tables -A INPUT -p tcp -m tcp --dport 587 -j ACCEPT
ip6tables -A INPUT -p tcp -m tcp --dport 993 -j ACCEPT

环境安装完成。


搭建Postfix

Postfix作为SMTP以及SMTPD伺服器,是本项目的基础软件之一。

  1. postfix直接apt-get安装即可。
1
apt-get install postfix postfix-pcre postfix-policyd-spf-python -y
  1. 配置alias,这样发给root@domain的邮件就能被自动重定向。
1
2
3
4
5
	cat > '/etc/aliases' << EOF
# See man 5 aliases for format
postmaster: root
root: ${mailuser}
EOF
1
newaliases
  1. 配置postfix主配置文件,为了方便起见,这里选择直接覆写,我会讲解关键的配置,其他请自行查阅Postfix文档
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
	cat > '/etc/postfix/main.cf' << EOF
home_mailbox = Maildir/
smtpd_banner = \$myhostname ESMTP \$mail_name (Debian/GNU)
biff = no
append_dot_mydomain = no
readme_directory = no
compatibility_level = 2
smtpd_tls_loglevel = 1
smtpd_tls_security_level = may
smtpd_tls_received_header = yes
smtpd_tls_eccert_file = /etc/certs/${domain}_ecc/fullchain.cer
smtpd_tls_eckey_file = /etc/certs/${domain}_ecc/${domain}.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:\${data_directory}/smtpd_scache
smtpd_tls_mandatory_ciphers = high
smtpd_tls_mandatory_exclude_ciphers = aNULL
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_dns_support_level=dnssec
smtp_host_lookup = native
smtp_tls_loglevel = 1
smtp_tls_security_level = dane
smtp_tls_mandatory_exclude_ciphers = aNULL
smtp_tls_connection_reuse = no
smtp_tls_eccert_file = /etc/certs/${domain}_ecc/fullchain.cer
smtp_tls_eckey_file = /etc/certs/${domain}_ecc/${domain}.key
smtp_tls_session_cache_database = btree:\${data_directory}/smtp_scache
smtp_tls_mandatory_ciphers = high
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_sasl_type = dovecot
smtpd_sasl_security_options = noanonymous
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_authenticated_header = no
myhostname = ${domain}
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = \$myhostname, ${domain}, localhost.${domain}, localhost
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 ${myip}/32
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = ipv4, ipv6
message_size_limit = 52428800
smtpd_helo_required = yes
disable_vrfy_command = yes
policyd-spf_time_limit = 3600
smtpd_helo_restrictions = permit_mynetworks permit_sasl_authenticated reject_non_fqdn_helo_hostname reject_invalid_helo_hostname reject_unknown_helo_hostname
smtpd_sender_restrictions = permit_mynetworks permit_sasl_authenticated reject_unknown_sender_domain reject_unknown_reverse_client_hostname reject_unknown_client_hostname
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
smtpd_recipient_restrictions = permit_mynetworks,permit_sasl_authenticated,reject_unauth_destination,check_policy_service,unix:private/policyd-spf
milter_default_action = accept
milter_protocol = 6
smtpd_milters = local:opendkim/opendkim.sock,local:opendmarc/opendmarc.sock,local:spamass/spamass.sock
non_smtpd_milters = local:opendkim/opendkim.sock,local:opendmarc/opendmarc.sock,local:spamass/spamass.sock
smtp_header_checks = regexp:/etc/postfix/smtp_header_checks
mailbox_transport = lmtp:unix:private/dovecot-lmtp
smtputf8_enable = no
tls_ssl_options = no_ticket, no_compression
tls_preempt_cipherlist = yes
EOF

配置讲解(以下代码仅供讲解用):

配置tls证书,ecc证书需在配置前面加上ec,rsa证书则为smtpd_tls_cert_file等。

1
2
smtpd_tls_eccert_file = /etc/certs/${domain}_ecc/fullchain.cer
smtpd_tls_eckey_file = /etc/certs/${domain}_ecc/${domain}.key

tls选项:

偏好伺服器cipher

1
tls_preempt_cipherlist = yes

仅启用安全的TLS1.2以及TLS1.3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
smtpd_tls_mandatory_ciphers = high
smtpd_tls_mandatory_exclude_ciphers = aNULL
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_dns_support_level=dnssec
smtp_host_lookup=dns
smtp_tls_loglevel = 1
smtp_tls_security_level = dane
smtp_tls_mandatory_exclude_ciphers = aNULL
smtp_tls_connection_reuse = yes
smtp_tls_eccert_file = /etc/certs/${domain}_ecc/fullchain.cer
smtp_tls_eckey_file = /etc/certs/${domain}_ecc/${domain}.key
smtp_tls_session_cache_database = btree:\${data_directory}/smtp_scache
smtp_tls_mandatory_ciphers = high
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1

禁用TLS1.2 Ticket以及TLS压缩

1
tls_ssl_options = no_ticket, no_compression
  1. 配置Postfix的master.cf配置文件以开启465/587访问,照例直接覆写配置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
	cat > '/etc/postfix/master.cf' << EOF
#
# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: "man 5 master" or
# on-line: http://www.postfix.org/master.5.html).
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (no) (never) (100)
# ==========================================================================
smtp inet n - y - - smtpd
#smtp inet n - y - 1 postscreen
#smtpd pass - - y - - smtpd
#dnsblog unix - - y - 0 dnsblog
#tlsproxy unix - - y - 0 tlsproxy
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_tls_auth_only=yes
-o smtpd_reject_unlisted_recipient=no
-o smtpd_recipient_restrictions=
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
smtps inet n - y - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_reject_unlisted_recipient=no
-o smtpd_recipient_restrictions=
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
#628 inet n - y - - qmqpd
pickup unix n - y 60 1 pickup
cleanup unix n - y - 0 cleanup
qmgr unix n - n 300 1 qmgr
#qmgr unix n - n 300 1 oqmgr
tlsmgr unix - - y 1000? 1 tlsmgr
rewrite unix - - y - - trivial-rewrite
bounce unix - - y - 0 bounce
defer unix - - y - 0 bounce
trace unix - - y - 0 bounce
verify unix - - y - 1 verify
flush unix n - y 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - y - - smtp
relay unix - - y - - smtp
-o syslog_name=postfix/\$service_name
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq unix n - y - - showq
error unix - - y - - error
retry unix - - y - - error
discard unix - - y - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - y - - lmtp
anvil unix - - y - 1 anvil
scache unix - - y - 1 scache
postlog unix-dgram n - n - 1 postlogd
#
# ====================================================================
# Interfaces to non-Postfix software. Be sure to examine the manual
# pages of the non-Postfix software to find out what options it wants.
#
# Many of the following services use the Postfix pipe(8) delivery
# agent. See the pipe(8) man page for information about \${recipient}
# and other message envelope options.
# ====================================================================
#
# maildrop. See the Postfix MAILDROP_README file for details.
# Also specify in main.cf: maildrop_destination_recipient_limit=1
#
maildrop unix - n n - - pipe
flags=DRhu user=vmail argv=/usr/bin/maildrop -d \${recipient}
#
# ====================================================================
#
# Recent Cyrus versions can use the existing "lmtp" master.cf entry.
#
# Specify in cyrus.conf:
# lmtp cmd="lmtpd -a" listen="localhost:lmtp" proto=tcp4
#
# Specify in main.cf one or more of the following:
# mailbox_transport = lmtp:inet:localhost
# virtual_transport = lmtp:inet:localhost
#
# ====================================================================
#
# Cyrus 2.1.5 (Amos Gouaux)
# Also specify in main.cf: cyrus_destination_recipient_limit=1
#
#cyrus unix - n n - - pipe
# user=cyrus argv=/cyrus/bin/deliver -e -r \${sender} -m \${extension} \${user}
#
# ====================================================================
# Old example of delivery via Cyrus.
#
#old-cyrus unix - n n - - pipe
# flags=R user=cyrus argv=/cyrus/bin/deliver -e -m \${extension} \${user}
#
# ====================================================================
#
# See the Postfix UUCP_README file for configuration details.
#
uucp unix - n n - - pipe
flags=Fqhu user=uucp argv=uux -r -n -z -a\$sender - \$nexthop!rmail (\$recipient)
#
# Other external delivery methods.
#
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/lib/bsmtp/bsmtp -t\$nexthop -f\$sender \$recipient
scalemail-backend unix - n n - 2 pipe
flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store \${nexthop} \${user} \${extension}
mailman unix - n n - - pipe
flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
\${nexthop} \${user}

policyd-spf unix - n n - 0 spawn
user=policyd-spf argv=/usr/bin/policyd-spf
EOF

以下为配置讲解(以下代码仅供讲解用):

开启465/587访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
submission inet n       -       y       -       -       smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_tls_auth_only=yes
-o smtpd_reject_unlisted_recipient=no
-o smtpd_recipient_restrictions=
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
smtps inet n - y - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_reject_unlisted_recipient=no
-o smtpd_recipient_restrictions=
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING

开启SPF验证,具体请看垃圾邮件过滤篇。

1
2
policyd-spf  unix  -       n       n       -       0       spawn
user=policyd-spf argv=/usr/bin/policyd-spf
  1. 设置mailname
1
echo ${domain} > /etc/mailname

Postfix安装并配置完成!


搭建Dovecot

  1. 添加APT源并安装Dovecot
1
2
3
4
5
curl https://repo.dovecot.org/DOVECOT-REPO-GPG | gpg --import
gpg --export ED409DA1 > /etc/apt/trusted.gpg.d/dovecot.gpg
echo "deb https://repo.dovecot.org/ce-2.3-latest/${dist}/$(lsb_release -cs) $(lsb_release -cs) main" > /etc/apt/sources.list.d/dovecot.list
apt-get update
apt-get install dovecot-core dovecot-imapd dovecot-lmtpd dovecot-sieve -y
  1. 将Dovecot用户添加到Mail组
1
adduser dovecot mail
  1. 配置Dovecot

为了方便起见,照例覆写配置文件。

1
2
3
4
5
6
	cat > '/etc/dovecot/conf.d/10-auth.conf' << EOF
auth_username_format = %Ln
disable_plaintext_auth = no
auth_mechanisms = plain
!include auth-system.conf.ext
EOF
1
2
3
4
5
6
7
8
9
10
	cat > '/etc/dovecot/conf.d/10-ssl.conf' << EOF
ssl = required
ssl_cert = </etc/certs/${domain}_ecc/fullchain.cer
ssl_key = </etc/certs/${domain}_ecc/${domain}.key
#ssl_dh = </usr/local/etc/trojan/dh.pem
#ssl_cipher_list = ${cipher_server}
ssl_min_protocol = TLSv1.2
ssl_prefer_server_ciphers = yes
ssl_options = no_ticket
EOF

强制非本机ip(非localhost)使用tls/ssl连线。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
	cat > '/etc/dovecot/conf.d/10-master.conf' << EOF
service imap-login {
inet_listener imap {
#port = 143
}
inet_listener imaps {
#port = 993
#ssl = yes
}
}

service submission-login {
inet_listener submission {
#port = 587
}
}

service imap {
# Most of the memory goes to mmap()ing files. You may need to increase this
# limit if you have huge mailboxes.
#vsz_limit = $default_vsz_limit

# Max. number of IMAP processes (connections)
#process_limit = 1024
}

service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}

service submission {
# Max. number of SMTP Submission processes (connections)
#process_limit = 1024
}

service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}

}

service auth-worker {
#user = root
}

service dict {
unix_listener dict {
#mode = 0600
#user =
#group =
}
}

service stats {
unix_listener stats {
user = netdata
group = netdata
mode = 0666
}
}
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat > '/etc/dovecot/conf.d/10-mail.conf' << EOF

mail_location = maildir:~/Maildir

namespace inbox {
inbox = yes
}

mail_privileged_group = mail

protocol !indexer-worker {
#mail_vsize_bg_after_count = 0
}
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
	cat > '/etc/dovecot/conf.d/15-mailboxes.conf' << EOF
namespace inbox {
mailbox Archive {
auto = subscribe
special_use = \Archive
}
mailbox Drafts {
auto = subscribe
special_use = \Drafts
}
mailbox Junk {
auto = subscribe
special_use = \Junk
}
mailbox Trash {
auto = subscribe
special_use = \Trash
}
mailbox Sent {
auto = subscribe
special_use = \Sent
}
}
EOF
1
2
3
4
5
6
	cat > '/etc/dovecot/conf.d/15-lda.conf' << EOF
protocol lda {
# Space separated list of plugins to load (default is global mail_plugins).
mail_plugins = \$mail_plugins sieve
}
EOF
1
2
3
4
5
6
	cat > '/etc/dovecot/conf.d/20-lmtp.conf' << EOF
protocol lmtp {
# Space separated list of plugins to load (default is global mail_plugins).
mail_plugins = \$mail_plugins quota sieve
}
EOF
1
2
3
4
5
6
	cat > '/etc/dovecot/conf.d/90-sieve.conf' << EOF
plugin {
sieve = file:~/sieve;active=~/.dovecot.sieve
sieve_before = /var/mail/SpamToJunk.sieve
}
EOF

以下为配置讲解(以下代码仅供讲解用):

定义收件箱,垃圾箱等并全自动启用

1
2
3
4
mailbox Archive {
auto = subscribe
special_use = \Archive
}

启用TLS

1
2
3
4
5
6
7
8
ssl = yes
ssl_cert = </etc/certs/${domain}_ecc/fullchain.cer
ssl_key = </etc/certs/${domain}_ecc/${domain}.key
#ssl_dh = </usr/local/etc/trojan/dh.pem
#ssl_cipher_list = ${cipher_server}
ssl_min_protocol = TLSv1.2
ssl_prefer_server_ciphers = yes
ssl_options = no_ticket

垃圾邮件分流(具体请看垃圾邮件过滤篇):

1
2
3
4
5
6
7
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}

Dovecot安装并配置完成!


搭建Roundcube Webmail并配置NGINX HTTPS反向代理

  1. 获取最新版本号
1
mailver=$(curl -s "https://api.github.com/repos/roundcube/roundcubemail/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
  1. 下载并安装最新版Roundcube Webmail
1
2
3
4
5
6
7
8
9
10
11
cd /usr/share/nginx/
rm -rf /usr/share/nginx/roundcubemail
wget --no-check-certificate https://github.com/roundcube/roundcubemail/releases/download/${mailver}/roundcubemail-${mailver}-complete.tar.gz
tar -xvf roundcubemail-${mailver}-complete.tar.gz
rm -rf roundcubemail-${mailver}-complete.tar.gz
mv /usr/share/nginx/roundcubemail*/ /usr/share/nginx/roundcubemail/
chown -R nginx:nginx /usr/share/nginx/roundcubemail/
cd /usr/share/nginx/roundcubemail/
curl -s https://getcomposer.org/installer | php
cp -f composer.json-dist composer.json
php composer.phar install --no-dev
  1. 配置MariaDB
1
mysql -u root
1
2
3
4
5
CREATE DATABASE roundcubemail DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER roundcube@localhost IDENTIFIED BY '${password1}';
GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost;
flush privileges;
EXIT;

初始化数据库

1
mysql -u roundcube -p"${password1}" -D roundcubemail < /usr/share/nginx/roundcubemail/SQL/mysql.initial.sql
  1. 配置Roundcube Webmail

生成deskey

1
deskey=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9-_#&!*%?' | fold -w 24 | head -n 1)

写入主配置(更多自定义配置请看这里)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
	cat > '/usr/share/nginx/roundcubemail/config/config.inc.php' << EOF
<?php

\$config['language'] = 'zh_TW';
\$config['db_dsnw'] = 'mysql://roundcube:${password1}@unix(/run/mysqld/mysqld.sock)/roundcubemail';
\$config['default_host'] = '${domain}';
\$config['default_port'] = 143;
\$config['smtp_server'] = '127.0.0.1';
\$config['smtp_port'] = 25;
\$config['support_url'] = 'https://github.com/johnrosen1/vpstoolbox';
\$config['product_name'] = 'Roundcube Webmail For VPSTOOLBOX';
\$config['des_key'] = '${deskey}';
\$config['ip_check'] = true;
\$config['enable_installer'] = false;
\$config['identities_level'] = 3;

// ----------------------------------
// PLUGINS
// ----------------------------------
// List of active plugins (in plugins/ directory)
\$config['plugins'] = array('archive','emoticons','enigma','markasjunk','newmail_notifier','zipdownload');
\$config['newmail_notifier_basic'] = true;
\$config['newmail_notifier_desktop'] = true;
\$config['enigma_pgp_homedir'] = '/usr/share/nginx/pgp/';
\$config['enigma_encryption'] = true;
\$config['enigma_signatures'] = true;
\$config['enigma_decryption'] = true;
\$config['enigma_sign_all'] = true;
EOF

新建pgp文件夹

1
mkdir /usr/share/nginx/pgp/

删除installer文件夹(此项为安全设置)

1
rm -rf /usr/share/nginx/roundcubemail/installer/
  1. 配置NGINX反向代理(HTTPS等请看NGINX篇)
1
sudo nano /etc/nginx/conf.d/default.conf

添加一个location

1
2
3
4
5
6
7
8
9
10
11
12
13
location /${password1}_webmail/ {
#access_log off;
client_max_body_size 0;
index index.php;
alias /usr/share/nginx/roundcubemail/;
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_param HTTPS on;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $request_filename;
}
}

Roundcube Webmail安装完成 !


搭建垃圾邮件过滤系统

垃圾邮件过滤是必不可少的系统,没人希望收件箱里堆满垃圾邮件。

本项目使用Spamassassin+opendkim+postfix-policyd-spf-python+opendmarc过滤垃圾邮件(DKIM,SPF,DMARC验证加Spamassassin)。

  1. 安装并配置 Spamassassin
1
apt-get install spamassassin spamc spamass-milter -y

将Spamassassin加入mail组

1
2
adduser debian-spamd mail
adduser spamass-milter mail

启用Spamassassin规则全自动更新

1
sed -i 's/CRON=0/CRON=1/' /etc/default/spamassassin

配置Spamassassin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
	cat > '/etc/default/spamass-milter' << EOF
# spamass-milt startup defaults

# OPTIONS are passed directly to spamass-milter.
# man spamass-milter for details

# Non-standard configuration notes:
# See README.Debian if you use the -x option with sendmail
# You should not pass the -d option in OPTIONS; use SOCKET for that.

# Default, use the spamass-milter user as the default user, ignore
# messages from localhost
OPTIONS="-u spamass-milter -i 127.0.0.1"

# Reject emails with spamassassin scores > 15.
OPTIONS="\${OPTIONS} -r 8"

# Do not modify Subject:, Content-Type: or body.
#OPTIONS="\${OPTIONS} -m"

######################################
# If /usr/sbin/postfix is executable, the following are set by
# default. You can override them by uncommenting and changing them
# here.
######################################
SOCKET="/var/spool/postfix/spamass/spamass.sock"
SOCKETOWNER="postfix:postfix"
SOCKETMODE="0660"
######################################
EOF

启动Spamassassin并设置开机自启

1
2
systemctl enable spamassassin
systemctl restart spamassassin
  1. 安装并配置OpenDKIM
1
2
apt-get install opendkim opendkim-tools -y
gpasswd -a postfix opendkim

配置OpenDKIM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
	cat > '/etc/opendkim.conf' << EOF
Syslog yes
UMask 007
Canonicalization relaxed/simple
Mode sv
SubDomains no
AutoRestart yes
AutoRestartRate 10/1M
Background yes
DNSTimeout 5
SignatureAlgorithm rsa-sha256
Socket local:/var/spool/postfix/opendkim/opendkim.sock
PidFile /var/run/opendkim/opendkim.pid
OversignHeaders From
TrustAnchorFile /usr/share/dns/root.key
UserID opendkim
KeyTable refile:/etc/opendkim/key.table
SigningTable refile:/etc/opendkim/signing.table
ExternalIgnoreList /etc/opendkim/trusted.hosts
InternalHosts /etc/opendkim/trusted.hosts
Nameservers 1.1.1.1
EOF
1
2
3
4
5
6
7
8
	cat > '/etc/default/opendkim' << EOF
RUNDIR=/var/run/opendkim
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
USER=opendkim
GROUP=opendkim
PIDFILE=\$RUNDIR/\$NAME.pid
EXTRAAFTER=
EOF

重启opendkim使配置生效

1
2
systemctl enable opendkim
systemctl restart opendkim

DKIM记录生成请看专门的生成篇。

  1. 安装并配置postfix-policyd-spf-python
1
apt-get install postfix-policyd-spf-python -y

开启SPF验证/etc/postfix/master.cf

1
2
policyd-spf  unix  -       n       n       -       0       spawn
user=policyd-spf argv=/usr/bin/policyd-spf
  1. 安装并配置opendmarc
1
apt-get install opendmarc -y

配置opendmarc

1
2
3
4
5
6
sed -i 's/Socket local:\/var\/run\/opendmarc\/opendmarc.sock/Socket local:\/var\/spool\/postfix\/opendmarc\/opendmarc.sock/' /etc/opendmarc.conf
sed -i 's/SOCKET=local:\$RUNDIR\/opendmarc.sock/SOCKET=local:\/var\/spool\/postfix\/opendmarc\/opendmarc.sock/' /etc/default/opendmarc
mkdir -p /var/spool/postfix/opendmarc
chown opendmarc:opendmarc /var/spool/postfix/opendmarc -R
chmod 750 /var/spool/postfix/opendmarc/ -R
adduser postfix opendmarc

启动opendmarc

1
2
systemctl enable opendmarc
systemctl restart opendmarc
  1. 配置sieve规则
1
2
3
4
5
6
	cat > '/etc/dovecot/conf.d/90-sieve.conf' << EOF
plugin {
sieve = file:~/sieve;active=~/.dovecot.sieve
sieve_before = /var/mail/SpamToJunk.sieve
}
EOF
1
2
3
4
5
6
7
8
9
	cat > '/var/mail/SpamToJunk.sieve' << EOF
require "fileinto";

if header :contains "X-Spam-Flag" "YES"
{
fileinto "Junk";
stop;
}
EOF
1
sievec /var/mail/SpamToJunk.sieve
  1. 配置Fail2ban规则(安全设置,可选)
1
2
3
4
	cat > '/etc/fail2ban/filter.d/dovecot-pop3imap.conf' << EOF
[Definition]
failregex = (?: pop3-login|imap-login): .*(?:Authentication failure|Aborted login \(auth failed|Aborted login \(tried to use disabled|Disconnected \(auth failed|Aborted login \(\d+ authentication attempts).*rip=`<HOST>`
EOF
1
2
3
4
5
6
7
8
echo "[dovecot-pop3imap]" >> /etc/fail2ban/jail.conf
echo "enabled = true" >> /etc/fail2ban/jail.conf
echo "filter = dovecot-pop3imap" >> /etc/fail2ban/jail.conf
echo "action = iptables-multiport[name=dovecot-pop3imap, port="pop3,imap", protocol=tcp]" >> /etc/fail2ban/jail.conf
echo "logpath = /var/log/mail.log" >> /etc/fail2ban/jail.conf
echo "maxretry = 3" >> /etc/fail2ban/jail.conf
echo "findtime = 1200" >> /etc/fail2ban/jail.conf
echo "bantime = 1200" >> /etc/fail2ban/jail.conf
1
systemctl restart fail2ban

生成DKIM记录

1
2
3
4
5
6
mkdir /etc/opendkim/
mkdir /etc/opendkim/keys/
chown -R opendkim:opendkim /etc/opendkim
chmod go-rw /etc/opendkim/keys
echo "*@${domain} default._domainkey.${domain}" > /etc/opendkim/signing.table
echo "default._domainkey.${domain} ${domain}:default:/etc/opendkim/keys/${domain}/default.private" > /etc/opendkim/key.table
1
2
3
4
5
6
7
8
9
	cat > '/etc/opendkim/trusted.hosts' << EOF
127.0.0.1
localhost
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16

*.${domain}
EOF
1
2
3
4
5
mkdir /etc/opendkim/keys/${domain}/
opendkim-genkey -b 2048 -d ${domain} -D /etc/opendkim/keys/${domain} -s default -v
chown opendkim:opendkim /etc/opendkim/keys/${domain}/default.private
mkdir /var/spool/postfix/opendkim/
chown opendkim:postfix /var/spool/postfix/opendkim

DKIM记录生成完成,重启opendkim使配置生效

1
systemctl restart opendkim

将DKIM记录添加到DNS解析中请看基础篇,SPF记录填写v=spf1 mx ip4:${myip} a ~all即可。


启动伺服器并测试

伺服器均配置完成,现重启各个服务模块并启动测试。

1
systemctl restart postfix dovecot

判断各个服务组件是否正常运行

1
2
3
4
5
6
7
8
systemctl status postfix
systemctl status dovecot
systemctl status opendkim
systemctl status opendmarc
systemctl status spamassassin
systemctl status mariadb
systemctl status nginx
systemctl status php7.4-fpm

判断端口是否正常开放

1
2
3
4
5
6
7
ss -tulpn | grep 80
ss -tulpn | grep 443
ss -tulpn | grep 25
ss -tulpn | grep 143
ss -tulpn | grep 465
ss -tulpn | grep 587
ss -tulpn | grep 993

如未正常开放,则你的配置有问题,请自行检查。

若所有服务以及端口皆正常可用,则进行下一步–邮件收发测试。

登录https://${domain}/${password1}_webmail/,用户名为${mailuser},密码为${password1},测试登录。

登录成功,则进行邮件收发测试。

发件测试,收件测试本文不详细涉及。

MX记录等基础篇已讲解的本文不再涉及。


设置多设备同步

下载并安装FairEmail

按照快速安装步骤配置即可。

SMTP/IMAP伺服器均为${domain},加密方法请选择 SSL/TLS而不是STARTTLS,端口默认即可,登录账户和密码均和Roundcube Webmail的一样。

如配置成功,则多设备同步已开启。


后记

本项目确实花费了我很多的时间和精力完成,但是不管各种各样的劝退方法,包括但不限于不完善的文档,缺少中文文献,困难的Debug等,不过最终我还是做到了,没有任何妥协,VPMS(Virtual Private Mail Server)真香 !


效果图

发件测试图

发件测试图

Gmail收件实测,发自本项目建成的伺服器

Gmail发件

Roundcube Webmail收件实测,发自Gmail

Roundcube Webmail收件


特别感谢以下文章对本项目提供的支援

  1. Build Your Own Email Server on Ubuntu: Basic Postfix Setup系列文章
  2. Postfix文档
  3. Dovecot文档
  4. OpenDKIM文档
  5. OpenDMARC文档
  6. Debian10使用Postfix+Dovecot+Roundcube搭建邮件服务器