强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

SMTP 服务器搭建完全指南 / 第 3 章:main.cf 配置详解

第 3 章:main.cf 配置详解

掌握 main.cf 的每一个关键参数,才能真正驾驭 Postfix。


3.1 配置文件概览

3.1.1 Postfix 配置文件体系

Postfix 有多个配置文件,各有分工:

文件路径作用
main.cf/etc/postfix/main.cf主配置文件(本章重点)
master.cf/etc/postfix/master.cf服务进程配置
aliases/etc/aliases系统别名
access/etc/postfix/access访问控制
transport/etc/postfix/transport邮件路由
virtual/etc/postfix/virtual虚拟用户映射
sasl_passwd/etc/postfix/sasl_passwd中继认证凭据
header_checks/etc/postfix/header_checks邮件头过滤

3.1.2 配置语法

# main.cf 语法规则:
# 1. 每行一个参数,格式:参数名 = 值
# 2. # 开头为注释
# 3. 空行被忽略
# 4. 值可引用其他参数($参数名)
# 5. 多值用逗号或空格分隔
# 6. 续行使用缩进或行尾 \

# 示例:
myhostname = mail.example.com
mydomain = example.com
myorigin = $mydomain    # 引用其他参数

3.1.3 配置管理命令

# 查看当前生效的配置(去除注释和默认值)
postconf -n

# 查看所有配置及默认值
postconf

# 查看单个参数
postconf myhostname

# 设置参数(写入 main.cf)
sudo postconf -e "myhostname = mail.example.com"

# 查看默认值
postconf -d myhostname

# 检查配置语法
sudo postfix check

# 重新加载配置
sudo systemctl reload postfix

3.2 网络与监听配置

3.2.1 inet_interfaces — 监听地址

# 监听所有网络接口(推荐生产环境使用)
inet_interfaces = all

# 仅监听本地回环
inet_interfaces = loopback-only

# 监听特定地址
inet_interfaces = 127.0.0.1, 203.0.113.10

# 使用主机名
inet_interfaces = mail.example.com

选择建议

场景推荐值说明
单机服务器all监听所有接口
仅本地收发loopback-only不对外暴露
多网卡服务器指定 IP精确控制

3.2.2 inet_protocols — 协议版本

# 仅 IPv4
inet_protocols = ipv4

# 仅 IPv6
inet_protocols = ipv6

# IPv4 和 IPv6(默认)
inet_protocols = all

3.2.3 master.cf 中的端口配置

# /etc/postfix/master.cf — 端口相关配置

# SMTP 端口 25(服务器间传输)
smtp      inet  n       -       y       -       -       smtpd

# 提交端口 587(客户端提交)
submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

# SMTPS 端口 465(隐式 TLS)
smtps     inet  n       -       y       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

3.3 域名与身份配置

3.3.1 核心域名参数

# 服务器主机名(FQDN)
myhostname = mail.example.com

# 域名
mydomain = example.com

# 发件域名(默认追加到没有 @domain 的发件地址)
myorigin = $mydomain

# 本服务器负责投递的域名
mydestination = $myhostname, $mydomain, localhost.$mydomain, localhost

3.3.2 mydestination 详解

mydestination 决定了哪些域名的邮件会被投递到本地邮箱:

# 接收发往这些域名的邮件并投递到本地
mydestination = $myhostname, $mydomain, localhost.$mydomain, localhost

# 如果要为多个域名提供服务
mydestination = $myhostname, example.com, mail.example.com, \
                example.org, localhost.$mydomain, localhost

注意mydestination 中的域名和虚拟域名(virtual domains)不能重叠。

3.3.3 发件地址伪装

# 将本地用户名伪装为完整域名地址
# 效果:本地用户 user 发出的邮件,发件地址显示为 user@example.com
myorigin = $mydomain

# 使用主机名作为发件域名
myorigin = $myhostname

3.4 中继控制(Relay Control)

3.4.1 什么是中继

中继(Relay)是指邮件服务器接收来自外部客户端的邮件,
然后转发到另一个域名的邮件服务器。

合法中继:用户通过认证后发送邮件到外部
开放中继(Open Relay):任何人都可以利用服务器发送邮件 ← 危险!

3.4.2 mynetworks — 可信网络

# 定义可信网络(这些来源的邮件允许中继)
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128

# 添加内部网络
mynetworks = 127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16

# 添加特定 IP
mynetworks = 127.0.0.0/8 203.0.113.50/32

# 使用 CIDR 格式
mynetworks = 127.0.0.0/8, 10.0.0.0/24, 192.168.1.0/24

