☰
从零搭建Postfix SMTP发信服务:DNS、认证与反垃圾实战
2026/10/23 9:13:53 网站建设 项目流程

1. 从一个真实需求说起:为什么自建邮件发送服务

很多做后端开发或者运维的朋友都遇到过这样的场景:项目上线后需要给用户发验证码、发通知邮件、发告警邮件,一开始图省事直接用第三方邮件推送服务,量小的时候免费额度够用,量一大就开始收费,而且到达率、发信域名信誉这些都不在自己手里。更麻烦的是,有些内部系统产生的邮件本身就包含敏感的业务数据,走第三方通道总让人觉得不太踏实。

这时候自建一个SMTP发信服务就成了一个很自然的选择。而在Linux世界里,Postfix几乎是搭建邮件传输代理(MTA)的首选方案。它稳定、性能好、配置灵活,而且经过二十多年的迭代,社区资料非常丰富。但问题也恰恰出在这里——Postfix的配置项太多了,官方文档又偏向手册风格,新手照着网上的教程一步步做,经常卡在某个环节就发不出邮件,或者发出去直接被对方拒收。

这篇内容就是把我自己从零搭建一套可对外发送邮件的Postfix SMTP服务的完整过程梳理出来。所谓“可对外发送”,指的是这套服务不仅能给本机或者内网发信,还能把邮件投递到外部邮箱服务商(比如常见的公共邮箱域名)。这中间涉及DNS记录配置、发信认证、加密传输、反垃圾策略等一系列环节,任何一个没处理好都可能导致邮件发不出去或者进了对方的垃圾箱。

适合阅读这篇内容的人包括:需要为业务系统搭建独立发信通道的后端开发者、负责维护公司邮件基础设施的运维人员,以及对邮件协议本身感兴趣想动手实践的技术爱好者。我会尽量把每个配置项背后的逻辑讲清楚,而不是只给一堆命令让你复制粘贴。毕竟邮件系统的坑实在太多了,不理解原理的话,出了问题根本无从下手排查。

2. 动手之前必须想清楚的几件事

2.1 自建发信服务和第三方推送的本质区别

很多人觉得自建SMTP就是装个软件配个密码的事,这个认知偏差会导致后面踩很多坑。第三方邮件推送服务之所以能保证较高的到达率,是因为它们维护了大量独立IP、做了完善的域名信誉管理、有专门的团队跟各大邮箱服务商做反馈循环。你自己搭一套,这些工作全部要自己扛。

具体来说,自建发信服务需要你自己处理的问题包括:发信IP的信誉积累(新IP直接大量发信基本必进垃圾箱)、反向DNS解析记录(PTR记录,很多接收方会检查)、SPF和DKIM签名(用来证明邮件确实是你发的)、以及退信处理和投诉反馈机制。这些不是Postfix本身能解决的,而是整个邮件生态的规则。

所以我的建议是:如果你的发信量每天只有几十封,用第三方服务更省心;如果发信量大、对数据隐私有要求、或者需要深度定制发信逻辑,那自建才划算。这个判断很重要,因为它决定了你愿意在这上面投入多少精力。

2.2 搭建前需要准备的基础条件

在开始安装Postfix之前,有几样东西必须先准备好,否则后面会反复返工。

第一是一台有公网IP的服务器。这个不用多说,没有公网IP就没法对外投递邮件。需要注意的是,很多云服务商默认封禁了25端口(SMTP的标准端口),你需要提前确认或者申请解封。如果25端口出站被封,可以考虑用587端口(提交端口)配合认证来发信,这是目前更推荐的做法。

第二是一个属于你自己的域名。你需要能修改这个域名的DNS记录,因为后面要配置MX记录、SPF记录、DKIM记录和DMARC记录。用别人的域名或者免费二级域名基本行不通,因为很多接收方会直接拒绝这类域名的邮件。

第三是确认服务器的操作系统和Postfix版本。我用的环境是主流的Linux发行版,Postfix版本在3.x以上。不同发行版的包管理命令和默认配置路径会有差异,下面的操作我会尽量标注清楚。

