Maddy
Maddy Mail Server implements all functionality required to run a e-mail server. It can send messages via SMTP (works as MTA), accept messages via SMTP (works as MX) and store messages while providing access to them via IMAP. In addition to that it implements auxiliary protocols that are mandatory to keep email reasonably secure (DKIM, SPF, DMARC, DANE, MTA-STS). It replaces Postfix, Dovecot, OpenDKIM, OpenSPF, OpenDMARC and more with one daemon with uniform configuration and minimal maintenance cost.
Rainloop Webmail
Modest system requirements, decent performance, simple installation and upgrade,no database required - all these make RainLoop Webmail a perfect choice for your email solution.
📄准备
- ✅ 一台VPS,支持开启25端口和rDNS(我使用的是Crunchbits的是$1.89/m [WA] 4.5GB Yearly SSD VPS [PROMO])
- ✅ 一个域名,支持管理A/AAAA记录、MX记录、TXT记录等
- ✅ 邮箱域名的证书和密钥(可以使用Certbot申请)
🔧安装docker和docker compose
这里使用docker compose来部署rainloop Webmai+Maddy,docker和docker compose安装教程省略
创建docker-compose.yml 的配置
1mkdir mail/
2cd mail/
3nano docker-compose.yml
docker-compose.yml 的配置如下:
1services:
2
3 maddy:
4 image: foxcpp/maddy:latest
5 container_name: maddy
6 restart: unless-stopped
7 volumes: #mount point
8 - ./maddy:/data
9 - /etc/letsencrypt/live/mail.example.com/fullchain.pem:/data/local_certs/cert.pem:ro #邮箱域名的证书挂载到docker内
10 - /etc/letsencrypt/live/mail.example.com/privkey.pem:/data/local_certs/key.pem:ro #邮箱域名的密钥挂载docker内
11 ports:
12 - 25:25/tcp
13 - 465:465/tcp
14 - 993:993/tcp
15
16 rainloop:
17 image: php:fpm-alpine3.15
18 container_name: rainloop
19 restart: unless-stopped
20 volumes:
21 - ./rainloop:/var/www/html
22 ports:
23 - 127.0.0.1:9000:9000
24 logging:
25 driver: json-file
26 options:
27 max-size: "1m"
28 max-file: "10"
🔎安装RainLoop Webmail
1cd ~/mail/
2mkdir rainloop/
3wget https://www.rainloop.net/repository/webmail/rainloop-latest.zip
4unzip rainloop-latest.zip
Nginx反代RainLoop Webmail
1server {
2 server_name mail.example.com;
3 listen 443 ssl http2;
4 listen [::]:443 ssl http2;
5 ssl_certificate /data/certs/fullchain.pem; #邮箱域名的证书
6 ssl_certificate_key /data/certs/cert.pem; #邮箱域名的密钥
7
8 access_log /var/log/nginx/access_mail.log;
9 error_log /var/log/nginx/error_mail.log;
10
11 root /data/rainloop/;
12 index index.php;
13
14 location ~ \.php$ {
15 root /var/www/html;
16 fastcgi_pass 127.0.0.1:9000;
17 fastcgi_index index.php;
18 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
19 include fastcgi_params;
20 }
21
22 location ^~ /data {
23 deny all; #用户无法通过 Internet 直接访问rainloop目录
24 }
25}
💡配置Maddy
1cd ~/mail/
2mkdir maddy/
3nano maddy.conf
Maddy.conf配置如下:
1# 预设了三个变量,方便后续使用
2$(hostname) = mail.example.com #外界通过这个域名找到你的邮件服务器。
3$(primary_domain) = example.com #你的邮箱 @后面的域名
4$(local_domains) = $(primary_domain)
5
6# 如果要使用 nginx 反代,这里可以选择 tls off,但如此一来没法生成 dkim 密钥对
7# 在之后检查时日志内会有安全警告,故推荐直接用 maddy 管理
8# tls off
9#tls file /etc/letsencrypt/live/$(local_domains)/fullchain.pem /etc/letsencrypt/live/$(local_domains)/privkey.pem
10tls file /data/local_certs/cert.pem /data/local_certs/key.pem
11
12# 数据用 SQLite3 存储较为简单、轻量
13auth.pass_table local_authdb {
14 table sql_table {
15 driver sqlite3
16 dsn credentials.db
17 table_name passwords
18 }
19}
20
21storage.imapsql local_mailboxes {
22 driver sqlite3
23 dsn imapsql.db
24}
25
26# ----------------------------------------------------------------------------
27# SMTP endpoints + message routing
28
29hostname $(hostname)
30
31table.chain local_rewrites {
32 optional_step regexp "(.+)\+(.+)@(.+)" "$1@$3"
33 optional_step static {
34 entry postmaster postmaster@$(primary_domain)
35 }
36 optional_step file /data/aliases
37}
38
39msgpipeline local_routing {
40 destination postmaster $(local_domains) {
41 modify {
42 replace_rcpt &local_rewrites
43 }
44
45 deliver_to &local_mailboxes
46 }
47
48 default_destination {
49 reject 550 5.1.1 "User doesn't exist"
50 }
51}
52
53# smtp 使用 25 号端口发送邮件
54smtp tcp://[::]:25 {
55 # tls self_signed
56 limits {
57 # Up to 20 msgs/sec across max. 10 SMTP connections.
58 all rate 20 1s
59 all concurrency 10
60 }
61
62 dmarc yes
63 check {
64 require_mx_record
65 dkim # 若无则不检查
66 spf
67 }
68
69 source $(local_domains) {
70 reject 501 5.1.8 "Use Submission for outgoing SMTP"
71 }
72 default_source {
73 destination postmaster $(local_domains) {
74 deliver_to &local_routing
75 }
76 default_destination {
77 reject 550 5.1.1 "User doesn't exist"
78 }
79 }
80}
81
82# 如果使用 nginx 反代则这里监听到本地端口即可 tcp://127.0.0.1:587
83# 不使用则邮件客户端以 SSL/TLS 方式直接访问该地址
84submission tls://[::]:465 {
85 limits {
86 # Up to 50 msgs/sec across any amount of SMTP connections.
87 all rate 50 1s
88 }
89
90 auth &local_authdb
91
92 source $(local_domains) {
93 check {
94 authorize_sender {
95 prepare_email &local_rewrites
96 user_to_email identity
97 }
98 }
99
100 destination postmaster $(local_domains) {
101 deliver_to &local_routing
102 }
103 default_destination {
104 modify {
105 dkim $(primary_domain) $(local_domains) default
106 }
107 deliver_to &remote_queue
108 }
109 }
110 default_source {
111 reject 501 5.1.8 "Non-local sender domain"
112 }
113}
114
115target.remote outbound_delivery {
116 limits {
117 # Up to 20 msgs/sec across max. 10 SMTP connections
118 # for each recipient domain.
119 destination rate 20 1s
120 destination concurrency 10
121 }
122 mx_auth {
123 dane
124 mtasts {
125 cache fs
126 fs_dir mtasts_cache/
127 }
128 local_policy {
129 min_tls_level encrypted
130 min_mx_level none
131 }
132 }
133}
134
135target.queue remote_queue {
136 target &outbound_delivery
137
138 autogenerated_msg_domain $(primary_domain)
139 bounce {
140 destination postmaster $(local_domains) {
141 deliver_to &local_routing
142 }
143 default_destination {
144 reject 550 5.0.0 "Refusing to send DSNs to non-local addresses"
145 }
146 }
147}
148
149# ----------------------------------------------------------------------------
150# IMAP endpoints
151# 同上,使用 nginx 反代则改为监听本地端口 tcp://127.0.0.1:143
152imap tls://[::]:993 {
153 auth &local_authdb
154 storage &local_mailboxes
155}
💻启动Maddy和Rainloop Webmail
1cd ~/mail
2docker compose upgrade -d
Maddy创建用户
1docker exec -it maddy sh
2maddy creds create [email protected] #创建邮箱
3maddy imap-acct create [email protected]
获取DKIM的公钥
1cat data/dkim_keys/*.dns
然后出现这段代码
"v=DKIM1; k=ed25519; p=nAcUUozPlhc4VPhp7hZl+owES7j7OlEv0laaDEDBAqg="
将其复制保存,将在设置DNS记录使用
设置DNS记录(域名服务商处设置)
以mail.example.com为邮件服务器的域名为例
# A 记录
mail.example.com A 10.2.3.4
mail.example.com AAAA 2001:beef::1
# MX 记录
example.com MX mail.example.com
# CNAME 记录
smtp.example.com CNAME mail.example.com
imap.example.com CNAME mail.example.com
# SPF
example.com TXT "v=spf1 mx ~all"
# _dmarc
_dmarc.example.com TXT "v=DMARC1; p=quarantine; ruf=mailto:[email protected]"
# DKIM DNS记录
default._domainkey.example.com TXT "v=DKIM1; k=ed25519; p=nAcUUozPlhc4VPhp7hZl+owES7j7OlEv0laaDEDBAqg="
🔋登陆Rainloop Webmail
通过邮箱域名登陆Rainloop Webmail后台控制面板
mail.example.com?admin
账号:admin
密码:12345
通过Rainloop Webmail控制面板与Maddy邮件服务器连接
- 点击“域名”
- 点击“添加域名”
- 输入
- 名字:example.com
- IMAP/SMTP服务器:mail.example.com
- 加密:SSL/TLS
- 点击“添加”
登陆Rainloop Webmail
mail.example.com
测试是否能收发邮件
⚠️注意
- 选择SSL/TLS加密,防火墙需要放行端口:465/tcp 993/tcp
- 垃圾邮件匹配度 根据得分低问题去修改,否则发送的邮件容易进垃圾箱
- MxtoolBox 可以查询MX记录,DKIM等用于检查是否配置正确