openSUSE15.6: postfix-dovecot-mariadb-搭建邮件服务器
标题是“指南”,纯粹是为了SEO,博主水平有限,不足之处,希望网友们批评指正。
背景 我在AWS购买一台配置为2C2G的lightsail轻型VPS云主机,由于工作繁忙,一直闲置。 恰逢26年春节假期,一下子有了大量空闲时间,本着物尽其用的原则,决定搭建邮件服务器。 这事儿如果成了,以后就拥有独家域名的邮箱,自己用起来随心所欲,还能分享给亲戚朋友,岂不美哉?
但说起来容易,做起来煞费周折。
一个原因是docker技术的普及,很多邮件方案均已打包成镜像,使用起来简单、方便。 另外一个原因,postfix系列软件安装、配置繁琐,还涉及域名解析及邮件服务专用的潜规则,对于普通人,有一定难度。
现在大部分云计算厂商封禁25端口,历尽千辛,服务搭建完成后,你大概率会卡在这一步。 博主的解决方案是,使用”AWS Simple Email Service(SES)”邮件代理,只需要在postfix添加配置即可。
在搭建过程中,大量依赖deepseek 和chatGPT , 感谢强大的人工智能技术~!
当然,如果把VPS当作玩具,折腾起来乐在其中,是不错的消磨时间的方式。
邮件服务搭建方案 Postfix是什么? Postfix是 MTA(Mail Transfer Agent),负责发信和收信传输。
它干的事:
接收外部服务器发来的邮件
把邮件转发到目标服务器
发送你服务器用户发出的邮件
跟别的邮件服务器SMTP通信
它只负责“传输”。
Dovecot是什么? Dovecot是MDA+IMAP/POP3 Server , 负责“存储”和“让用户读取”。
它干的事:
管理邮箱目录(Maildir)
提供IMAP/POP3给客户端
负责用户认证
可提供SASL认证给Postfix使用
它只负责“用户访问”。
完整邮件流程(从外部发到你) 假设别人给你发邮件
流程:
对方SMTP连接到你的服务器25端口
Postfix接收邮件
Postfix把邮件投递到本地邮箱目录
Dovecot读取该目录
Outlook/手机等使用IMAP协议连接Dovecot读取邮件
流程图:
1 2 3 4 5 6 7 8 9 外部服务器 ↓ 25 Postfix ↓ Maildir ↑ Dovecot ↑ 993 Outlook
从你发邮件到外部 1 Outlook -> 你的服务器 -> Gmail
流程:
Outlook连接587端口
Dovecot提供SASL认证
Postfix验证用户名和密码
Postfix把邮件发给目标MX
流程图:
1 2 3 4 5 6 7 Outlook ↓ 587 Dovecot → mariadb ↓ ↑验证密码 Postfix ↓ 25 目标服务器
二者如何配合? 核心协作点在:
SASL认证
Postfix自己不掌管密码。
它通常使用:
1 2 smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth
代表
Postfix把认证交给Dovecot
所以:
Dovecot = 账户系统
Postfix = 传输系统
邮件存储目录
默认情况下,Postfix投递到
Dovecot读取同一个目录,二者共享存储。
必须开放的端口
25 - SMTP收信(服务器与服务器之间通信) - 必须
587 - SMTP提交(客户端提交邮件,必须开启认证) - 建议
993 - IMAPS(客户端收邮件,加密) - 必须
可选端口
465 - SMTPS(旧标准)
110 - POP3
995 - POP3S
142 - IMAP明文
生产级端口策略 1 2 3 4 5 # 仅开放以下,其他全部关闭。 25 587 993
软件版本
postfix-3.8.4-150600.3.3.1.x86_64
dovecot23-2.3.15-150200.65.1.x86_64
mariadb-10.11.15-150600.4.17.1.x86_64
使用zypper命令安装,上面是主要组件的版本号,其他组件不再展示。
搭建过程 准备工作
一台具有IPv4地址的vps云主机(至少1C1G,性能够用)
一个拥有完全解析权限的国际域名。 以上,建议均在国外运营商购买,国内要求域名备案等,相对繁琐。
deepseek/chatGPT,提供专家咨询。
一个自行注册、可以登录的gmail邮箱,后期用作收件测试和排障。
操作系统(openSUSE Leap 15.6) 为什么使用openSUSE ?
博主具备5年以上”SUSE Linux Enterprise Server (SLES)”生产一线使用经验,不论硬件服务器(戴尔)系统安装,还是应用搭建维护,都非常熟悉。 个人认为,SuSE系统是除Redhat系列外,最稳定、易用的发行版,非常省心。
Server就绪后,第一步,应该执行系统级安全加固和配置优化,可以问deepseek,此处略过。
系统更新 1 2 3 4 5 6 # 更新系统 sudo zypper refresh sudo zypper update # 重启(必须) sudo reboot
软件安装 安装基础组件 1 2 3 4 5 6 7 8 9 10 # 安装主要组件和中间依赖 zypper install postfix postfix-mysql mariadb-server mariadb dovecot dovecot-mysql cyrus-sasl cyrus-sasl-plain # 如果不想安装冗余,可以添加 "--no-recommends" 参数。 zypper install --no-recommends postfix postfix-mysql mariadb-server mariadb dovecot dovecot-mysql cyrus-sasl cyrus-sasl-plain # 设置开机自启动 systemctl enable --now mariadb systemctl enable --now postfix systemctl enable --now dovecot
基础软件安装好后,会同时向系统添加用户和用户组,检查/etc/passwd和/etc/group,发现新增”opendkim”, “unbound”, “maildrop”, “vmail”, “postfix”, “dovecot”等,后续安装会涉及,最好检查一下。
配置Mysql 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 # 配置mysql数据库 # 执行后,按照提示,一步一步操作。 # 删除匿名账户和测试数据库,为root设置密码,同时禁用root远程登录。 mysql_secure_installation -- 创建数据库 CREATE DATABASE mailserver; USE mailserver; -- 创建虚拟域表 CREATE TABLE virtual_domains ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL UNIQUE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 创建虚拟用户表 CREATE TABLE virtual_users ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, domain_id INT NOT NULL, email VARCHAR(100) NOT NULL UNIQUE, password VARCHAR(106) NOT NULL, -- 存储加密后的密码 FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 创建别名表 CREATE TABLE virtual_aliases ( id INT NOT NULL AUTO_INCREMENT 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 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 创建数据库用户并授权 CREATE USER 'mailuser'@'localhost' IDENTIFIED BY 'your_password'; -- 注意,这里是赋查询权限,下一步添加用户时,要使用root登录,操作这张表。 GRANT SELECT ON mailserver.* TO 'mailuser'@'localhost'; FLUSH PRIVILEGES;
Let’s Encrypt证书 安装过程中,Let’s Encrypt 的服务器访问到当前服务器上的临时验证文件 。 所以需要:
开放80端口
安装nginx
配置域名解析,为申请证书的域名,创建一个A记录解析,指向当前服务器的IP
安装证书申请工具 1 2 3 4 5 #安装 Certbot 和 Nginx 插件(Nginx用于验证域名所有权) sudo zypper install nginx certbot python3-certbot-nginx #运行 Certbot 获取证书(替换为你的真实域名) sudo certbot certonly --nginx -d mail.example.com
使用独立目录存放证书 1 2 3 4 5 6 7 8 9 #使用独立目录存放证书 sudo mkdir /etc/postfix/certs sudo cp /etc/letsencrypt/live/mail.wisepkg.com/fullchain.pem /etc/postfix/certs/ sudo cp /etc/letsencrypt/live/mail.wisepkg.com/privkey.pem /etc/postfix/certs/ #设置权限 sudo chown root:postfix /etc/postfix/certs/privkey.pem sudo chmod 640 /etc/postfix/certs/privkey.pem sudo chmod 644 /etc/postfix/certs/fullchain.pem
配置定时任务 1 2 3 4 # 编辑root用户的crontab sudo crontab -e # 添加以下行(假设Certbot的续期路径正确) 0 0,12 * * * certbot renew --deploy-hook "cp /etc/letsencrypt/live/mail.wisepkg.com/*.pem /etc/postfix/certs/ && systemctl reload postfix"
配置postfix 文件备份 1 cp /etc/postfix/main.cf /etc/postfix/main.cf.backup
注意: /etc/postfix/main.cf.default, 这是配置模板,如果必须的参数在main.cf没有找到,会从该模板文件读取。
main.cf(适用于使用AWS SES服务做发送代理) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 ############################ # 基础身份,保留原配置 ############################ compatibility_level = 3.8 queue_directory = /var/spool/postfix command_directory = /usr/sbin daemon_directory = /usr/lib/postfix/bin/ data_directory = /var/lib/postfix mail_owner = postfix sendmail_path = /usr/sbin/sendmail newaliases_path = /usr/bin/newaliases mailq_path = /usr/bin/mailq setgid_group = maildrop html_directory = /usr/share/doc/packages/postfix-doc/html manpage_directory = /usr/share/man sample_directory = /usr/share/doc/packages/postfix-doc/samples readme_directory = /usr/share/doc/packages/postfix-doc/README_FILES biff = no # 替换为你的域名 myhostname = mail.example.com mydomain = example.com myorigin = $mydomain inet_interfaces = all inet_protocols = ipv4 mydestination = $myhostname, localhost.$mydomain, localhost mynetworks = 127.0.0.0/8 [::1]/128 unknown_local_recipient_reject_code = 550 recipient_delimiter = + ############################ # SMTP 安全限制 ############################ smtpd_banner = $myhostname ESMTP default_destination_concurrency_limit = 20 smtpd_recipient_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination smtpd_sender_restrictions = reject_non_fqdn_sender reject_unknown_sender_domain smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination smtpd_helo_required = yes disable_vrfy_command = yes smtpd_forbid_bare_newline = yes smtpd_forbid_bare_newline_exclusions = $mynetworks ############################ # SASL (Dovecot) ############################ smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_sasl_auth_enable = yes smtpd_sasl_security_options = noanonymous smtpd_sasl_tls_security_options = noanonymous ############################ # TLS - 服务端 ############################ smtpd_use_tls = yes smtpd_tls_cert_file = /etc/postfix/certs/fullchain.pem smtpd_tls_key_file = /etc/postfix/certs/privkey.pem smtpd_tls_security_level = may smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtpd_tls_ciphers = medium smtpd_tls_mandatory_ciphers = medium smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache ############################ # TLS - 客户端 (发往 SES) ############################ smtp_tls_security_level = encrypt smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtp_tls_ciphers = medium smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache smtp_tls_note_starttls_offer = yes ############################ # SES Relay 配置 # AWS封禁25端口,使用AWS SES邮件投递代理服务 ############################ relayhost = [email-smtp.ap-southeast-1.amazonaws.com]:587 smtp_sasl_auth_enable = yes smtp_sasl_password_maps = texthash:/etc/postfix/sasl_passwd smtp_sasl_security_options = noanonymous smtp_sasl_mechanism_filter = plain,login ############################ # 虚拟邮箱 + LMTP ############################ virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf, mysql:/etc/postfix/mysql-virtual-email2email.cf virtual_mailbox_base = /var/mail/vhosts virtual_uid_maps = static:5000 virtual_gid_maps = static:5000 virtual_minimum_uid = 1000 virtual_mailbox_limit = 1073741824 virtual_transport = lmtp:unix:private/dovecot-lmtp ############################ # 邮件大小限制 ############################ message_size_limit = 20971520 mailbox_size_limit = 0 ############################ # 别名 ############################ alias_maps = lmdb:/etc/aliases alias_database = lmdb:/etc/aliases ############################ # 打印日志 ############################ smtpd_tls_loglevel = 2 ############################ # 其他继续保留 ############################ delay_warning_time = 1h masquerade_classes = envelope_sender, header_sender, header_recipient masquerade_exceptions = root canonical_maps = lmdb:/etc/postfix/canonical relocated_maps = lmdb:/etc/postfix/relocated sender_canonical_maps = lmdb:/etc/postfix/sender_canonical transport_maps = lmdb:/etc/postfix/transport mail_spool_directory = /var/mail message_strip_characters = \0
master.cf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 smtp inet n - n - - smtpd submission inet n - y - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject -o smtpd_tls_auth_only=yes -o smtpd_reject_unlisted_recipient=no -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_relay_restrictions=permit_sasl_authenticated,reject -o milter_macro_daemon_name=ORIGINATING -o smtpd_client_connection_count_limit=10 -o smtpd_client_connection_rate_limit=20 pickup fifo n - n 60 1 pickup cleanup unix n - n - 0 cleanup qmgr fifo n - n 300 1 qmgr rewrite unix - - n - - trivial-rewrite bounce unix - - n - 0 bounce defer unix - - n - 0 bounce trace unix - - n - 0 bounce verify unix - - n - 1 verify flush unix n - n 1000? 0 flush proxymap unix - - n - - proxymap proxywrite unix - - n - 1 proxymap smtp unix - - n - - smtp relay unix - - n - - smtp -o syslog_name=postfix/$service_name showq unix n - n - - showq error unix - - n - - error retry unix - - n - - error discard unix - - n - - discard local unix - n n - - local virtual unix - n n - - virtual lmtp unix - - n - - lmtp anvil unix - - n - 1 anvil scache unix - - n - 1 scache tlsmgr unix - - n 1000? 1 tlsmgr postlog unix-dgram n - n - 1 postlogd dovecot unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}
重启postfix服务 1 systemctl restart postfix
检查postfix配置
查看所有配置项
验证25端口证书读取 1 2 3 4 5 # 服务端 openssl s_client -connect localhost:25 -starttls smtp -showcerts # 客户端 openssl s_client -connect mail.example.com:587 -starttls smtp
查看postfix日志 1 journalctl -u postfix -f
上面的main.cf 是使用了AWS Simple Email Service 邮件代理,在开放25端口的场景下,让chatGPT重新整理了一份配置。 当然,这种场景下,DNS涉及A记录/PTR/SPF/DKIM/DMARC的配置也会发生改变。
main.cf(仅供参考) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 # 基础身份 myhostname = mail.yourdomain.com mydomain = yourdomain.com myorigin = $mydomain inet_interfaces = all inet_protocols = ipv4 # 域设置 mydestination = $myhostname, localhost.$mydomain, localhost virtual_mailbox_domains = yourdomain.com virtual_transport = lmtp:unix:private/dovecot-lmtp # 网络信任 mynetworks = 127.0.0.0/8 # 严格禁止开放中继 smtpd_relay_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination # 基础反垃圾 smtpd_helo_required = yes disable_vrfy_command = yes smtpd_delay_reject = yes smtpd_helo_restrictions = reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname smtpd_sender_restrictions = reject_non_fqdn_sender, reject_unknown_sender_domain smtpd_recipient_restrictions = reject_non_fqdn_recipient, reject_unknown_recipient_domain # TLS 服务端 smtpd_tls_cert_file = /etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem smtpd_tls_key_file = /etc/letsencrypt/live/mail.yourdomain.com/privkey.pem smtpd_tls_security_level = may smtpd_tls_auth_only = yes smtpd_tls_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1 smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1 smtpd_tls_ciphers = high smtpd_tls_mandatory_ciphers = high # TLS 客户端(直投必须验证) smtp_tls_security_level = verify smtp_tls_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1 smtp_tls_loglevel = 1 # SASL 认证(交给 dovecot) smtpd_sasl_auth_enable = yes smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth broken_sasl_auth_clients = yes # 邮箱目录 virtual_mailbox_base = /var/mail/vhosts virtual_minimum_uid = 1000 # 限制并发(防止被利用发垃圾) default_process_limit = 100 smtpd_client_connection_count_limit = 20 smtpd_client_connection_rate_limit = 30 # 日志 maillog_file = /var/log/mail.log
创建postfix依赖文件 /etc/postfix/mysql-virtual-mailbox-domains.cf (查询域名)
1 2 3 4 5 user = mailuser password = your_password hosts = localhost dbname = mailserver query = SELECT 1 FROM virtual_domains WHERE name='%s'
/etc/postfix/mysql-virtual-mailbox-maps.cf (查询用户邮箱)
1 2 3 4 5 user = mailuser password = your_password hosts = localhost dbname = mailserver query = SELECT 1 FROM virtual_users WHERE email='%s'
/etc/postfix/mysql-virtual-alias-maps.cf (查询别名)
1 2 3 4 5 user = mailuser password = your_password hosts = localhost dbname = mailserver query = SELECT destination FROM virtual_aliases WHERE source='%s'
重要:将上述文件中的 your_password 替换为你为数据库 mailuser 设置的密码。
设置文件权限
1 2 3 # 这些文件包含数据库密码,必须确保安全。 chmod 640 /etc/postfix/mysql-virtual-*.cf chgrp postfix /etc/postfix/mysql-virtual-*.cf
配置dovecot /etc/dovecot/dovecot.conf (主配置文件) 1 2 3 protocols = imap pop3 listen = * !include conf.d/*.conf
/etc/dovecot/conf.d/10-auth.conf (认证和数据库配置) 1 2 3 4 5 # 禁用系统用户登录,启用SQL认证 disable_plaintext_auth = yes auth_mechanisms = plain login !include auth-sql.conf.ext # 注释掉系统用户认证行: #!include auth-system.conf.ext
/etc/dovecot/conf.d/auth-sql.conf.ext (SQL数据库配置) 1 2 3 4 5 6 7 8 passdb { driver = sql args = /etc/dovecot/dovecot-sql.conf.ext } userdb { driver = static args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n }
/etc/dovecot/dovecot-sql.conf.ext (SQL连接配置文件) 1 2 3 4 5 6 driver = mysql connect = host=localhost dbname=mailserver user=mailuser password=your_password default_pass_scheme = SHA512-CRYPT password_query = SELECT email as user, password FROM virtual_users WHERE email='%u'; ## 迭代次数(使用doveadm默认值) iterate_query = SELECT email AS user FROM virtual_users
/etc/dovecot/conf.d/10-mail.conf (邮件位置) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 ## 邮件存储位置(Maildir格式) # %d - 域名 # %n - 用户名 mail_location = maildir:/var/mail/vhosts/%d/%n ## 邮件目录权限 mail_privileged_group = mail ## 邮箱格式 maildir_stat_dirs = yes maildir_copy_with_hardlinks = yes ## 收件箱命名空间 namespace inbox { inbox = yes type = private separator = / prefix = hidden = no list = yes subscriptions = yes # 各种系统文件夹 mailbox Drafts { special_use = \Drafts auto = subscribe } mailbox Junk { special_use = \Junk auto = subscribe } mailbox Trash { special_use = \Trash auto = subscribe } mailbox Sent { special_use = \Sent auto = subscribe } } mail_plugin_dir = /usr/lib64/dovecot/modules protocol !indexer-worker { }
/etc/dovecot/conf.d/10-master.conf (主服务配置) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 ## 主服务配置 service imap-login { inet_listener imap { port = 143 } inet_listener imaps { port = 993 ssl = yes } } service pop3-login { inet_listener pop3 { port = 110 } inet_listener pop3s { port = 995 ssl = yes } } service lmtp { unix_listener /var/spool/postfix/private/dovecot-lmtp { mode = 0600 user = postfix group = postfix } } ## Postfix SASL认证关键配置 service auth { unix_listener /var/spool/postfix/private/auth { mode = 0660 user = postfix group = postfix } unix_listener auth-userdb { mode = 0600 user = vmail } } service auth-worker { user = vmail }
/etc/dovecot/conf.d/10-ssl.conf (SSL配置) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ## SSL强制启用 ssl = required # ### 证书路径(请替换example.com) ssl_cert = </etc/postfix/certs/fullchain.pem ssl_key = </etc/postfix/certs/privkey.pem # ### 协议版本(Dovecot 2.3.15支持TLSv1.3[citation:3]) ssl_min_protocol = TLSv1.2 ssl_cipher_list = PROFILE=SYSTEM ssl_prefer_server_ciphers = yes # ### Diffie-Hellman参数(安全性增强) ssl_dh = </etc/dovecot/dh.pem
/etc/dovecot/conf.d/20-lmtp.conf (LMTP配置) 1 2 3 4 5 ## LMTP服务(接收Postfix投递) protocol lmtp { mail_plugins = $mail_plugins sieve postmaster_address = postmaster@example.com }
/etc/dovecot/conf.d/15-lda.conf (LDA配置) 1 2 3 4 5 6 7 ## 本地投递代理 protocol lda { mail_plugins = $mail_plugins sieve postmaster_address = postmaster@example.com deliver_log_format = msgid=%m: %$ rejection_reason = Your message to <%t> was automatically rejected:%n%r }
生成 Diffie-Hellman 参数(SSL强化) 1 2 3 4 5 6 7 8 9 10 11 12 13 #方案一: openssl dhparam -out /etc/dovecot/dh.pem 4096 chmod 600 /etc/dovecot/dh.pem #方案二: # 速度快,几秒到几分钟即可完成(推荐) openssl dhparam -dsaparam -out /etc/dovecot/dh.pem 4096 #文件属主设为 root:dovecot(或 root:root) chown root:dovecot /etc/dovecot/dh.pem #权限设置为 640(root可读写,dovecot组可读) chmod 640 /etc/dovecot/dh.pem
创建虚拟用户 1 2 ## 检查是否已创建(之前Postfix步骤应该已创建) id vmail || groupadd -g 5000 vmail && useradd -g vmail -u 5000 vmail -d /var/mail/vhosts -m
设置权限 1 2 3 ## 确保邮件存储目录权限正确 chown -R vmail:vmail /var/mail/vhosts chmod 755 /var/mail/vhosts
创建邮件存储目录 1 2 3 4 # 域名目录(如果手动创建)同样设置 sudo mkdir -p /var/mail/vhosts/example.com sudo chown vmail:vmail /var/mail/vhosts/example.com sudo chmod 755 /var/mail/vhosts/example.com
注意:你只需要创建到域名级别的目录(/var/mail/vhosts/wisepkg.com/),用户级目录 Dovecot 会自动创建。
创建用户 创建用户密码 1 2 3 4 # 假设密码是 Password123 sudo doveadm pw -s SHA512-CRYPT -p 'Password123' # 输出 {SHA512-CRYPT}$6$CaxxQ4e6VgnZiX0C$rClI9yGQIidEt92nsB3ZTpTt80O.V6U4cO0gTyJUYtSGBnzyaMt5.if3ecu9Bq4be0Sw69Eu9xAVZOetd5cPV.
向数据库中新增用户 (root登录) 1 INSERT INTO virtual_users (domain_id, email, password) VALUES ('1', 'chao.dong@wisepkg.com', '{SHA512-CRYPT}$6$CaxxQ4e6VgnZiX0C$rClI9yGQIidEt92nsB3ZTpTt80O.V6U4cO0gTyJUYtSGBnzyaMt5.if3ecu9Bq4be0Sw69Eu9xAVZOetd5cPV.')
dovecot验证用户密码 1 2 3 doveadm auth test user@wisepkg.com '用户密码' # 成功会显示 doveadm auth test user@wisepkg.com '用户密码'
添加用户完成,即可使用邮件客户端连接测试。
Debug记录 证书权限 1 2 3 4 5 sudo -u postfix cat /etc/letsencrypt/live/example.wisepkg.com/privkey.pem 报错: Permission denied 说明需要将证书文件拷贝出来,单独存放,别忘了修改main.cf中的证书位置。
SSL连接587端口报错 (该问题由chatGPT协助解决) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 openssl s_client -connect localhost:587 -starttls smtp -showcerts CONNECTED(00000003) 807B37821C7F0000:error:0A00010B: SSL routines:ssl3_get_record:wrong version number:ssl/record/ssl3_record.c:355: --- no peer certificate available --- No client certificate CA names sent --- SSL handshake has read 240 bytes and written 328 bytes Verification: OK --- New, (NONE), Cipher is (NONE) This TLS version forbids renegotiation. Compression: NONE Expansion: NONE No ALPN negotiated Early data was not sent Verify return code: 0 (ok) --- # 这个报错排查了好久,最后查看postfix日志,才定位根因。 sudo journalctl -u postfix -n 50 --no-pager ... warning: connect to private/tlsmgr: No such file or directory warning: problem talking to server private/tlsmgr warning: no entropy for TLS key generation: disabling TLS support ... 表明: 🔴 Postfix 的 TLS 管理进程 tlsmgr 没有运行 👉 所以 TLS 被禁用 👉 STARTTLS 被 advertise 👉 但 TLS 实际不可用 👉 OpenSSL 报 wrong version number 解决方案: # postfix配置文件master.cf添加一行: tlsmgr unix - - n 1000? 1 tlsmgr # 完整示例: anvil unix - - n - 1 anvil scache unix - - n - 1 scache tlsmgr unix - - n 1000? 1 tlsmgr # 修改完重启postfix , 重新测试,问题解决。