提示:在正式配置之前,先确认服务器的防火墙规则。除了25和587端口,如果需要接收退信,还要考虑开放其他必要端口。出站方向一般不需要额外配置,但有些云平台的安全组会限制出站流量,这个要提前检查。

2.3 关于发信IP的一个残酷现实

新申请的云服务器IP,大概率已经在某些反垃圾邮件组织的黑名单里了。这不是你的问题,而是因为之前可能有其他用户用这个IP发过垃圾邮件。所以在正式发信之前,建议先查一下自己的IP是否在常见黑名单中。如果已经在黑名单里,需要先申请移除,否则你配置得再完美,邮件也发不出去。

另外,新IP需要一个“预热”过程。不要一上来就群发大量邮件,而是应该从少量开始,逐步增加发信量,让接收方逐渐建立对你这个IP的信任。这个过程可能需要几周时间。如果业务紧急,可以考虑购买已经有一定信誉的IP或者使用专业的发信中继服务。

3. Postfix的安装与基础配置拆解

3.1 安装过程中的包选择问题

在主流Linux发行版上安装Postfix,通常会遇到一个交互式配置界面,让你选择“General type of mail configuration”。这个选择决定了Postfix的默认配置模板,选错了后面要改很多地方。

常见的选项有Internet Site、Internet with smarthost、Satellite system、Local only等。对于我们要搭建的对外发信服务,应该选“Internet Site”,这个模式会直接把邮件通过SMTP投递到收件人的邮件服务器。如果你选了“Satellite system”,所有邮件都会被转发到一台中继服务器,那就不符合我们自建发信的需求了。

安装过程中还会让你填写“System mail name”,这个应该填你的主域名,比如example.com。这个值会作为默认的发信域名后缀,影响邮件的From地址和HELO/EHLO标识。

安装完成后,Postfix的主配置文件通常在/etc/postfix/main.cf,这是我们需要重点调整的文件。另外还有一个master.cf,控制各个服务进程的监听方式和参数,一般不需要大改,但后面配置提交端口时会用到。

3.2 main.cf里最关键的几个参数

main.cf的配置项有上百个,但真正影响对外发信的核心参数就那么几个。我按重要性逐个说明。

myhostname:这个参数设置服务器的主机名,会用在SMTP会话的HELO/EHLO命令中。很多接收方会检查这个值是否是一个合法的域名,以及是否和你的IP有正向解析对应关系。建议设置成mail.example.com这种形式,并且确保这个域名有A记录指向你的服务器IP。

mydomain:你的主域名,一般设置成example.com。这个参数会影响很多默认值的生成。

myorigin:发信时使用的源域名,通常设置为$mydomain。它决定了邮件地址中@后面的部分。

inet_interfaces:监听哪些网络接口。如果要对外提供服务,需要设置为all或者指定具体的公网IP。默认可能是localhost,那样只能本机发信。

mydestination:这个参数定义了Postfix认为哪些域名是“本地”的,发给这些域名的邮件会被本地投递而不是转发出去。这里要特别注意,不要把你自己用来对外发信的域名放进去,否则发给自己的邮件会被本地处理而不是走外部投递。

mynetworks:定义哪些网络被认为是可信的,来自这些网络的连接不需要认证就可以发信。默认通常包含127.0.0.0/8和本机网段。如果你的业务服务器和邮件服务器在同一内网,可以把内网网段加进去,这样内网应用发信就不需要配置认证了。

relayhost:如果你需要通过上游中继发信,可以在这里指定。但既然我们是自建直接投递,这个参数留空即可。

这些参数配置好之后,用postfix check命令检查语法,然后用systemctl reload postfix重载配置。每次改完main.cf都建议先check再reload,避免配置错误导致服务起不来。

3.3 理解Postfix的队列机制

Postfix收到一封邮件后,并不是立刻投递出去的,而是先放进队列,然后由不同的进程按优先级处理。这个设计的好处是解耦了接收和投递,即使目标服务器暂时不可达,邮件也不会丢失,而是会在队列里等待重试。

