在 Debian 12 上搭建邮件服务器

本教程及后续教程将介绍如何搭建带有网页界面的邮件服务器。本部分将介绍启用服务器接收邮件和从服务器发送邮件的技术细节。第二和第三篇教程将分别介绍如何 转发最终用户的电子邮件 以及如何设置 网页邮件界面

使用您自己的邮件服务器的一个优势是,您可以轻松设置联系表单,让用户通过该表单向您发送邮件。

安装和运行邮件服务器所需的最低硬件配置为:1 个虚拟中央处理器、1 GB 内存和 3 GB 硬盘空间。

1. 打开端口

要设置邮件服务器,您需要打开特定的端口以允许邮件的收发。需要打开的端口取决于您计划使用的电子邮件协议。最常见的电子邮件协议是用于发送电子邮件的 SMTP(简单邮件传输协议)以及用于接收电子邮件的 IMAP(互联网消息访问协议)或 POP3(邮局协议)。以下是通常与这些协议关联的端口:

SMTP:

端口 25:这是 SMTP 的默认端口,用于发送邮件。

IMAP:

端口 143:这是 IMAP 的默认端口,用于接收邮件。它不安全,通常需要配合 STARTTLS 或 SSL/TLS 加密使用。

端口 993:这是安全的 IMAP 端口,用于使用 IMAPS(基于 SSL/TLS 的 IMAP)加密。

POP3:

端口 110:这是 POP3 的默认端口,用于接收未加密的邮件。

端口 995:这是安全的 POP3 端口,用于使用 POP3S(基于 SSL/TLS 的 POP3)加密时。

在本教程中,我们仅使用 SMTP 和 IMAP,因此需要打开以下端口:

请登录您的网站并打开上述端口。此外,还需要为网络服务打开 HTTP(入站):端口 80 和 HTTPS(入站):端口 443

2. 软件安装

以下教程适用于 Debian 12 上的 PostgreSQL。对于 Debian 11 上的 MariaDB,请参阅 Debian 11 上的邮件服务器

在 Linux 系统上,需要安装一系列软件:pwgen(生成随机密码)、PostgreSQL 服务器(数据库管理系统)、postfix(邮件服务器)、Apache 和 PHP(网络服务器)、swaks(测试邮件发送)和 mutt(在命令行中查看电子邮件)。用于存储电子邮件的附加软件是 dovecot。

pwgen

让我们从 pwgen 工具开始。 它可以帮助您创建安全的密码。除非您已经有了类似的工具……

sudo apt install -y pwgen

稍后您需要一个随机密码来为邮件服务器创建数据库用户。例如:要创建一个长度为 20 个字符的安全密码,您可以运行:

pwgen -s 20 1

您将获得一个类似 “W2EzNUFJzjEmA8tQT7A0” 的字符串。

PostgreSQL 服务器

如果您以“postgres”用户名登录服务器,则无需密码即可访问数据库服务器。当然,您也可以设置密码,但并非必须。

请安装 PostgreSQL 服务器软件包:

sudo apt install -y postgresql-contrib-15 postgresql-15 postgresql-client-15

如果一切顺利,您现在可以运行“sudo -u postgres -i”切换到postgres用户,然后运行“psql”连接到您的PostgreSQL数据库:
    psql (15.15 (Debian 15.15-1.pgdg12+1))
    输入“help”获取帮助。

    postgres=#
        
输入“\q”或按 CTRL-D 退出 SQL shell。输入“exit”切换回 sudo 用户。

Postfix

现在安装 Postfix 软件包:

sudo apt install postfix
sudo apt install postfix-pgsql

当系统询问邮件服务器配置类型时,请选择“Internet 站点”。输入您自己的邮件服务器名称(完全限定域名),或者直接按回车键。主机名和域名无需与您的任何电子邮件域名匹配。

Apache 和 PHP

要提供网页邮件服务,您需要 Apache 网络服务器软件和 PHP 脚本语言支持:

sudo apt install -y apache2 php

swaks

SWAKS(SMTP 的瑞士军刀)是一个非常实用的工具,可用于测试电子邮件发送功能:

sudo apt install -y swaks

mutt

这是一个功能齐全的 IMAP 邮件客户端。可以把它想象成邮件客户端中的 vi 编辑器。它无法显示 HTML 邮件,但对于测试 IMAP 邮件服务器非常有用。而且一些资深用户仍然更喜欢它而不是其他任何邮件客户端。

sudo apt install -y mutt

Dovecot

除了 Postfix(用于处理 SMTP 通信)之外,您还需要 Dovecot 来存储接收到的电子邮件,并为您的用户提供 IMAP(以及可选的 POP3)访问:

