前不久其实已经在另一台机器搭建过,但是当时没有记录,这次刚好那台机器到期也不续费了,索性重新搭建一遍并记录下来
Mailcow介绍和搭建准备
Mailcow是一个功能很齐全,体量也相对较大的邮局服务,支持Docker自托管
服务器要求(官方):
支持KVM、ESX、Hyper-V等全虚拟化平台,不支持OpenVZ、Virtuozzo和LXC
开放25号端口
处理器:1Ghz
内存:最小6G+1G Swap(部署完后实际大概占用4G左右内存,越大越好)
磁盘:20G(越大越好)
架构:x86_64, ARM64(新发布,可能存在问题)
Mailcow主要是比较吃内存,最好部署在内存较大的服务器上,如果你想减少对内存的占用可以尝试通过在mailcow.conf中设置SKIP_CLAMD=y和SKIP_SOLR=y来禁用这两个比较吃内存的服务
Mailcow使用的TCP端口:25|80|110|143|443|465|587|993|995|4190
在搭建前尤其要测试自己服务器的25号端口的流量是否能够出站,因为目前许多IDC默认是屏蔽了25端口的出站流量,如果被屏蔽了可以发工单询问是否可以解除限制(PS:有些IDC就是不允许,发工单也没用)
可以使用telnet smtp.outlook.com 25测试25端口流量是否能顺利出站,一般返回220就表示没有问题:
$ telnet smtp.outlook.com 25
Trying 52.98.252.98...
Connected to smtp.outlook.com.
Escape character is '^]'.
220 FR4P281CA0131.outlook.office365.com Microsoft ESMTP MAIL Service ready at Sun, 21 Apr 2024 08:42:46 +0000
Mailcow搭建
NTP时间同步
执行timedatectl status查看服务器是否启动了NTP服务,显示如下的话就证明已启动:
System clock synchronized: yes
NTP service: active
如果没有启动NTP服务,则需要执行timedatectl set-ntp true来启动,若提示Failed to set ntp: NTP not supported的话则需要先安装chrony这个NTP服务
$ apt install chrony
$ systemctl status chrony # 检查一下服务是否正常启动
$ systemctl enable chrony # 设置自启动
$ timedatectl set-ntp true # 启用NTP
安装后再执行timedatectl status检查一下,一般就没问题了
rDNS
reverse DNS(rDNS),指的是反向DNS,就是让你的ip解析到邮件服务器的域名(例如mail.example.com),设置这个能提高你的可信度,让你发的邮件有更大的概率进入收件箱而不是垃圾桶
rDNS是由你的VPS提供商提供的,一般在控制面板里设置,以Netcup为例:

设置完后可以通过nslookup server_ip来查看是否生效(可能需要点时间)
DNS记录
按下面所示设置好DNS记录:
注意我们邮件服务器的域名是
mail.example.com,但是也要将example.com(@)解析到邮件服务器的ipdkim._domainkey值中的p需要我们部署完后再填写_dmarc值p参数表示对于失败的DMARC检查应该采取什么措施,可以设置为以下三个值之一:none: 仅发送DMARC报告,不执行任何其他操作(宽松)quarantine: 将失败的邮件发送到垃圾邮件文件夹reject: 直接拒绝并丢弃失败的邮件(严格)
mailto:mailauth-reports@example.org可以填写一个我们自己的常用邮箱即可
docker-compose部署服务端
需要确保服务器已经安装了docker和docker-compose
执行umask命令确保输出0022(默认一般都是这个值)
创建存放容器的目录,然后拉取官方项目目录并进入
$ mkdir /docker
$ cd /docker
$ git clone https://github.com/mailcow/mailcow-dockerized
$ cd mailcow-dockerized
执行./generate_config.sh脚本初始化Mailcow并生成配置文件,执行后会要求我们填写邮件服务器域名,也就是之前A记录设置的mail.example.com,时区的话就选择Asia/Shanghai,分支的话选择主分支master branch
执行脚本后生成的mailcow.conf就是配置文件,我们可以打开按照自己需要修改一些配置,如果我们使用反向代理的话可以修改:
HTTP_PORT=8080
HTTP_BIND=127.0.0.1
HTTPS_PORT=8443
HTTPS_BIND= 127.0.0.1
然后依次执行docker-compose pull和docker-compose up -d就搭建好了
Nginx反代
先为我们的服务器申请一个SSL证书:
$ certbot certonly --standalone --agree-tos -d mail.example.com
确保系统已经安装了Nginx,然后进入配置文件目录/etc/nginx/conf.d新建一个配置为mailcow.conf,写入下面内容,注意把域名改为自己的邮件服务器域名:
server {
listen 80;
listen [::]:80;
server_name mail.example.com autodiscover.* autoconfig.*;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name mail.example.com autodiscover.* autoconfig.*;
ssl_certificate /etc/letsencrypt/live/mail.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mail.example.com/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# See https://ssl-config.mozilla.org/#server=nginx for the latest ssl settings recommendations
# An example config is given below
ssl_protocols TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5:!SHA1:!kRSA;
ssl_prefer_server_ciphers off;
location /Microsoft-Server-ActiveSync {
proxy_pass http://127.0.0.1:8080/Microsoft-Server-ActiveSync;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 75;
proxy_send_timeout 3650;
proxy_read_timeout 3650;
proxy_buffers 64 512k; # Needed since the 2022-04 Update for SOGo
client_body_buffer_size 512k;
client_max_body_size 0;
}
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 0;
# The following Proxy Buffers has to be set if you want to use SOGo after the 2022-04 (April 2022) Update
# Otherwise a Login will fail like this: https://github.com/mailcow/mailcow-dockerized/issues/4537
proxy_buffer_size 128k;
proxy_buffers 64 512k;
proxy_busy_buffers_size 512k;
}
}
然后systemctl start nginx就完成了
登录并配置服务端管理面板
登录https://mail.example.com进入管理页面,默认用户名为admin,密码为moohoo
登陆后最好赶紧修改密码以及添加两步验证,点击右上角System-Configuration,我这里已经修改好了