队列分为几类:maildrop队列存放刚收到还没处理的邮件,incoming队列存放正在处理的邮件,active队列存放正在投递的邮件,deferred队列存放暂时投递失败的邮件。你可以用mailq命令查看当前队列情况,用postqueue -f手动触发重试。

理解这个机制对排查问题很重要。比如你发现邮件发出去了但对方没收到,可以先看mailq里有没有堆积,如果有,看deferred队列里的错误信息,通常会告诉你具体是什么原因导致的投递失败,比如连接超时、被拒绝、DNS解析失败等。

4. 让邮件能真正发出去的关键环节

4.1 DNS记录配置:SPF、DKIM、DMARC一个都不能少

邮件能不能送达,很大程度上取决于DNS记录配置得对不对。这部分是很多自建邮件服务的人最容易忽略的,也是最容易导致邮件进垃圾箱的原因。

SPF记录:SPF的全称是Sender Policy Framework,它通过一条TXT记录告诉接收方,哪些IP有权代表你的域名发信。配置格式大概是这样的:v=spf1 mx ip4:你的服务器IP -all。这里的-all表示除了列出的IP,其他所有IP发来的邮件都视为伪造。如果你还有别的发信渠道,需要把它们也加进去。SPF记录只能有一条,多条会导致解析失败。

DKIM记录:DKIM是DomainKeys Identified Mail的缩写,它通过给邮件加上数字签名,让接收方可以验证邮件在传输过程中没有被篡改,并且确实是由你的域名发出的。配置DKIM需要先生成一对密钥,私钥放在服务器上给Postfix使用,公钥以TXT记录的形式发布到DNS。DKIM的好处是即使邮件被转发,签名依然有效,而SPF在转发场景下会失效。

DMARC记录:DMARC建立在SPF和DKIM之上,它告诉接收方当SPF和DKIM验证失败时应该怎么处理邮件,以及把报告发到哪里。一条典型的DMARC记录是:v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com。这里的p=quarantine表示验证失败的邮件应该被隔离,初期建议先用p=none只收集报告不做处理,观察一段时间后再收紧策略。

这三条记录配合使用,才能最大程度保证你的邮件被正确识别和投递。配置完成后,可以用一些在线的邮件测试工具发一封测试邮件,看看各项验证是否通过。

4.2 反向DNS解析:容易被忽视的硬性要求

反向DNS解析,也就是PTR记录,是把IP地址解析回域名的记录。很多大型邮箱服务商在接收邮件时,会检查发信IP是否有PTR记录,以及PTR记录解析出的域名是否和HELO/EHLO中声明的域名一致。如果不一致或者根本没有PTR记录,邮件很可能被直接拒绝或者标记为垃圾邮件。

PTR记录不是你在自己域名的DNS管理后台能设置的,而是需要你的服务器IP提供商来配置。大部分云服务商的控制面板里都有申请反向解析的入口,你提交申请后,他们会帮你把IP的PTR记录指向你指定的域名。这个域名最好就是你的mail.example.com,和myhostname保持一致。

这里有个细节:PTR记录的正向解析也要能对应上。也就是说,mail.example.com的A记录应该指向你的服务器IP,这样IP到域名、域名到IP就形成了一个闭环,这在邮件领域叫做“正反向解析一致”,是建立IP信誉的基础。

4.3 发信认证配置:SASL的集成

如果你的邮件服务器需要给多个客户端或者应用提供发信服务,就需要配置发信认证,防止被当成开放中继被人滥用。Postfix本身不提供认证功能,需要配合SASL(Simple Authentication and Security Layer)来实现。

在主流Linux发行版上,通常用Cyrus SASL或者Dovecot SASL。我个人更推荐用Dovecot SASL,因为配置相对简单,而且如果你后面还要搭IMAP/POP3服务,Dovecot本来就要装,一举两得。

配置的大致步骤是:安装Dovecot,在Dovecot的配置中启用SASL认证服务,然后在Postfix的main.cf中指定使用Dovecot的SASL socket。具体参数包括smtpd_sasl_type = dovecot、smtpd_sasl_path指向Dovecot的认证socket路径、smtpd_sasl_auth_enable = yes等。