⚠️ 安全警告mynetworks 必须精确配置,范围过大会导致服务器成为开放中继。

3.4.3 relay_domains — 允许中继的目标域名

# 允许为这些域名中继邮件
relay_domains = example.org, example.net

# 使用 hash 表文件
relay_domains = hash:/etc/postfix/relay_domains

# 禁止所有中继(仅本地投递)
relay_domains =

3.4.4 smtpd_relay_restrictions — 中继限制

# 端口 25 的中继限制(默认配置)
smtpd_relay_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_unauth_destination

# 端口 587 的中继限制(提交端口,更严格)
# 在 master.cf 中设置
# -o smtpd_relay_restrictions=permit_sasl_authenticated,reject

限制规则详解

规则作用
permit_mynetworks允许可信网络
permit_sasl_authenticated允许已认证用户
reject_unauth_destination拒绝未授权的目标域名
reject_unknown_sender_domain拒绝未知发件域名
reject_unknown_reverse_client拒绝无 PTR 记录的客户端
reject_rhsbl_reverse_client拒绝 PTR 在黑名单中的客户端

3.5 发件人与收件人限制

3.5.1 连接限制

# 每个客户端最大并发连接数
smtpd_client_connection_count_limit = 50

# 同一客户端的连接速率(次/秒)
smtpd_client_connection_rate_limit = 100

# 每个会话的最大错误次数
smtpd_soft_error_limit = 5
smtpd_hard_error_limit = 10

3.5.2 发件人限制

# 每个会话最大收件人数
smtpd_recipient_limit = 1000

# 每封邮件最大大小(字节)
message_size_limit = 10485760    # 10MB

# 邮箱最大大小(字节)
mailbox_size_limit = 5368709120  # 5GB

# 每个会话最大命令数
smtpd_error_sleep_time = 5s

3.5.3 速率限制配置

# 使用 anvil 进行速率限制
# 每个客户端每分钟最大连接数
smtpd_client_message_rate_limit = 100

# 邮件发送速率(使用 postfwd)
# 安装 postfwd
sudo apt install postfwd

# 在 main.cf 中配置
smtpd_recipient_restrictions =
    check_policy_service inet:127.0.0.1:10040,
    ...

3.6 邮件路由与传输

3.6.1 transport_maps — 传输映射

# transport 文件格式:域名    transport:nexthop

# /etc/postfix/transport
# 将 example.org 的邮件通过特定服务器中继
example.org     smtp:[mail.example.org]:25

# 将所有其他邮件通过默认路由发送
*               :

# 在 main.cf 中引用
transport_maps = hash:/etc/postfix/transport

# 生成数据库
sudo postmap /etc/postfix/transport

3.6.2 sender_dependent_relayhost — 基于发件人中继

# 不同发件人使用不同的中继服务器
# /etc/postfix/sender_relay
user1@example.com   [smtp.provider1.com]:587
user2@example.com   [smtp.provider2.com]:587
@example.com        [smtp.default.com]:587

# 在 main.cf 中配置
sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relay

3.6.3 relayhost — 统一中继

# 所有外发邮件通过特定服务器中继
relayhost = [smtp.example.com]:587

# 使用方括号避免 MX 查询
# [smtp.example.com] 表示直接连接到 smtp.example.com 的 A 记录
# 不会查询 smtp.example.com 的 MX 记录

3.7 别名与虚拟域

3.7.1 系统别名(aliases)

# /etc/aliases
# 基础别名
postmaster:     root
abuse:          root
root:           admin@example.com

# 邮件列表(一个地址转发给多人)
team:           user1@example.com, user2@example.com, user3@example.com

# 包含文件
dev-team:       :include:/etc/postfix/lists/dev-team.txt

# 管道到程序
bug-reports:    "|/usr/local/bin/bug-handler"

# 丢弃邮件
spam-trap:      /dev/null
# 修改别名后必须更新数据库
sudo newaliases

# 或者
sudo postalias /etc/aliases

3.7.2 虚拟别名(virtual alias)

# /etc/postfix/virtual
# 虚拟域名别名
admin@example.com       user1@example.com
info@example.com        user2@example.com
@example.com            catch-all@example.com

# 跨域名转发
user@example.com        user@external.com

# 在 main.cf 中配置
virtual_alias_maps = hash:/etc/postfix/virtual

# 生成数据库
sudo postmap /etc/postfix/virtual

3.7.3 虚拟域名托管

# 为多个域名提供邮件服务