点击右上角E-Mail-Configuration,找到Add Domain添加域,Domain设置为example.com(注意不是mail.example.com),然后点击最下面Add domain and restart SOGo

点击右上角System-Configuration,找到Options-ARC/DKIM keys点击进入,复制右面的Private Key,填入我们前面配置DNS记录时dkim._domainkey的值

至此,Mailcow服务端基本配置就完成了
最后,点击右上角E-Mail-Configuration,点击页面的Mailboxes找到Add mailbox就可以添加账户了,登陆的话可以直接访问https://mail.example.com找到Webmail点进去登录即可

去Mail-tester测试一下
可以去Mail-tester这个网站测试一下,我的显示7.9/10分,主要扣分是因为域名注册时间太短,不是大问题

客户端配置
如果想在其他客户端登录邮箱可以按照下面协议和对应端口配置即可:
解决无法收信的问题
经测试发现发邮件没太大问题,但是经常收不到邮件,最后发现是被RSPAMD这个服务认为是垃圾邮件给拒收了
解决方法是首先登录管理面板,点击右上角System-Configuration,找到Access-Rspamd UI点击进入

进入Rspamd UI面板后,点击History就可以看到所有的收发邮件记录
我们需要点击Configuration,把greylist、addheader、reject这三个值设置大一点,保存再测试一下基本就没问题了

数据备份
Mailcow提供了自己的备份脚本(/docker/mailcow-dockerized/helper-scripts/backup_and_restore.sh),使用方法如下:
# Syntax:
/docker/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup (vmail|crypt|redis|rspamd|postfix|mysql|all|--delete-days)
# Backup all, delete backups older than 3 days
/docker/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup all --delete-days 3
# Backup vmail, crypt and mysql data, delete backups older than 30 days
/docker/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup vmail crypt mysql --delete-days 30
# Backup vmail
/docker/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup vmail
# MULTITHREADING
THREADS=14 /docker/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup all
# BACKUP PATH
MAILCOW_BACKUP_LOCATION=/tmp /docker/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup all
# MULTITHREADING + BACKUP PATH
MAILCOW_BACKUP_LOCATION=/opt/backup THREADS=14 /opt/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup all
这里我是设置定时任务执行脚本并使用rclone上传到我的网盘,rclone的配置还是比较简单的就不在这里讲了,以下是我的配置mail_backup.sh,该备份将上传到我的两个网盘中,并最多只保留两个最近的备份文件
#!/bin/bash
delete_mail_files() {
echo "开始删除 /tmp 下所有以 mailcow 开头的文件和目录..."
for item in /tmp/mailcow*; do
if [ -f "$item" ]; then
echo "正在删除文件: $item"
rm -f "$item"
elif [ -d "$item" ]; then
echo "正在删除目录: $item"
rm -rf "$item"
fi
done
echo "删除操作完成。"
}
SOURCE_DIR="/tmp"
DEST_DIR1="DEST_DIR1:/LocalStorage/Backups/MailData/"
DEST_DIR2="DEST_DIR2:/LocalStorage/Backups/MailData/"
CURRENT_DATE=$(date +"%Y-%m-%d")
delete_mail_files
THREADS=3 MAILCOW_BACKUP_LOCATION=/tmp /docker/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup all
TARGET=$(find /tmp -maxdepth 1 -type d -name "mailcow*" -print -quit)
tar -zcf "/tmp/mailcow_backup_$CURRENT_DATE.tar.gz" "$TARGET"
rclone copy "/tmp/mailcow_backup_$CURRENT_DATE.tar.gz" "$DEST_DIR1"
rclone copy "/tmp/mailcow_backup_$CURRENT_DATE.tar.gz" "$DEST_DIR2"
# 删除临时文件
delete_mail_files
# 只保留最近的两个备份
rclone lsf --format tp --separator " " "$DEST_DIR1" | sort -rk1 | awk 'NR>2 {print $NF}' | while read -r file; do
rclone deletefile "$DEST_DIR1/${file}"
done
rclone lsf --format tp --separator " " "$DEST_DIR2" | sort -rk1 | awk 'NR>2 {print $NF}' | while read -r file; do
rclone deletefile "$DEST_DIR2/${file}"
done
然后执行crontab -e,设置每天0点备份一次
0 0 * * * /root/scripts/mail_backup.sh >> /root/scripts/mail_backup.log 2>&1转载地址:https://blog.manjusaka.de/p/0-0-0-31/