配置完成后,需要创建邮箱用户。如果用Dovecot,可以用系统用户或者虚拟用户。虚拟用户更灵活,不依赖系统账号,适合多域名多用户的场景。创建好用户后,用testsaslauthd或者直接用邮件客户端测试认证是否正常。

注意:启用认证后,一定要确保mynetworks里没有包含你不信任的网段,否则来自这些网段的连接可以绕过认证直接发信,等于开了开放中继,很快就会被滥用。

4.4 加密传输:TLS证书的配置

现在几乎所有主流邮件服务商都要求或者推荐使用TLS加密传输邮件。没有TLS的话,邮件内容在网络上是明文传输的,不仅不安全,而且很多接收方会直接降低你的信誉评分。

配置TLS需要一张证书。你可以用Let's Encrypt申请免费证书,也可以用商业证书。证书配置在main.cf中的smtpd_tls_cert_file和smtpd_tls_key_file参数里指定。同时建议设置smtpd_tls_security_level = may,表示支持但不强制TLS,这样兼容性更好。如果对安全要求高,可以设为encrypt强制加密,但可能会导致一些老旧的客户端无法连接。

除了入站TLS,出站投递时也建议启用TLS。Postfix默认会尝试用机会性TLS(opportunistic TLS)投递,也就是如果对方支持TLS就用,不支持就明文。这个行为由smtp_tls_security_level控制,默认值通常是may,保持默认即可。

证书配置好后,可以用openssl s_client -connect mail.example.com:587 -starttls smtp命令测试TLS握手是否正常。如果输出中能看到证书信息和TLS版本,说明配置成功。

5. 踩坑实录:那些让我折腾半天的典型问题

5.1 邮件发出去了但对方说没收到

这是最常见的问题,也是最难排查的。因为从你的角度看,邮件已经离开了队列,日志里也显示投递成功,但对方就是没收到。这种情况通常有几个原因。

第一个可能是邮件进了对方的垃圾箱。这个最普遍,尤其是新IP或者DNS记录没配好的情况下。解决办法是让对方检查垃圾箱,同时用邮件测试工具检查自己的SPF、DKIM、DMARC是否全部通过。如果有一项没通过,优先解决那一项。

第二个可能是邮件被对方静默丢弃了。有些邮件服务商对于判定为垃圾邮件的来信,不会退信也不会放到垃圾箱,而是直接丢弃。这种情况下你的日志会显示投递成功(因为对方服务器返回了250 OK),但实际上邮件根本没到用户手里。要确认这一点,只能通过DMARC报告或者对方管理员协助排查。

第三个可能是你的邮件被自己的服务器处理了。检查mydestination参数,如果你把发信域名也放进去了,那发给这个域名的邮件会被本地投递,而不是发到外部。这个坑我在第一次搭建时就踩过,排查了半天才发现是mydestination配置的问题。

5.2 连接被拒绝:端口和防火墙的排查链路

有一次配置完成后,本机测试发信正常,但从外部客户端连接587端口总是被拒绝。排查过程是这样的:先用telnet mail.example.com 587测试,发现连接直接被拒绝,说明端口根本没通。然后在服务器上用ss -tlnp查看监听状态,发现Postfix确实在监听587端口。那问题就出在防火墙或者安全组了。

检查本机防火墙规则,发现587端口没有放行。添加规则后还是不行,又检查云平台的安全组,发现安全组的入站规则里也没有587端口。两处都放行后,连接终于正常了。

这个排查链路可以总结为:客户端测试确认现象,服务器本地检查监听状态,然后逐层检查本机防火墙和云平台安全组。每一步都要确认,不要假设某一层已经配好了。

5.3 被当成开放中继:一次危险配置的教训

开放中继是指你的邮件服务器允许任何人通过它发送邮件到任何目的地。这是非常危险的,因为垃圾邮件发送者会很快发现并利用你的服务器,导致你的IP被拉黑,甚至被云服务商封禁。

我见过一个典型的错误配置:在main.cf中设置了smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination,但mynetworks的值被错误地设置成了0.0.0.0/0,也就是允许所有IP无需认证发信。这等于把服务器变成了开放中继。