# /etc/postfix/virtual_domains
example.com
example.org
example.net

# /etc/postfix/virtual
# example.com
admin@example.com       user1
user@example.com        user2

# example.org
admin@example.org       user3

# 在 main.cf 中配置
virtual_mailbox_domains = hash:/etc/postfix/virtual_domains
virtual_mailbox_maps = hash:/etc/postfix/virtual
virtual_mailbox_base = /var/mail/vhosts
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000

3.8 邮件大小与队列配置

3.8.1 邮件大小限制

# 单封邮件最大大小(字节)
message_size_limit = 10485760    # 10MB

# 邮箱总大小限制(0 = 不限制)
mailbox_size_limit = 0

# 队列文件大小限制
virtual_mailbox_limit = 0

3.8.2 队列管理配置

# 队列扫描间隔(秒)
queue_run_delay = 300

# 最小退信间隔(秒)
minimal_backoff_time = 300

# 最大退信间隔(秒)
maximal_backoff_time = 4000

# 队列生命周期(天)
maximal_queue_lifetime = 5

# 退信生命周期(天)
bounce_queue_lifetime = 5

# 队列目录
queue_directory = /var/spool/postfix

3.9 日志配置

# 日志文件路径(Debian/Ubuntu)
maillog_file = /var/log/mail.log

# RHEL/CentOS 使用 syslog
# 在 /etc/rsyslog.d/postfix.conf 中配置
# mail.*  /var/log/maillog

# 日志级别(0-5)
# 0: 仅错误和警告
# 1: 加上连接和协议信息
# 2: 加上排队信息
# 3: 加上延迟和转发信息
# 4: 加上详细调试
# 5: 极其详细(仅调试用)

3.10 业务场景:多域名邮件托管

场景描述

一家小型 ISP 需要为三个域名提供邮件托管服务:

  • company-a.com
  • company-b.com
  • company-c.com

完整配置

# /etc/postfix/main.cf — 多域名托管配置

# ==================== 基础设置 ====================
myhostname = mail.hosting-isp.com
mydomain = hosting-isp.com
myorigin = $mydomain
mydestination = localhost.$mydomain, localhost

# ==================== 虚拟域名 ====================
virtual_mailbox_domains = hash:/etc/postfix/virtual_domains
virtual_mailbox_maps = hash:/etc/postfix/virtual_mailbox
virtual_alias_maps = hash:/etc/postfix/virtual_alias
virtual_mailbox_base = /var/mail/vhosts
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_minimum_uid = 5000

# ==================== 安全限制 ====================
smtpd_relay_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_unauth_destination

message_size_limit = 20971520
mailbox_size_limit = 0

# ==================== TLS ====================
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.hosting-isp.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.hosting-isp.com/privkey.pem
smtpd_tls_security_level = may
# /etc/postfix/virtual_domains
company-a.com
company-b.com
company-c.com
# /etc/postfix/virtual_mailbox
admin@company-a.com    company-a.com/admin/
user1@company-a.com    company-a.com/user1/
admin@company-b.com    company-b.com/admin/
admin@company-c.com    company-c.com/admin/
# /etc/postfix/virtual_alias
# 别名映射
info@company-a.com     admin@company-a.com
info@company-b.com     admin@company-b.com
# 生成数据库
sudo postmap /etc/postfix/virtual_domains
sudo postmap /etc/postfix/virtual_mailbox
sudo postmap /etc/postfix/virtual_alias

# 创建目录
sudo mkdir -p /var/mail/vhosts/{company-a.com,company-b.com,company-c.com}
sudo useradd -r -u 5000 -d /var/mail vmail
sudo chown -R vmail:vmail /var/mail/vhosts

# 重新加载
sudo systemctl reload postfix

3.11 注意事项

⚠️ mydestination 与 virtual_mailbox_domains 不能重叠,否则会导致投递冲突。

  • mydestination 中的域名:邮件投递到系统用户邮箱
  • virtual_mailbox_domains 中的域名:邮件投递到虚拟用户邮箱

⚠️ 修改 main.cf 后必须重新加载

sudo systemctl reload postfix
# 或
sudo postfix reload

💡 使用 postconf 而非手动编辑

# 推荐方式(自动写入 main.cf)
sudo postconf -e "myhostname = mail.example.com"

# 不推荐方式(容易出错)
sudo vi /etc/postfix/main.cf

3.12 扩展阅读


上一章← 第 2 章:Postfix 安装与基础配置 下一章第 4 章:SASL 认证与 Dovecot 集成 →