公司动态

Linux下自建邮件服务器:Postfix+Dovecot+MySQL完整搭建指南

📅 2026/8/4 4:15:39
Linux下自建邮件服务器:Postfix+Dovecot+MySQL完整搭建指南
1. 项目概述为什么要在Linux上自建邮件服务器在云服务无处不在的今天你可能觉得搭建自己的邮件服务器是件“复古”又麻烦的事。确实直接用Gmail、QQ邮箱或者企业邮箱服务省心省力。但作为一名运维工程师或者技术爱好者我选择自建邮件服务器核心原因有几个首先是数据自主所有邮件数据都掌握在自己手里不用担心服务商的政策变化或隐私问题其次是高度定制化从反垃圾邮件策略、邮件过滤规则到存储备份都可以按需配置再者对于内部开发测试、学习网络协议如SMTP、POP3原理或者为特定应用如监控告警、网站用户注册提供发信服务自建方案成本更低、更灵活。这次要搭建的是一个功能完整的邮件服务器支持发送SMTP和接收POP3/IMAP邮件。核心组件我们选用Postfix作为邮件传输代理MTADovecot作为邮件投递代理MDA来提供POP3/IMAP服务并用MySQL来管理虚拟用户和域名。这套组合在稳定性、性能和社区支持方面都是经过时间考验的。整个过程涉及系统配置、软件安装、DNS解析、安全加固等多个环节我会把每一步的原理和踩过的坑都讲清楚。2. 环境准备与核心组件解析在开始敲命令之前我们需要先理清邮件系统的基本架构和我们的目标环境。一个典型的邮件收发流程涉及几个关键角色MTA邮件传输代理如Postfix负责在服务器之间路由和传递邮件MDA邮件投递代理如Dovecot负责将邮件投递到用户的邮箱如Maildir格式的目录还有用于认证和管理的数据库如MySQL。我们的目标是搭建一个支持虚拟用户即系统用户与实际邮箱用户分离的邮件系统。2.1 系统环境与网络前提我使用的是一台全新的CentOS 8 Stream服务器其他如Ubuntu 20.04/22.04步骤类似包管理命令不同。首先确保服务器有一个固定的公网IP地址这是邮件服务器能被外界访问的基础。其次你需要拥有一个域名例如 yourdomain.com因为绝大多数正规邮件服务商都会拒绝来自裸IP地址的邮件以防止垃圾邮件。注意如果你的服务器位于家庭宽带或某些云服务商的内网可能没有独立的公网IP或25端口SMTP默认端口被屏蔽。这种情况下你可以将自建服务器仅用于内部发信如应用程序通知或者考虑使用云服务商提供的邮件中继服务来发送对外邮件。登录服务器后第一件事是更新系统并设置主机名sudo dnf update -y sudo hostnamectl set-hostname mail.yourdomain.com编辑/etc/hosts文件确保有一行记录将主机名解析到本机IP127.0.0.1或你的内网IP这能避免一些本地服务因DNS查询延迟而出错。2.2 核心组件选型与职责Postfix我们将用它作为SMTP服务器。它负责接收从外部发来的邮件以及将本地用户要发出的邮件传递到目标服务器。Postfix以其安全、高效和配置清晰著称。我们会将其配置为使用MySQL来查询虚拟用户和域名信息而不是依赖系统用户。Dovecot负责POP3和IMAP服务让用户可以用邮件客户端如Outlook、Thunderbird或手机自带的邮件App来收取、管理邮件。它同样会连接MySQL来验证用户身份并从指定的Maildir目录读取邮件。MySQL (MariaDB)作为后端数据库存储虚拟邮箱用户、域名、别名转发等信息。使用数据库管理用户比直接使用系统用户或纯文本文件要灵活和安全得多。其他辅助工具我们可能还会用到openssl来生成自签名证书用于加密连接以及telnet或swaks等工具进行测试。3. 详细安装与配置步骤实录接下来是实操部分我会按照逻辑顺序一步步完成安装和配置。请务必理解每一步的目的而不是单纯复制命令。3.1 安装必要的软件包首先安装Postfix、Dovecot、MariaDB服务器以及相关的连接库sudo dnf install -y postfix postfix-mysql dovecot dovecot-mysql mariadb-server mariadb安装完成后启动MariaDB并设置开机自启同时进行初步的安全设置sudo systemctl enable --now mariadb sudo mysql_secure_installation运行安全设置脚本时会提示你设置root密码、移除匿名用户、禁止root远程登录等建议全部选择‘Y’。3.2 配置MySQL数据库现在为我们的邮件系统创建专用的数据库和用户。登录MySQLsudo mysql -u root -p然后执行以下SQL语句请将mailuserpassword替换为一个强密码CREATE DATABASE mailserver; GRANT ALL ON mailserver.* TO mailuserlocalhost IDENTIFIED BY mailuserpassword; FLUSH PRIVILEGES; USE mailserver;接下来创建存储虚拟域名、用户和别名的表-- 存储允许接收邮件的域名 CREATE TABLE virtual_domains ( id int(11) NOT NULL auto_increment, name varchar(50) NOT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8; -- 存储邮箱用户密码字段用于Dovecot认证 CREATE TABLE virtual_users ( id int(11) NOT NULL auto_increment, domain_id int(11) NOT NULL, email varchar(100) NOT NULL, password varchar(106) NOT NULL, -- 用于存储加密后的密码 PRIMARY KEY (id), UNIQUE KEY email (email), FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE ) ENGINEInnoDB DEFAULT CHARSETutf8; -- 存储邮件别名转发规则 CREATE TABLE virtual_aliases ( id int(11) NOT NULL auto_increment, domain_id int(11) NOT NULL, source varchar(100) NOT NULL, destination varchar(100) NOT NULL, PRIMARY KEY (id), FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE ) ENGINEInnoDB DEFAULT CHARSETutf8;插入测试数据。假设你的域名是yourdomain.com你想创建用户user1yourdomain.comINSERT INTO virtual_domains (name) VALUES (yourdomain.com); -- 假设上面插入的域名id是1 INSERT INTO virtual_users (domain_id, email, password) VALUES (1, user1yourdomain.com, ENCRYPT(user_password, CONCAT($6$, SUBSTRING(SHA(RAND()), -16)))); -- 上面使用了MySQL的ENCRYPT函数配合SHA512$6$生成一个加密密码。更常见的做法是在系统外用doveadm pw生成后再插入。实操心得密码处理是个关键。上述SQL生成的密码格式可能不被Dovecot默认支持。更稳妥的做法是使用Dovecot自带的工具doveadm pw生成加密密码。在终端执行doveadm pw -s SHA512-CRYPT输入明文密码后会生成类似{SHA512-CRYPT}$6$...的字符串将这个完整字符串包括花括号和算法标识填入virtual_users表的password字段。这能确保Dovecot能正确验证。3.3 配置Postfix连接MySQLPostfix需要通过查询数据库来知道哪些域名是它需要处理的以及用户是否存在。我们需要创建几个配置文件来告诉Postfix如何连接MySQL并执行查询。首先创建主配置文件/etc/postfix/mysql-virtual-domains.cf用于查询虚拟域名user mailuser password mailuserpassword hosts 127.0.0.1 dbname mailserver query SELECT name FROM virtual_domains WHERE name%s创建/etc/postfix/mysql-virtual-users.cf用于查询虚拟用户user mailuser password mailuserpassword hosts 127.0.0.1 dbname mailserver query SELECT email FROM virtual_users WHERE email%s创建/etc/postfix/mysql-virtual-aliases.cf用于查询别名转发user mailuser password mailuserpassword hosts 127.0.0.1 dbname mailserver query SELECT destination FROM virtual_aliases WHERE source%s创建/etc/postfix/mysql-virtual-email2email.cf用于将邮件地址映射回自身用于投递user mailuser password mailuserpassword hosts 127.0.0.1 dbname mailserver query SELECT email FROM virtual_users WHERE email%s注意务必修改这些文件中的password为你在MySQL中为mailuser设置的密码。并且将这些文件的权限设置为仅root可读因为里面包含数据库密码sudo chmod 600 /etc/postfix/mysql-virtual-*.cf sudo chown root:root /etc/postfix/mysql-virtual-*.cf接下来修改Postfix的主配置文件/etc/postfix/main.cf。以下是一些关键的配置行你需要根据注释进行修改或添加# 基本设置 myhostname mail.yourdomain.com mydomain yourdomain.com myorigin $mydomain inet_interfaces all inet_protocols ipv4 # 如果不需要IPv6可以只使用ipv4 # 禁用本地传输我们只使用虚拟邮箱 mydestination localhost.$mydomain, localhost local_transport error:local delivery is disabled # 虚拟域名、用户、别名的映射配置 virtual_mailbox_domains mysql:/etc/postfix/mysql-virtual-domains.cf virtual_mailbox_maps mysql:/etc/postfix/mysql-virtual-email2email.cf virtual_alias_maps mysql:/etc/postfix/mysql-virtual-aliases.cf virtual_mailbox_base /var/mail/vmail virtual_uid 1000 # 指定一个系统用户ID用于邮件存储目录的所有者 virtual_gid 1000 # 指定一个系统组ID # 邮件存储格式设置为Maildir每个用户的邮件会存储在以其邮箱地址命名的目录下 virtual_mailbox_limit 512000000 # 邮箱大小限制约500MB virtual_mailbox_extensions .mdbox # 也可以使用 .Maildir这里以Maildir为例但配置需对应 # 实际上对于Maildir我们通常这样指定 virtual_mailbox_maps mysql:/etc/postfix/mysql-virtual-users.cf # 并在Dovecot中配置具体的Maildir路径 # 更常见的配置是使用下面的方式定义邮箱位置 virtual_mailbox_domains mysql:/etc/postfix/mysql-virtual-domains.cf virtual_mailbox_maps mysql:/etc/postfix/mysql-virtual-users.cf virtual_alias_maps mysql:/etc/postfix/mysql-virtual-aliases.cf virtual_mailbox_base /var/mail/vhosts virtual_mailbox_limit 512000000 virtual_minimum_uid 1000 virtual_uid_maps static:1000 virtual_gid_maps static:1000 # SMTP认证配置与Dovecot SASL集成 smtpd_sasl_type dovecot smtpd_sasl_path private/auth smtpd_sasl_auth_enable yes smtpd_sasl_security_options noanonymous smtpd_sasl_local_domain $myhostname broken_sasl_auth_clients yes # 限制规则防止开放中继 smtpd_recipient_restrictions permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination # TLS加密配置稍后生成证书后配置 # smtpd_tls_cert_file/etc/pki/tls/certs/mail.yourdomain.com.crt # smtpd_tls_key_file/etc/pki/tls/private/mail.yourdomain.com.key # smtpd_use_tlsyes # smtpd_tls_session_cache_database btree:${data_directory}/smtpd_scache配置看起来很多但核心思路是告诉Postfix用MySQL来管理域名和用户并指定邮件的存储位置和所有者。配置完成后检查配置语法并重启Postfixsudo postfix check sudo systemctl restart postfix sudo systemctl enable postfix3.4 配置Dovecot提供POP3/IMAP服务Dovecot的配置稍微复杂因为它涉及认证、邮件存储和协议服务。我们主要修改几个关键文件。首先备份原始配置然后编辑Dovecot的主配置文件/etc/dovecot/dovecot.conf。确保以下关键参数被设置或取消注释# 启用支持的协议 protocols imap pop3 lmtp # 如果也需要管理后台如doveadm可以加上 imap pop3 lmtp接下来配置认证和邮件存储。编辑/etc/dovecot/conf.d/10-auth.conf# 禁用明文认证除非在SSL/TLS下 disable_plaintext_auth yes # 启用认证调试测试后可关闭 auth_verbose yes # 指定认证机制 auth_mechanisms plain login # 配置SQL认证 !include auth-sql.conf.ext然后配置SQL认证的详细信息。编辑/etc/dovecot/conf.d/auth-sql.conf.extpassdb { driver sql args /etc/dovecot/dovecot-sql.conf.ext } userdb { driver sql args /etc/dovecot/dovecot-sql.conf.ext }现在创建最重要的SQL配置文件/etc/dovecot/dovecot-sql.conf.ext。这个文件告诉Dovecot如何连接数据库并查询用户信息driver mysql connect host127.0.0.1 dbnamemailserver usermailuser passwordmailuserpassword default_pass_scheme SHA512-CRYPT password_query SELECT email as user, password FROM virtual_users WHERE email%u user_query SELECT /var/mail/vhosts/%d/%u as home, 1000 as uid, 1000 as gid FROM virtual_users WHERE email%u iterate_query SELECT email as user FROM virtual_users注意再次替换password为你的数据库密码。default_pass_scheme必须与你存储在数据库中的密码加密方式一致如前文用doveadm pw -s SHA512-CRYPT生成的。user_query中的路径/var/mail/vhosts/%d/%u定义了每个用户的邮件存储目录%d代表域名部分%u代表完整邮箱地址。同样保护这个包含密码的配置文件sudo chmod 600 /etc/dovecot/dovecot-sql.conf.ext sudo chown dovecot:dovecot /etc/dovecot/dovecot-sql.conf.ext接着配置邮件存储位置Maildir。编辑/etc/dovecot/conf.d/10-mail.confmail_location maildir:/var/mail/vhosts/%d/%u创建邮件存储目录并设置正确的权限。我们假设使用UID/GID为1000的系统用户vmail来管理邮件文件你需要先创建这个用户sudo groupadd -g 1000 vmail sudo useradd -g vmail -u 1000 -d /var/mail/vhosts -s /sbin/nologin vmail sudo mkdir -p /var/mail/vhosts sudo chown -R vmail:vmail /var/mail/vhosts最后配置Dovecot提供SASL认证服务给Postfix使用。编辑/etc/dovecot/conf.d/10-master.conf找到service auth部分取消注释并修改unix_listener部分service auth { ... unix_listener /var/spool/postfix/private/auth { mode 0660 user postfix group postfix } ... }这创建了一个Unix域套接字Postfix可以通过它来请求Dovecot进行用户认证。重启Dovecot服务并设置开机自启sudo systemctl restart dovecot sudo systemctl enable dovecot3.5 配置DNS记录这是邮件服务器能被外界成功寻址和信任的关键。你需要在你的域名注册商或DNS服务商的控制面板中添加以下几条记录A记录将mail.yourdomain.com指向你的服务器公网IP地址。MX记录这是邮件交换记录告诉全世界发往yourdomain.com的邮件应该送到哪台服务器。主机记录通常为或留空代表根域名记录值填写mail.yourdomain.com优先级设置为10数字越小优先级越高。PTR记录反向DNS解析这通常需要你的服务器托管商或VPS提供商在IP管理界面设置。将你的服务器公网IP反向解析到mail.yourdomain.com。很多邮件服务商会检查PTR记录如果缺失或不匹配邮件很可能被标记为垃圾邮件。SPF记录TXT记录这是一种声明告诉别人哪些服务器有权限以你的域名发送邮件。添加一条TXT记录主机为值为vspf1 mx ~all。这表示允许你的MX记录所指的服务器即mail.yourdomain.com发送邮件其他服务器则软失败~all。DKIM记录TXT记录域名密钥识别邮件通过数字签名验证邮件的完整性和发件人。生成DKIM密钥对稍微复杂通常使用opendkim工具。这里先列出概念后续安全加固部分会详述。DMARC记录TXT记录基于SPF和DKIM定义接收方如何处理未通过验证的邮件并发送报告。例如vDMARC1; pnone; ruamailto:adminyourdomain.com。添加完DNS记录后使用dig或nslookup命令在线工具检查记录是否生效特别是MX和A记录。4. 测试与问题排查实战配置完成后不要急于用客户端连接先进行一系列基础测试可以帮你快速定位问题所在。4.1 基础服务与端口测试首先检查Postfix和Dovecot服务是否在运行并监听正确端口sudo systemctl status postfix dovecot sudo ss -tlnp | grep -E :25|:110|:143|:587|:993|:995你应该看到Postfix监听25端口SMTPDovecot监听110POP3、143IMAP、993IMAPS、995POP3S等端口。如果没看到检查防火墙firewalld或iptables是否放行了这些端口。4.2 SMTP发送测试Telnet这是最直接的测试方法。我们先用Telnet模拟SMTP对话从本地发送一封测试邮件。首先测试服务器是否能响应telnet localhost 25如果连接成功你会看到Postfix的欢迎标语。然后可以输入SMTP命令注意EHLO后面跟你的主机名MAIL FROM和RCPT TO的地址需要是你在数据库里添加的虚拟用户EHLO mail.yourdomain.com MAIL FROM: user1yourdomain.com RCPT TO: user1yourdomain.com # 可以发给自己或者另一个已存在的用户 DATA Subject: Test email from Telnet This is the body of the test email. . QUIT输入完邮件正文后单独一行输入一个英文句点.然后回车表示正文结束。如果一切正常你会看到250 2.0.0 Ok: queued as XXXXXXXXXX的响应。这封邮件应该已经被Postfix接收并准备投递到本地Dovecot管理的邮箱里。4.3 检查邮件投递与日志发送测试邮件后检查邮件是否成功投递到用户的Maildir目录。根据我们的配置邮件应该位于/var/mail/vhosts/yourdomain.com/user1yourdomain.com目录下注意目录名是完整的邮箱地址。进入该目录你应该能看到new、cur、tmp等子目录新邮件会在new目录里。sudo ls -la /var/mail/vhosts/yourdomain.com/user1yourdomain.com/Maildir/new/如果看到文件用sudo cat查看其内容应该就是你刚才发送的邮件包含原始头信息。同时查看Postfix和Dovecot的日志是排查问题的利器。日志通常位于/var/log/maillog或/var/log/mail.log。使用tail -f命令实时查看sudo tail -f /var/log/maillog然后再次进行Telnet测试观察日志输出。任何错误或警告信息都会在这里显示。4.4 客户端连接测试配置加密前在配置SSL/TLS加密之前我们可以先用邮件客户端如Thunderbird进行不加密的连接测试以验证认证和基本收发功能。在客户端添加账户时账户类型POP3或IMAP接收服务器mail.yourdomain.com端口POP3用110IMAP用143安全连接无/无用户名完整的邮箱地址如user1yourdomain.com密码你在数据库中设置的密码发送服务器SMTPmail.yourdomain.com端口25或587安全连接无/无认证勾选使用与接收服务器相同的用户名和密码如果连接失败客户端通常会给出错误信息。结合查看服务器端的日志能更精确地定位问题。4.5 常见问题与排查技巧根据我的经验新手搭建时最容易遇到以下几个问题连接被拒绝检查防火墙是否开放了相应端口25, 110, 143, 587, 993, 995。对于云服务器还要检查安全组规则。认证失败密码错误确认数据库中的密码是使用doveadm pw生成的正确格式且dovecot-sql.conf.ext中的default_pass_scheme与之匹配。用户不存在检查virtual_users表中是否存在该邮箱记录以及virtual_domains表中是否有对应的域名。SASL路径错误确认Postfix配置中smtpd_sasl_path private/auth指向的路径以及Dovecot的10-master.conf中unix_listener路径是否一致通常是/var/spool/postfix/private/auth并且权限正确postfix用户和组可访问。邮件能发不能收或反之DNS问题用dig mx yourdomain.com和dig A mail.yourdomain.com命令检查MX和A记录是否解析正确。PTR记录是否设置。Postfix配置检查main.cf中的mydestination是否包含了你的域名如果是虚拟域这里应该排除virtual_mailbox_domains是否正确指向了MySQL查询。Dovecot存储权限确保/var/mail/vhosts目录及其子目录的所有者是vmail用户和组并且Dovecot进程有读取权限。邮件被收件方判定为垃圾邮件这通常是由于缺乏正确的反向DNSPTR、SPF、DKIM、DMARC记录造成的。自建邮件服务器要进入公共邮箱的收件箱必须妥善配置这些发件人策略框架记录。5. 安全加固与高级配置基础功能跑通后我们必须立即进行安全加固一个开放的邮件服务器是黑客和垃圾邮件发送者最爱的目标。5.1 配置SSL/TLS加密使用自签名证书或从Let‘s Encrypt获取免费证书。这里以自签名证书为例生产环境建议使用Let’s Encryptsudo openssl req -new -x509 -days 3650 -nodes -out /etc/pki/tls/certs/mail.yourdomain.com.crt -keyout /etc/pki/tls/private/mail.yourdomain.com.key -subj /CNmail.yourdomain.com sudo chmod 600 /etc/pki/tls/private/mail.yourdomain.com.key然后在Postfix的main.cf中启用TLSsmtpd_tls_cert_file /etc/pki/tls/certs/mail.yourdomain.com.crt smtpd_tls_key_file /etc/pki/tls/private/mail.yourdomain.com.key smtpd_use_tls yes smtpd_tls_session_cache_database btree:${data_directory}/smtpd_scache smtpd_tls_security_level may # 强制加密可改为encrypt在Dovecot中编辑/etc/dovecot/conf.d/10-ssl.confssl required ssl_cert /etc/pki/tls/certs/mail.yourdomain.com.crt ssl_key /etc/pki/tls/private/mail.yourdomain.com.key重启Postfix和Dovecot后客户端应使用加密端口SMTP: 465/587, IMAP: 993, POP3: 995进行连接。5.2 配置DKIM签名安装opendkim并生成密钥sudo dnf install -y opendkim opendkim-tools sudo mkdir -p /etc/opendkim/keys/yourdomain.com cd /etc/opendkim/keys/yourdomain.com sudo opendkim-genkey -s mail -d yourdomain.com sudo chown -R opendkim:opendkim /etc/opendkim/keys查看公钥将其添加到域名的DNS TXT记录中主机名填写mail._domainkey值就是p后面的长字符串需要合并成一行sudo cat /etc/opendkim/keys/yourdomain.com/mail.txt配置/etc/opendkim.conf和/etc/opendkim/KeyTable、SigningTable等文件并配置Postfix通过Milter协议与OpenDKIM交互。这是一个相对复杂的步骤需要仔细阅读OpenDKIM的文档。5.3 配置防火墙与Fail2ban使用firewalld或iptables严格限制访问端口。只开放必要的服务端口SSH, HTTP/HTTPS, SMTP, SMTPS, IMAPS, POP3S。强烈建议安装Fail2ban来防止暴力破解sudo dnf install -y fail2ban sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local编辑/etc/fail2ban/jail.local启用针对Postfix、Dovecot和SSH的监控并设置合适的封禁时间和重试次数。Fail2ban会监控日志当发现多次认证失败后会自动将攻击IP加入防火墙黑名单一段时间。5.4 反垃圾邮件与防病毒可选对于生产环境可以考虑集成SpamAssassin进行垃圾邮件评分和过滤以及ClamAV进行邮件病毒扫描。这些工具可以通过配置Postfix的header_checks、body_checks或者使用amavisd-new作为内容过滤器来实现。这将会显著增加系统的复杂性和资源消耗需要根据实际需求和服务器性能来决定。6. 日常维护与监控建议邮件服务器搭建完成后日常维护同样重要。日志监控定期检查/var/log/maillog关注错误和警告信息。可以使用logwatch或fail2ban的日志分析功能。磁盘空间监控/var/mail/vhosts目录的大小防止用户邮箱撑满磁盘。可以在Postfix的main.cf中设置virtual_mailbox_limit来限制单个邮箱大小并考虑设置全局配额。队列管理偶尔会有邮件卡在队列中。使用mailq命令查看队列postsuper -d ALL删除所有队列邮件谨慎使用或者postqueue -f刷新队列。备份定期备份MySQL数据库mailserver库和/var/mail/vhosts邮件存储目录。这是你最宝贵的资产。软件更新定期使用dnf update更新系统及邮件服务器软件以获取安全补丁。搭建一个稳定、安全的邮件服务器是一个系统工程涉及网络、系统、应用和安全多个层面。这套基于PostfixDovecotMySQL的方案提供了一个坚实且可扩展的基础。在实际运营中你可能会根据邮件量、安全要求或功能需求进一步调整配置例如集成Webmail界面如Roundcube、设置更复杂的过滤规则、或者搭建邮件集群。但无论如何理解这里介绍的每一个组件和配置项的原理是解决未来可能出现的任何问题的关键。