正确的做法是:mynetworks只包含你信任的内网网段,比如127.0.0.0/8和你的业务服务器所在的内网段。对于外部客户端,必须通过SASL认证才能发信。smtpd_relay_restrictions参数要确保包含defer_unauth_destination,这样未认证的请求发往外部域名时会被拒绝。

配置完成后,可以用在线的开放中继测试工具检测一下,确认自己的服务器没有这个问题。这个检查应该成为每次修改配置后的固定动作。

5.4 大附件被拒:message_size_limit的调整

Postfix默认的邮件大小限制是10MB左右,超过这个大小的邮件会被拒绝。如果你的业务需要发送较大的附件,需要调整message_size_limit参数。这个参数的单位是字节,比如要设置成50MB,就写message_size_limit = 52428800。

但要注意,这个值不能超过接收方的限制。大部分公共邮箱服务商的附件大小限制在25MB到50MB之间,你设置得再大,对方也收不了。另外,邮件大小限制还和邮箱配额、磁盘空间有关,设置过大可能导致队列积压。

还有一个容易忽略的地方:如果你用了内容过滤器(比如Amavisd),内容过滤器本身也可能有大小限制,需要同步调整。否则邮件虽然被Postfix接收了,但在过滤环节被拒绝,日志里会出现看起来不相关的错误。

6. 上线后的日常维护与监控要点

6.1 日志分析:从maillog里读出有用信息

Postfix的日志通常在/var/log/maillog或者/var/log/mail.log,具体路径取决于发行版。日志里记录了每一封邮件的完整生命周期,包括接收、队列处理、投递尝试、投递结果等。

几个关键的状态码需要记住:status=sent表示投递成功,status=deferred表示暂时失败会重试,status=bounced表示永久失败会退信,status=rejected表示被拒绝。看到deferred不要慌,先看后面的原因描述,常见的有连接超时、对方服务器繁忙、DNS解析失败等。

如果日志量很大,可以用grep配合关键字过滤。比如grep "status=bounced" /var/log/maillog可以快速找出所有退信的邮件。grep "to=<" /var/log/maillog可以按收件人过滤。建议把常用的日志分析命令整理成脚本,方便日常巡检。

6.2 队列监控:防止邮件堆积

邮件队列堆积是邮件服务器最常见的故障表现。原因可能是目标服务器不可达、DNS故障、网络问题、或者被大量退信拖慢。不管什么原因,队列堆积都会导致新邮件投递延迟,严重时可能撑满磁盘。

监控队列长度可以用mailq | tail -1命令,它会输出队列中邮件总数。建议设置一个阈值,比如超过100封就告警。另外,deferred队列里的邮件如果超过一定时间(默认5天)会被退信,这个时间由maximal_queue_lifetime参数控制,可以根据业务需求调整。

如果发现队列异常增长,先用mailq看看堆积的邮件有什么共同特征,比如都是发往同一个域名的,那可能是对方服务器出了问题;如果都是同一类错误,比如连接超时,那可能是网络问题。定位到原因后再针对性处理,不要盲目清空队列。

6.3 发信信誉的持续维护

发信信誉不是一次配置好就一劳永逸的,需要持续维护。几个关键动作包括:定期检查自己的IP是否被列入黑名单、监控DMARC报告了解邮件验证通过率、及时处理用户的投诉和退信请求、避免发送用户没有订阅的邮件。

DMARC报告是一个很有价值的工具。配置好DMARC记录后,你指定的邮箱会定期收到各大邮箱服务商发来的报告,里面详细列出了有多少邮件通过了SPF和DKIM验证,有多少失败了,失败的来源IP是哪里。如果发现有大量失败记录来自你不知道的IP,说明可能有人在伪造你的域名发信,需要进一步调查。

另外,如果业务量增长,发信量突然大幅增加,也可能触发接收方的风控机制。建议发信量增长要平缓,不要短时间内暴增。如果确实有大规模发信需求,提前和主要的接收方沟通,或者考虑使用专业的发信中继服务。

7. 一些让配置更稳的进阶技巧