sudo apt install -y dovecot-pgsql dovecot-pop3d dovecot-imapd dovecot-managesieved dovecot-lmtpd

3. 配置 Apache 网络服务器以支持 HTTP

让我们从网络服务器开始。我假设您想为用户提供主机名 webmail.example.org。当然,您的服务器会使用您的域名。在本教程中,我将始终使用这个示例,并将该名称以粗体显示,以提醒您需要使用自己的主机名。

您只是想试用一下新服务器,暂时不想使用独立域名吗?没问题。您可以使用 nip.io 或在 Azure 门户中设置 DNS 名称标签,这将为您的网站创建一个子域名。如果您拥有独立域名,则需要为该主机设置指向服务器 IP 地址的 DNS “A”记录或“AAAA”记录(如果您使用 IPv6)。

打开浏览器,访问您网站的 DNS 名称。您应该会看到类似以下内容:

debianApache

首先,您需要为该主机创建一个网络根目录:

sudo mkdir /var/www/webmail.example.org
sudo chown www-data:www-data /var/www/webmail.example.org

接下来,您需要创建一个虚拟主机配置文件。Apache 使用一套简洁的系统来管理虚拟主机: 这种技术允许您启用和禁用虚拟主机,而无需删除任何配置。Linux 系统自带“a2ensite”(“apache2 enable site”的缩写)和“a2dissite”命令。除了进行一些健全性检查之外,这些命令主要用于在“sites-available”和“sites-enabled”之间创建或删除符号链接。

