使用Maddy+RainLoop搭建自己的邮箱
本文最后更新于 429 天前,其中的信息可能已经有所发展或是发生改变。

一直想用自己的域名搭建一个的邮箱,但传统的Dovecot+Postfix方案十分复杂,封装起来的docker-mailserver虽整洁不少,但仍然存在占用资源很高的问题。

想起Golang效率挺高的,也已经有了不错的生态,于是找到了Maddy,一个使用Golang编写的一体化邮件服务器,占用较少,也免去了各种模块相互配合的。它充当了MTA(中转服务器)和MDA(投递服务器)的角色。

而Rainloop则是一个PHP写成的webmail,可以作为一个类似于Gmail的网页端。

一般的VPS都可以搭建邮件服务器,不过某些服务商会屏蔽必要的25端口,可能需要发工单解决,不过上网搜一下一般就能知道。

本文以Nginx 1.20.2、PHP 8.1.1、Ubuntu 18.04 LTS为例

邮件服务器:Maddy

下载与安装

Maddy的文档说得其实挺明白的,但如果你不想看英语,也可以跟我走。这里使用预编译的二进制文件来搭建。

首先要从GitHub Releases下载最新的二进制文件到服务器中,文件名为maddy-x.x.x-x86_64-linux-musl.tar.zst。

解压zst文件需要zstd依赖(Debian系可直接用apt安装),安装后使用

tar --use-compress-program=unzstd -xvf archive.tar.zst

来指定zstd程序解压这个文件。然后将文件夹内的maddy和maddycli复制到/usr/local/bin目录下。

除此之外,Maddy无法以root用户运行,所以你还需要新建一个用户:

sudo useradd -mrU -s /sbin/nologin -d /var/lib/maddy -c "maddy mail server" maddy

预编译二进制文件的压缩包内还带有systemd服务,可以直接拷贝到系统文件夹内使用:

sudo cp ./systemd/*.service /etc/systemd/system
sudo systemctl reload

将压缩包内附带的maddy.conf复制到etc目录下,然后用你喜欢的文本编辑器打开。暂时只需要编辑Base variables部分,记得要将上面的内容都换成你对应的。

$(hostname) = mx1.example.org # 外界通过这个域名找到你的邮件服务器。
$(primary_domain) = example.org # 你的邮箱@后面的域名,比如test@example.org,而不一定是test@mx1.example.org
$(local_domains) = $(primary_domain) # @后面可以添加的其他域名,比如test@one.example.org。你需要在几个域名中选一个主要的,将其填入primary domain。

tls file /etc/maddy/certs/$(hostname)/fullchain.pem /etc/maddy/certs/$(hostname)/privkey.pem # TLS证书文件。

对于证书文件,如果你使用Certbot获取hostname的TLS证书,你可以直接进行一个软连接,使得Maddy可以识别,而且要确保其有权限读取:

ln -s /etc/letsencrypt/live /etc/maddy/certs
sudo setfacl -R -m u:maddy:rX /etc/letsencrypt/{live,archive}

如果由其他方法获取证书,可以将文件拷贝至/etc/maddy/certs并用相似的命令赋予maddy用户读取权限。

现在我们可以将其启动了:

systemctl start maddy

配置DNS

首先是各个domain的A/AAAA record,即上面提到example.org和one.example.org的指向。这个没必要指向你的邮件服务器IP,也就是说你可以拿这些域名指向其他服务器建个站什么的,但如果没有另外的用处,不设置应该也没什么问题。

然后仍然是上面几个domain,这次是MX record。它由domain指向hostname。举个例子,将example.org的MX记录指向mx1.example.org,意思是任何发送到@example.org的邮件服务都由mx1.example.org来处理。如果你有多个domain,那么需要逐个设置。

之后设置hostname即邮件服务器的A/AAAA记录。它需要将类似于mx1.example.org的地址解析为IP地址。

要设置MTA-STS(后面会讲),需要将mta-sts.example.org和mta-sts.one.example.org(即各个domain)的A/AAAA记录指向邮件服务器IP。

还有一系列的TXT类型的解析如下。

SPF 为domain和hostname(非必要)都添加txt解析,内容如下。用于表明MX解析的域名是可以发邮件的。

v=spf1 mx ~all

DMARC 用于处理损坏的邮件。需要为所有_dmarc.yourdomain(如_dmarc.example.org和_dmarc.one.example.org)添加。

v=DMARC1; p=quarantine; ruf=mailto:postmaster@example.org

MTA-STS标记 加上之后,失败的报告会被送到指定的邮箱(默认postmaster)。为_mta-sts.example.org添加(其他domain不要漏下)

v=STSv1; id=1

然后为_smtp._tls.example.org添加

v=TLSRPTv1;rua=mailto:postmaster@example.org

DKIM Key 在/var/lib/maddy/dkim_keys/example.org_default.dns(文件名因人而异)找到该项TXT记录值,并将其给予default._domainkey.example.org的TXT解析。

MTA-STS保护

其实包括MTA-STS和DKIM等措施,对于发送邮件来说并不是必要的,但如果没有这几个措施,那么一些大电子邮件服务商(比如Gmail)会认为从你的服务器发出的是垃圾邮件。

MTA-STS(RFC 8461)是一个预防中间人攻击的防护措施。它的标记已经在上一步做好。然后,我们需要使用一个网页服务器来返回一串文本。

官方文档推荐的方式是serve一个文本文档,内容如下:

version: STSv1
mode: enforce
max_age: 604800
mx: mx1.example.org

当访问https://mta-sts.example.org/.well-known/mta-sts.txt的时候,就返回它。

对于Nginx,也可以使用以下方式直接返回这串文字,在Nginx配置文件的HTTP块内加入一个server:

server {
    server_name mta-sts.example.org;
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_certificate /path/to/fullchain.pem; # 路径因人而异,下同
    ssl_certificate_key /path/to/privkey.pem;
    location = /.well-known/mta-sts.txt {
        default_type text/plain;
        return 200 "version: STSv1\r\nmode: enforce\r\nmx: mx1.example.org\r\nmax_age: 604800\r\n";
    }
}

当然,这之前需要确保你将mta-sts.example.org指向正确的IP,并申请其对应的TLS证书。

如果你使用Nginx、Caddy或Litespeed等网页服务器,请自行研究。

要验证是否添加成功,可以直接访问https://example.org/.well-known/mta-sts.txt,查看返回的内容。

TLSA/DANE记录这里不再指引,因为我使用的阿里云DNS是不能添加DLSA记录的,有兴趣的可以自行看官方文档。

添加账户

Maddy的账户体系是“虚拟用户”,也就是说验证账户和IMAP邮箱是分离开来的。

首先,要创建用户验证,使用命令:

maddyctl creds create example@example.org

输入账户密码,然后再创建它的邮箱:

maddyctl imap-acct create example@example.org

这样,一个传统意义上的邮件账户就创建完成了。

如果需要更多帮助,可以使用

maddyctl creds --help
maddyctl imap-acct --help

命令来获取。

到现在,你可以使用任何一个现代的邮件客户端,连接你刚刚创建的邮件服务器。IMAP协议即可,发送和接收可以全都选SSL。为安全起见,建议以后的邮件客户端全部启用SSL。

发一封邮件,如果你上述的安全措施做得比较好,发送给Gmail等对安全比较严格的邮箱,应该能够作为重要邮件,起码不会被作为垃圾邮件。使用IMAP+SMTP+SSL,收件端口号为993,发件端口号为465。

Webmail:RainLoop

大部分看这篇文章的人都应该是搭着玩的个人用户吧。如果不是,那么请首先参阅RainLoop的不同版本比较页面,他们针对不同用户有不同的版本和Licence。这里直接选对无盈利的个人免费的Standard Edition,因其带有比较简便的更新功能。

下载与安装

从这里可以下载两种版本到服务器上。下载下来是ZIP格式,所以我们需要安装unzip解压(apt包管理器内有,不带apt的发行版请自行想办法)。

然后输入以下命令,将RainLoop的文件拷贝至/var/www/rainloop,并设置权限。你也可以使用其他自己喜欢的路径,别忘了修改后面的配置文件对应部分。

unzip rainloop-latest.zip -d /var/www/rainloop
cd /var/www/rainloop
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;

然后编辑Nginx配置文件,加入server块:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name webmail.example.org;

    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    index index.html index.php;
    root /var/www/rainloop;
    client_max_body_size 2G;

    error_log /var/log/nginx/rainloop.error.log;
    access_log /var/log/nginx/rainloop.access.log;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ^~/data {
        deny all;
    }

    location ~ \.php$ {
        fastcgi_pass php-handler-https;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

其中你必须更改的是server_namessl_certificatessl_certificate_key。你可以把页面直接放到邮件服务器上,也可以换个服务器或者域名,但如果你想直接用上文提到的mx1.example.org即hostname,那么可以做正向代理,但更推荐的做法是把RainLoop直接部署到邮件服务器上。其他root等项视情况更改。根据官方文档,data目录不能允许被外网访问从而直接获取配置文件,所以直接deny all。

然后使用nginx -t测试配置文件,如果没有问题,就systemctl restart nginx重启nginx,然后访问webmail.example.org(例)试试吧。

若仍提示no data folder write permission权限问题,大不了给对应目录文件直接777权限(问题不大、

初始配置

访问webmail.example.org/?admin来进行初始配置。默认管理员用户名为admin,密码为12345。

首先建议在“安全”选项卡中修改默认管理员密码。在“域名“选项卡中,你可以添加你刚刚架设好的邮件domain,也可以添加其他商用邮箱域名。添加之后点击测试,可以测试一下邮件服务器在此设定下能否连通。正常来说,你不需要勾选”使用短域名登录“。

此外,”白名单“功能能够限制某域中能登陆到Webmail的账户列表,如设置example.com的白名单为test@example.com,那么除上述邮箱外,后缀为@example.com的邮箱全部不能登录。

这两项基础设置做完之后,你就可以重新打开webmail.example.org,输入你的邮箱和密码,登录Webmail。如果无法登录,请检查你刚刚的初始配置。如果能够成功进入邮箱,那就……enjoy it!

参考文献

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