7.1 用传输映射控制特定域名的投递方式

Postfix的transport_maps功能可以让你针对特定域名指定投递方式。比如你发现发给某个域名的邮件总是被拒,可以配置通过一个中继服务器投递。或者你有一些内部域名需要走特定的网关,也可以用这个功能。

配置方法是创建一个transport文件,格式是域名 传输方式:目标,比如example.net smtp:[relay.example.com]。然后在main.cf中设置transport_maps = hash:/etc/postfix/transport,用postmap命令生成数据库文件后重载配置。

这个功能在混合云或者多邮件系统的环境中特别有用,可以灵活控制邮件流向,而不需要改动整体架构。

7.2 速率限制:避免被误判为垃圾邮件发送者

短时间内向同一个域名发送大量邮件,很容易被对方判定为垃圾邮件行为。Postfix提供了几种速率限制机制,可以在main.cf中配置。

smtpd_client_connection_rate_limit限制单个客户端IP在单位时间内的连接数。smtpd_client_message_rate_limit限制单个客户端在单位时间内发送的邮件数。anvil_rate_time_unit定义时间单位,默认是60秒。

这些限制主要针对入站连接,防止被滥用。对于出站投递,Postfix也有default_destination_rate_delay参数,可以设置向同一个目标域名投递邮件之间的延迟,避免发送过快。这个值设置成几秒到几十秒比较合适,具体取决于你的发信量和对方的要求。

7.3 备份与迁移:配置文件的版本管理

邮件服务器的配置文件虽然不多,但每一项都很关键。建议把/etc/postfix/目录下的配置文件纳入版本管理,每次修改都提交一次,这样出问题可以快速回滚,也方便迁移到新服务器。

需要备份的文件包括main.cf、master.cf、transport、virtual等映射文件,以及TLS证书和DKIM私钥。DKIM私钥尤其重要,丢了的话所有已签名的邮件验证都会失败,需要重新生成密钥并更新DNS记录。

迁移到新服务器时,除了配置文件,还要注意队列目录的迁移。如果旧服务器上还有未投递的邮件,直接迁移队列目录可以保留这些邮件。但要注意权限和属主,Postfix对队列目录的权限要求比较严格,权限不对会导致服务起不来。

7.4 测试策略:上线前必须做的几项验证

在正式上线之前,建议做一轮完整的测试。测试内容包括:本机发信测试、内网发信测试、外部发信测试、认证发信测试、TLS加密测试、大附件测试、退信处理测试。

本机和内网测试可以用sendmail命令或者mail命令直接发。外部发信测试建议用几个不同的邮箱服务商,比如发到常见的公共邮箱,看看是否能正常收到,以及是否进了垃圾箱。认证测试可以用swaks这个工具,它能模拟SMTP会话的完整过程,方便调试认证和TLS问题。

测试过程中要同时观察日志,确认每一步的状态码都符合预期。如果某个环节失败,根据日志中的错误信息定位问题。测试通过后再正式上线,可以避免很多上线后的紧急故障。

8. 个人经验总结

这套Postfix发信服务我从第一次搭建到现在,前后折腾了大概两周时间才算是比较稳定。中间踩过的坑包括DNS记录配错导致DKIM验证失败、mynetworks设置过宽差点变成开放中继、PTR记录没配导致邮件被拒、以及队列堆积把磁盘撑满。每一个问题都让我对邮件系统的运作机制有了更深的理解。

如果让我给准备自建邮件服务的人一个建议,那就是:先把DNS记录和IP信誉这些外部条件准备好,再去折腾Postfix本身的配置。因为邮件能不能送达,很大程度上不取决于你的Postfix配得多好,而取决于你的域名和IP在接收方那里的信誉。Postfix只是一个投递工具,它无法替你解决信誉问题。

另外,不要怕看日志。Postfix的日志信息其实很详细,大部分问题都能从日志里找到线索。养成每次修改配置后观察日志的习惯,时间长了就能快速定位常见问题。邮件系统虽然复杂,但它的规则是确定的,理解了规则之后,排查问题就是按图索骥的事。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询