除非您已经在使用默认的符号链接,否则可以删除 /etc/apache2/sites-enabled/* 中的默认符号链接。

创建一个新的虚拟主机配置文件 /etc/apache2/sites-available/webmail.example.org-http.conf,并添加以下内容:

<VirtualHost *:80>
ServerName webmail.example.org
DocumentRoot /var/www/webmail.example.org
</VirtualHost>

这种简单的配置使得 Apache 能够处理 HTTP 请求(在标准 TCP 端口 80 上),前提是浏览器发送的请求头中包含一行“Host: webmail.example.org”。因此,浏览器实际上会告诉您的 Apache 网络服务器它正在寻找哪个服务器名称。这使得单个 IP 地址可以托管多个网站。(得益于服务器名称指示(SNI)技术,这种方法也适用于 HTTPS。)

启用该站点:

sudo a2ensite webmail.example.org-http

您将收到以下提示:
        要激活新配置,您需要运行:
         systemctl reload apache2
您可能需要在命令开头添加 sudo: sudo systemctl reload apache2

4. 获取 Let's Encrypt 证书

安装 Let's Encrypt 证书的方法有很多种。以下介绍的是 Linux (apt) 方法:

sudo apt update
sudo apt install certbot

由于我们使用的是 Apache 网络服务器,因此我们也需要安装 Apache 插件。

sudo apt install python3-certbot-apache

Certbot 提供多种通过插件获取 SSL 证书的方式。Apache 插件会在必要时负责重新配置 Apache 并重新加载配置。要使用此插件,请运行以下命令:

sudo certbot --apache --agree-tos --email your-account@example.com -d webmail.your-domain.com

这条命令会使用 `--apache` 插件运行 certbot,并使用 `-d` 参数指定证书生效的域名。 之后,certbot 会与 Let's Encrypt 服务器通信,然后运行一个验证码来确认你拥有申请证书的域名的控制权。

如果验证成功,配置将自动更新,并且 Apache 将重新加载以应用新设置。certbot 将显示一条消息,告知您成功以及证书的存储位置:

成功获取证书。
证书已保存到: /etc/letsencrypt/live/umd.eastus.cloudapp.azure.com/fullchain.pem
密钥已保存到:         /etc/letsencrypt/live/umd.eastus.cloudapp.azure.com/privkey.pem
此证书将于 2025-09-18 到期。
证书续订时,这些文件将自动更新。
Certbot 已设置计划任务,将在后台自动续订此证书。

部署证书
已成功将 umd.eastus.cloudapp.azure.com 的证书部署到 
/etc/apache2/sites-available/umd.eastus.cloudapp.azure.com-http-le-ssl.conf
恭喜!您已成功在 https://umd.eastus.cloudapp.azure.com 上启用 HTTPS。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
如果您喜欢 Certbot,请考虑通过以下方式支持我们的工作:
 * 向 ISRG / Let's Encrypt 捐款:   https://letsencrypt.org/donate
 * 向 EFF 捐款:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        

您的证书已下载、安装并加载完毕。请尝试使用 https:// 重新加载您的网站,并留意浏览器的安全指示器。它应该会显示网站已安全加密,通常会显示一个锁形图标。如果您使用 SSL Labs 服务器测试工具测试您的服务器,它将获得 A 级评分。

最后,我们来测试一下续订流程。

验证 Certbot 自动续订

Let’s Encrypt 证书的有效期只有九十天。这是为了鼓励用户自动化证书续订流程。您安装的 certbot 软件包会通过在 /etc/cron.d 中添加一个续订脚本来为您处理此事。该脚本每天运行两次,并会自动续订任何在三十天内即将过期的证书。

要测试续订流程,您可以使用 certbot 进行模拟运行:

sudo certbot renew --dry-run

如果您没有收到任何错误,则一切正常。如有必要,Certbot 将续订您的证书并重新加载 Apache 以应用更改。如果自动续订过程失败,Let’s Encrypt 会向您指定的电子邮件地址发送消息,警告您证书即将过期。

5. 准备数据库

现在需要准备用于存储邮件服务器控制信息的 PostgreSQL 数据库。在此过程中,您需要输入 SQL 查询语句——关系型数据库服务器的语言。您可以使用“psql”命令在终端窗口中输入这些语句。

生成两个随机密码

在本节中,您将创建基本数据库 “mailserver” 和两个用户。一个用户“mailadmin”可以修改数据库中的数据,供您使用。另一个用户“mailserver”只能读取数据库数据,供服务器进程使用。

使用 pwgen 工具为这两个用户生成两个随机密码:

pwgen -s1 30 2

记下密码或将其保存在安全的地方。

创建 ‘mailserver’ 数据库

这一步很简单。使用“psql”命令连接到数据库:

sudo -u postgres -i
psql

您应该会看到 PostgreSQL 提示符,允许您输入更多 SQL 命令:

postgres=#

现在您需要使用 SQL 了。为了创建一个满足我们需求的新数据库,请输入:

CREATE DATABASE mailserver;

系统会提示您的查询成功,并且添加了一行新数据。

创建数据库用户

现在您有了一个空数据库。让我们为 “mailadmin” 数据库用户授予管理该数据库所需的权限。

您仍然连接到数据库,对吗?要创建一个具有完整权限的用户,请输入以下 SQL 命令。请使用您刚刚生成的第一个密码,而不是我的密码:

CREATE USER mailadmin WITH ENCRYPTED PASSWORD 'E2zhrYD1156RtbPRgWLfU4uC0uCQ0g';
GRANT ALL PRIVILEGES ON DATABASE mailserver TO mailadmin;

同时创建一个只读用户,稍后将授予 Postfix 和 Dovecot 数据库访问权限(此处使用您的 第二个 随机密码)。

CREATE USER mailserver WITH ENCRYPTED PASSWORD 'uoDFE981mMpM0X996QNirfq4rJJ5ZR';
GRANT CONNECT ON DATABASE mailserver TO mailserver;
\c mailserver
GRANT SELECT ON ALL TABLES IN SCHEMA public TO mailserver;

为未来的表设置默认权限,以便用户自动拥有对该架构中创建的新表的 SELECT 访问权限。

ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO mailserver;

您可以通过尝试使用新用户登录来验证用户的访问权限:

psql -h localhost -U mailserver -d mailserver

创建数据库表

我们需要三个 Postfix 映射:一个用于虚拟域,一个用于虚拟别名,另一个用于虚拟用户。每一个映射都需要一个数据库表,您现在就来创建它们。您可以使用 Adminer。不过,我将展示用于创建表的 SQL 语句,您可以在 ‘psql’ 命令行工具中输入该语句。 要创建的第一个表是 virtual_domains。

此表保存您在 Postfix 中用作virtual_mailbox_domains 的域列表。

\connect mailserver;
CREATE TABLE virtual_domains (
id SERIAL PRIMARY KEY,
name varchar(50) NOT NULL
);

下一个表包含关于您的用户的信息。每个邮件帐户占用一行。

CREATE TABLE virtual_users (
id SERIAL PRIMARY KEY,
domain_id int NOT NULL,
email varchar(100) UNIQUE,
password varchar(150) NOT NULL,
quota bigint NOT NULL DEFAULT 0,
FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
);

最后一个表包含从一个电子邮件转发到其他电子邮件地址的映射。

CREATE TABLE virtual_aliases (
id SERIAL PRIMARY KEY,
domain_id int NOT NULL,
source varchar(100) NOT NULL,
destination varchar(100) NOT NULL,
FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
);

一个源邮箱地址可以对应多个目标地址。您只需插入多行数据,这些行具有相同的源地址和不同的目标地址,用于接收一封邮件的副本。Postfix会处理所有匹配的行。

示例数据供您参考

理论太多了吗?我能理解。我们先在数据库中填充 example.org 域名、john@example.org 邮箱账户,并将 jack@example.org 的邮件转发到 john@example.org。我们将在第 6 节“允许 Postfix 访问 PostgreSQL”中使用这些信息。

要添加示例数据,只需运行以下 SQL 查询语句:

\connect mailserver;
INSERT INTO virtual_domains (id,name) VALUES (1,'example.org');

INSERT INTO virtual_users (id,domain_id,password,email)
VALUES (1, 1,
'{BLF-CRYPT}$2y$05$xAEZd6RSftRCRKWuGwbc4.2HR/RFI5JwMFpymE/.TWZXWUp1.Krqi',
'john@example.org');

INSERT INTO virtual_aliases (id,domain_id,source,destination)
VALUES (1, 1, 'jack@example.org', 'john@example.org');

你是不是好奇我是怎么得到这么长的加密密码的?我运行了......

sudo doveadm pw -s BLF-CRYPT

......来生成简单密码“summersun”的安全哈希值。安装 Dovecot 后,您可以自己尝试一下,但结果你有所不同。这是因为密码经过 加盐 处理,以提高安全性。

6. 允许 Postfix 访问 PostgreSQL

在第5节,我们已经创建了 SQL 数据库模式并插入了一些数据进行练习。让我们从系统中所有邮件的入口点 Postfix 开始。因此,我们需要告诉 Postfix 如何从数据库中获取信息。首先,让我们告诉它如何判断某个域名是否为有效的邮件域名。

虚拟邮箱域

Postfix 中的映射就是一个包含左侧 (LHS) 和右侧 (RHS) 的表格。为了让 Postfix 从数据库获取虚拟域信息,我们需要创建一个“cf”文件(配置文件)。首先,创建一个名为 `/etc/postfix/pgsql-virtual-mailbox-domains.cf` 的文件,用于配置 `virtual_mailbox_domains` 映射。使其包含以下内容:

user = mailserver
password = uoDFE981mMpM0X996QNirfq4rJJ5ZR
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name=‘%s’

请在此输入您之前创建的 mailserver 数据库用户的密码。

假设 Postfix 收到一封发往 somebody@example.org 的邮件,并想知道 example.org 是否是一个虚拟邮箱域。它将运行上述 SQL 查询,并将 ‘%s’ 替换为 ‘example.org’。如果在 virtual_domains 中找到这样的行,它将返回 ‘1’。实际上,只要有结果,返回的具体内容并不重要。

现在,您需要让 Postfix 使用以下数据库映射:

sudo postconf virtual_mailbox_domains=pgsql:/etc/postfix/pgsql-virtual-mailbox-domains.cf

“postconf” 命令会方便地将配置行添加到您的 /etc/postfix/main.cf 文件中。它还会立即激活新设置,因些您无需重新加载 Postfix 进程。

使用具有管理权限的用户(例如默认的 postgres 用户)连接到 PostgreSQL 数据库。

sudo -u postgres psql
\connect mailserver

连接成功后,使用 GRANT 命令向邮件服务器用户授予对别名、域和用户表的 SELECT 权限。同时,使用 GRANT 命令授予邮件管理员用户对用户表的所有权限,因为我们需要这些权限才能在 Roundcube 中更新用户密码。

GRANT SELECT ON virtual_aliases TO mailserver;
GRANT SELECT ON virtual_domains TO mailserver;
GRANT SELECT ON virtual_users TO mailserver;
GRANT ALL PRIVILEGES ON virtual_users TO mailadmin;

退出 postgres 用户。您之前创建的测试数据已将域名“example.org”添加为您的邮箱域名之一。让我们询问 Postfix 是否识别该域名:

sudo postmap -q example.org pgsql:/etc/postfix/pgsql-virtual-mailbox-domains.cf

您应该会得到 ‘1’ 作为结果。这意味着您的第一个映射已生效。您可以尝试在该行命令的 -q 参数后添加其他域名。您应该不会收到任何响应。

现在,您需要定义 virtual_mailbox_maps。它会将收件人的邮件地址(左侧)映射到用户硬盘上的邮箱位置(右侧)。Postfix 内置了一个名为 “virtual” 的传输服务,可以接收邮件并将其存储到收件人的邮件目录中。该服务的功能相当有限,因此我们将委托给 Dovecot,以便更好地处理邮件。

Postfix 会将所有邮件转发给 Dovecot 进行进一步投递。但在此这前,我们需要确保收件人确实存在。因此,Postfix 需要检查邮件地址是否有效。这简化了操作,因为我们只需要映射的左侧部分。

与上述 virtual_domains 映射类似,您需要一个 SQL 查询来查找邮件地址,如果找到则返回 “1” 。

为此,请在 /etc/postfix/pgsql-virtual-mailbox-maps.cf 创建另一个配置文件:

user = mailserver
password = uoDFE981mMpM0X996QNirfq4rJJ5ZR
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email=‘%s’

再次提醒,请使用您数据库用户 ‘mailserver’ 的实际密码。

告诉 Postfix 此映射用于 virtual_mailbox_maps 映射:

sudo postconf virtual_mailbox_maps=pgsql:/etc/postfix/pgsql-virtual-mailbox-maps.cf

测试 Postfix 是否接受些映射,方法是询问 john@example.org 用户的邮箱目录在哪里:

sudo postmap -q john@example.org pgsql:/etc/postfix/pgsql-virtual-mailbox-maps.cf

虚拟别名映射

virtual_alias_maps 映射用于将邮件从一个电子邮件地址转发到一个或多个其他电子邮件地址。在数据库中,通过使用多行数据来实现多个目标。

在 /etc/postfix/pgsql-virtual-alias-maps.cf 创建另一个“.cf”文件:

user = mailserver
password = uoDFE981mMpM0X996QNirfq4rJJ5ZR
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source=‘%s’

让 Postfix 使用以下数据库映射:

sudo postconf virtual_alias_maps=pgsql:/etc/postfix/pgsql-virtual-alias-maps.cf

测试映射文件是否按预期工作:

sudo postmap -q jack@example.org pgsql:/etc/postfix/pgsql-virtual-alias-maps.cf

您应该会看到预期目的地:

john@example.org

7. 搭建鸽舍

我们旅程的这一部分将介绍 Dovecot——这款软件的功能包括: 出于安全考虑,在进行实际配置之前,我建议您创建一个新的系统用户,该用户将拥有所有虚拟邮箱。以下 shell 命令将创建一个 GID(组 ID)为 5000 的系统组“vmail”和一个 UID(用户 ID)为 5000 的系统用户“vmail”。(请确保 UID 和 GID 尚未被占用,或者选择其他数字——该数字可以是 1000 到 65000 之间任何未被占用的数字):

sudo groupadd -g 5000 vmail
sudo useradd -g vmail -u 5000 vmail -d /var/vmail -m

Dovecot 的配置文件位于 /etc/dovecot/conf.d/ 目录中。所有这些文件都会被 Dovecot 加载。这是通过 /etc/dovecot/dovecot.conf 文件末尾附近的这行神奇的命令实现的:

!include conf.d/*.conf

它会按字母数字顺序加载 /etc/dovecot/conf.d/ 目录中所有以“.conf”结尾的文件。因此,“10-auth.conf”会首先加载,“90-sieve-extprograms.conf”会最后加载。这样做的一个巨大优势是,您可以编辑或替换配置的某些部分,而无需覆盖整个配置文件。主配置文件 /etc/dovecot/dovecot.conf 不需要进行任何更改。但是,conf.d/ 目录中的其他文件需要进行修改。

/etc/dovecot/conf.d/10-auth.conf

最常见的身份验证机制称为 PLAIN. 但是,如果您有 Outlook 用户,则可能还需要添加 LOGIN 机制:

auth_mechanisms = plain login

这两种机制都会要求输入密码,但不会强制使用加密来保护密码。不过不用担心。默认情况下,Dovecot 会设置 disable_plaintext_auth = yes,这确保只有通过 TLS 加密连接才能接受身份验证。

在此文件的末尾,您会找到 Dovecot 提供的各种身份验证后端。默认情况下,它将使用系统用户(来自 /etc/passwd)。但我们想要使用 PostgreSQL 数据库后端,因此请将此代码块更改为:

#!include auth-system.conf.ext
!include auth-sql.conf.ext
#!include auth-ldap.conf.ext
#!include auth-passwdfile.conf.ext
#!include auth-checkpassword.conf.ext
#!include auth-static.conf.ext

10-mail.conf

将 mail_location 设置更改为:

mail_location = maildir:~/Maildir

这是 Dovecot 查找特定用户电子邮件的目录。波浪号字符 (~) 表示用户的主目录。这目前可能还不太好理解。但在本页的后面部分,我们将告诉 Dovecot 主目录具体指的是什么。例如,john@example.org 的主目录将位于 /var/vmail/example.org/john。

在 10-mail.conf 文件中,您会找到定义命名空间的部分。这些是您的电子邮件程序连接到邮件服务器时看到的文件夹结构。如果您使用 POP3,则只能访问“收件箱”——所有收到的电子邮件都存储在此处。使用 IMAP 协议,您可以访问文件夹和子文件夹的层次结构。您甚至可以在用户之间共享文件夹。或者使用任何人都可以访问的公共文件夹——甚至可以匿名访问。因此,通常建议使用 IMAP。

此外,编辑“mail_plugins”行,启用可选的配额插件,将其修改为:

mail_plugins = quota

10-master.conf

此配置文件处理典型的服务端口,例如 IMAP 或 POP3。

这里大多数设置都是合理的,无需更改。但是,“service auth”部分需要进行一项更改,因为我们希望 Postfix 允许 Dovecot 作为身份验证服务。将其修改为如下所示:

        # Postfix smtp-auth
        unix_listener /var/spool/postfix/private/auth {
          mode = 0660
          user = postfix
          group = postfix
        }
        
Postfix 运行在位于 /var/spool/postfix 的 chroot 环境中。它无法访问该目录之外的任何内容。因此,为了允许与 Postfix 进行通信,我们指示 Dovecot 将通信套接字放置在该 chroot 环境中。

10-ssl.conf

您已经创建了密钥和证书文件,用于加密用户与邮件服务器之间通过 POP3、IMAPs 和 HTTPS 进行的通信。您需要告诉 Dovecot 这些文件的位置:

ssl_cert = </etc/letsencrypt/live/webmail.example.org/fullchain.pem
ssl_key = </etc/letsencrypt/live/webmail.example.org/privkey.pem

并将 TLS 加密更改为:

ssl = required

接下来,让我们看看 Dovecot 如何识别用户及其密码:

auth-sql.conf.ext

Dovecot 读取 auth-sql.conf.ext 文件,该文件定义了如何在数据库中查找用户信息。打开该文件。其中包含两个部分: 默许情况下,Dovecot 会对您的数据库执行两次查询。一次用于 userdb,获取用户 ID、组 ID、主目录和配额等信息。另一次用于 passdb,获取哈希密码。

“userdb”部分的内容如下:

        userdb {
           driver = sql
           args = /etc/dovecot/dovecot-sql.conf.ext
        }
        
正如您所看到的,Dovecot 使用 SQL 数据库查找来获取这些信息。它引用 dovecot-sql.conf.ext 文件以获取更多信息。让我们看看……

/etc/dovecot/dovecot-sql.conf.ext

(此配置文件位于上一级目录,而不是“conf.d”目录中。)

您会发现此文件注释非常详细,尽管所有配置指令都被注释掉了。在文件末尾添加以下几行:

driver = pgsql
connect = \
host=127.0.0.1 \
dbname=mailserver \
user=mailserver \
password=uoDFE981mMpM0X996QNirfq4rJJ5ZR
user_query = SELECT email as user, ‘/var/vmail/%d/%n’ As home, 5000 AS uid, 5000 AS gid FROM virtual_users WHERE email=‘%u’
password_query = SELECT password FROM virtual_users WHERE email=‘%u’

反斜杠

行尾的反斜杠(\)表示该行将在下一行继续。当配置信息跨越多行时,使用反斜杠可以使配置更易于阅读。

这些行的含义:

user_query 从数据库获取多个信息。让我们逐一查看:

修复权限

确保只有 root 用户才能访问 SQL 配置文件,以防止其他人读取您的数据库访问密码:

sudo chown root:root /etc/dovecot/dovecot-sql.conf.ext
sudo chmod go= /etc/dovecot/dovecot-sql.conf.ext

从命令行重启 Dovecot:

sudo systemctl restart dovecot

运行 sudo journalctl -fu dovecot。您应该会看到:

dovecot[10637]: master: Dovecot v2.3.19.1 (9b53102964) 正在启动,用于 imap、lmtp、sieve、pop3(已禁用核心转储)
systemd[1]: 已启动 dovecot.service - Dovecot IMAP/POP3 邮件服务器。

如果出现任何错误信息,请仔细检查您的配置文件。

8. 允许 Postfix 向 Dovecot 发送电子邮件

在第 7 节中,我们确保 Postfix 知道它允许接收哪些电子邮件。那么接下来该如何处理这些电子邮件呢?它们必须保存到磁盘上,存入正在焦急等待的邮件用户的邮箱中。你可以让 Postfix 使用其内置的邮件投递代理 (MDA)“虚拟”来处理此事。然而,与 Dovecot 提供的功能(例如基于服务器的过滤规则或配额)相比,Postfix 的投递代理功能相当基础。我们无论如何都要使用 Dovecot 来提供 IMAP(以及可选的 POP3)服务。所以,让我们使用它的投递代理。

我们如何让 Postfix 将电子邮件交给 Dovecot 呢?通常有两种方法可以建立这种连接。
  1. 使用 dovecot-lda (本地投递代理)进程。它可以一次处理一封电子邮件。并且它会为每封电子邮件启动一个新进程。这在很长一段时间内都是默认方式。但正如你所想,它的可伸缩性并不好。
  2. 更好的选择是使用为此目的而设计的 LMTP(本地邮件传输协议) 它可以同时处理多个收件人,并且有一个永久运行的进程,比使用 LDA 性能更好。简而言之,LMTP 是 SMTP 的一个变体,功能较少。它用于相互信任的内部服务之间的电子邮件通信。

你已经猜到了--我们将选择第二种方法。你之前已经安装了 dovecot-lmtpd 软件包。让我们来配置它。

告诉 Dovecot 在哪里监听来自 Postfix 的 LMTP 连接

编辑 Dovecot 的配置文件,该文件用于处理 LMTP 守护进程——你可以在 /etc/dovecot/conf.d/10-master.conf 找到它。找到“service lmtp”部分并进行编辑,使其看起来如下所示:

        service lmtp {
          unix_listener /var/spool/postfix/private/dovecot-lmtp {
            group = postfix
            mode = 0600
            user = postfix
          }
        }
        
这将使 Dovecot 的 lmtp 守护进程在 /var/spool/postfix/private/dovecot-lmtp 创建一个 UNIX 套接字。就像在设置 Dovecot 的部分一样,我们让它将套接字放在 /var/spool/postfix chroot 目录中,因为 Postfix 被限制在该目录中,无法访问其外部的任何内容。因此,从 Postfix 的角度来看,该套接字位于“private/dovecot-lmtp”。

重启 Dovecot…

sudo systemctl restart dovecot

检查 Dovecot 是否接受了此更改:

systemctl status dovecot

输出应包含 “Active: active (running)”.

让 Postfix 使用 LMTP 将电子邮件投递到 Dovecot

这更简单。“virtual_transport” 在 Postfix 中定义了用于将电子邮件投递到本地系统的服务。Dovecot 已经创建了一个套接字文件,并准备好监听传入的 LMTP 连接。我们只需要告诉 Postfix 将电子邮件发送到那里即可:

sudo postconf virtual_transport=lmtp:unix:private/dovecot-lmtp

这个语法看起来很复杂,但实际上很简单。您只是告诉 Postfix 使用 LMTP 协议。并且我们想要使用同一系统上的 UNIX 套接字(而不是 TCP 连接)。套接字文件位于 /var/spool/postfix/private/dovecot-lmtp。

启用服务器端邮件规则

Dovecot 的功能之一是服务器端处理的自动接收邮件规则。您可以将邮件列表的电子邮件分类到特定的文件夹中。您可以拒绝某些发件人。或者您可以设置假期自动回复。无需运行邮件客户端——即使您的邮件用户未连接,所有操作也会在服务器上自动进行。

此类规则的开放标准 (RFC 5228) 称为 Sieve。基本上,Sieve 是一种管理服务器端电子邮件规则的方法。规则由条件和操作组成。例如,如果发件人地址与 steve@example.org 匹配,您可以告诉 Dovecot 自动将此类电子邮件移动到您的“steve”文件夹。这些规则存储在 Dovecot 服务器上并自动执行。无论您是从智能手机、笔记本电脑还是使用网页邮件访问,这些规则始终有效,并且无需在客户端进行任何配置。

由于我们使用 LMTP,因此我们需要告诉 lmtp 服务我们想要使用 Dovecot 的“sieve”插件。编辑文件 /etc/dovecot/conf.d/20-lmtp.conf,并在“protocol lmtp”部分中将“mail_plugins”行更改为:

mail_plugins = $mail_plugins sieve

重启 Dovecot 即可完成:

sudo systemctl restart dovecot

9. 测试 IMAP

您已经完成了 Dovecot 的配置。因此,通过 IMAP 收取电子邮件应该已经可以正常工作了。让我们使用一个看似简单但功能强大的 IMAP 客户端 mutt 来尝试一下:

mutt -f imaps://john@example.org@**webmail.example.org**

由于有两个“@”字符,连接 URL 看起来可能有点令人困惑。通常,mutt 期望的格式是 imaps://user@server。由于我们使用电子邮件地址作为“user”部分,所以会显示成这样。

系统会提示您输入密码,我们之前设置的密码是 “summersun”。

如果您收到任何证书警告,请检查您是否使用了正确的服务器名称进行连接,以及您是否已按照本指南前面的步骤完成了证书/Let's Encrypt 的配置。

登录后,您将看到一个空的收件箱:

mutt empty folder

10. 测试电子邮件投递

到目前为止,您已经花费了大量时间进行理论学习和配置。您是否担心您所做的一切最终能否构建一个正常工作的邮件服务器?在进行最后步骤之前,让我们休息一下,验证一下您目前所做的一切是否都按预期工作。

此时,/var/vmail 目录应该是空的,或者如果您之前使用过 john@example.org 帐户,则可能包含一个“example.org”目录。您可以通过运行以下命令获取其中所有文件和目录的列表:

sudo find /var/vmail

尽管服务器上实际上还没有任何电子邮件,但您仍然可能会看到类似以下内容:

/var/vmail
/var/vmail/.bash_logout
/var/vmail/umd.me.uk
/var/vmail/umd.me.uk/john
/var/vmail/umd.me.uk/john/Maildir
/var/vmail/umd.me.uk/john/Maildir/dovecot-uidlist
/var/vmail/umd.me.uk/john/Maildir/new
/var/vmail/umd.me.uk/john/Maildir/dovecot-uidvalidity.697cfa2f
/var/vmail/umd.me.uk/john/Maildir/dovecot-uidvalidity
/var/vmail/umd.me.uk/john/Maildir/dovecot.list.index.log
/var/vmail/umd.me.uk/john/Maildir/maildirfolder
/var/vmail/umd.me.uk/john/Maildir/dovecot.index.log
/var/vmail/umd.me.uk/john/Maildir/tmp
/var/vmail/umd.me.uk/john/Maildir/cur
/var/vmail/.profile
/var/vmail/.cloud-locale-test.skip
/var/vmail/.bashrc

基本上,您看到的结构是 /var/vmail/域名/用户/Maildir/…

每个IMAP 邮件文件夹包含三个子目录:

嵌套文件夹(文件夹中的文件夹)将用点号分隔,例如:

检查 Postfix

要检查 Postfix 中是否存在明显的配置错误,请运行:

sudo postfix check

发送测试邮件

现在是时候向系统中发送一封新邮件了。现在,让我们向 John 发送一封电子邮件。我最喜欢的邮件测试工具是您之前安装的 swaks。在原始终端中运行:

swaks --to john@example.org --server localhost

运行以下命令查看邮件服务器正在执行的操作:

sudo journalctl -n 10 -u dovecot

您要查找的行看起来像这样:

dovecot[10976]: lmtp(john@umd.me.uk)<11396><gf56HE37fGmELAAATRJD4g>: msgid=<20260130184117.011384@webmail.umd.me.uk>: 已将邮件保存到收件箱

您的输出结果可能略有不同。如果一切正常,Postfix 应该已经接受了电子邮件并将其转发到 Dovecot,而 Dovecot 又会将电子邮件写入 John 的邮件目录(maildir)。如果您在日志文件中发现任何错误,请尝试理解错误消息并找到问题的原因,然后再继续操作。

再次查看:

sudo find /var/vmail/example.org/john

它看起来像这样吗?

/var/vmail/umd.me.uk/john
/var/vmail/umd.me.uk/john/Maildir
/var/vmail/umd.me.uk/john/Maildir/dovecot-uidlist
/var/vmail/umd.me.uk/john/Maildir/new
/var/vmail/umd.me.uk/john/Maildir/new/1769798477.M505403P11396.webmail.umd.me.uk,S=700,W=720
/var/vmail/umd.me.uk/john/Maildir/dovecot-uidvalidity.697cfa2f
/var/vmail/umd.me.uk/john/Maildir/dovecot-uidvalidity
/var/vmail/umd.me.uk/john/Maildir/dovecot.list.index.log
/var/vmail/umd.me.uk/john/Maildir/dovecot.index.cache
/var/vmail/umd.me.uk/john/Maildir/maildirfolder
/var/vmail/umd.me.uk/john/Maildir/dovecot.index.log
/var/vmail/umd.me.uk/john/Maildir/tmp
/var/vmail/umd.me.uk/john/Maildir/cur

这里重要的文件是…/Maildir/new/1769798477.M505403P11396.webmail.umd.me.uk,S=700,W=720。这些数字在您的系统中可能显示不同。但这就是实际送达的邮件。

您还可以使用一个更便捷的工具来访问 Maildir,这对于邮件服务器管理员来说非常实用:“mutt”。

sudo mutt -f /var/vmail/example.org/john/Maildir

(系统可能会提示您创建 /root/Mail 目录——这是标准流程。只需按回车键即可。)

现在您看到的是 John 邮箱的内容:

mutt John's inbox

使用 mutt 是一种在登录邮件服务器时检查邮箱的好方法。

重申一下收到电子邮件时会发生什么:
  1. Postfix 接收电子邮件(在本例中使用了“swaks”命令——但通常是通过网络使用 SMTP 协议从其他服务器接收)
  2. Postfix 通过 LMTP 与 Dovecot 通信并传递电子邮件
  3. Dovecot 会执行用户的 Sieve 规则。
  4. Dovecot 将电子邮件文件写入磁盘

本教程介绍了如何设置邮件服务器以接收和从服务器发送电子邮件。关于如何配置邮件服务器以转发最终用户的电子邮件,请参阅 “邮件中继”。