自建邮箱系统的一些经验总结与流程SOP

之前为本论坛寻找邮件服务商屡遭挫败,最终决定自建SMTP服务器。以SMTP服务器以后就可以进行发件了,但是还不能收件,一直心痒痒。遂决定建立一个完整的可发件,可收件,有web邮箱界面的邮箱系统。这里就当是一篇博客记录(技术分享?)吧。网上自建邮箱系统的帖子不少,但详细度参差不齐。在这里以一个流程总结的方式写一篇自己的分享。

先搞一个VPS

你需要有一个公网IP,所以你应该要找一个公网服务器。这个公网服务器基本的要求是要开放25端口出站,25端口入站(很多服务器或者云计算服务商是不会给你开放25端口的,这个比较特别,主要也是防电子邮件欺诈和滥用);其次,你还需要开放一些别的端口,但别的端口一般不封;哦,可选锦上添花地,最好这家服务商提供PTR反向解析服务(但实测下来不提供似乎也行,比方说我现在正在用的就没PTR)

来点便宜推荐?我用的是 [野草云](野草云|香港云主机|香港vps|香港服务器|美国服务器)(塞个aff哈哈)。这个不错,我用的是99包年hk。国内大厂服务商基本上都不会给开25(实测下来,阿里云不给开阿里云必须买他的ECS,且是大公司有营业资质之类的,过审核才可能给开。客服表示小公司都不行,个人,哪怕是学生,当然也都不行),所以基本上你都得看一些境外的。RackNerd听说听有名气,但是客服回我好慢:(

野草云开25出站是没阻碍的(这就离谱,也可能只是去年9月没阻碍,我是在那个时候开的),25入站却要申请你要提工单,然后他会让你交25$的保证金,保证你不会发一些垃圾邮件什么的。如果没有举报投诉的话,在租期到的时候会退给你。美中不足的就是他们居然不提供PTR。

当然你还要一个域名

你要买一个你自己心仪的域名,因为这样就能控制特定的dns解析记录,也是你邮箱系统的安身立命之本。

下面就是部署SOP了

• 下面是这次我做的工作总结,并整理成可复用的 SOP(收件/发件/Webmail/SSL/DNS/端口开放全覆盖)。我保留了旧域(系统用户)不动,并新增了 SQL 虚拟域 <MAIL_DOMAIN>(我这里是 test.lsamc.website),对应邮箱 xxx@<MAIL_DOMAIN>

Scope

  • 架构:Postfix + Dovecot (IMAP/LMTP) + MariaDB + Roundcube + Nginx + Let’s Encrypt + OpenDKIM

  • 新域独立配置:<MAIL_DOMAIN>;邮件主机 mail.<MAIL_DOMAIN>;Webmail webmail.<MAIL_DOMAIN>

  • 旧域:mail.nju-aia.lsamc.website 保持系统用户模式不变

DNS 解析

  • A 记录

    • mail.<MAIL_DOMAIN> → 服务器公网 IP

    • webmail.<MAIL_DOMAIN> → 服务器公网 IP

  • MX 记录

    • <MAIL_DOMAIN> → mail.<MAIL_DOMAIN>(优先级 10)
  • TXT 记录

    • SPF(最小可用)
      <MAIL_DOMAIN> TXT “v=spf1 mx -all”

    • DKIM(由 OpenDKIM 生成)
      mail._domainkey.<MAIL_DOMAIN> TXT “v=DKIM1; k=rsa; p=…”

    • DMARC(建议)
      _dmarc.<MAIL_DOMAIN> TXT “v=DMARC1; p=none; rua=mailto:postmaster@<MAIL_DOMAIN>

端口开放

  • 必开:25(SMTP 入站),587(Submission),993(IMAPS),443(Webmail)

  • 可选:80(Let’s Encrypt HTTP-01,签SSL证书用的)

  • 说明:需要云厂商安全组 + 服务器本地防火墙都放行;PTR 反向解析不会阻止入站,但会影响对外投递信誉。

系统与依赖安装

这里以debian/ubuntu系为例

sudo apt update
sudo apt install -y postfix dovecot-core dovecot-imapd dovecot-lmtpdmariadb-server opendkim opendkim-toolsnginx php-fpm php-mysql roundcube roundcube-core roundcube-mysqlcertbot python3-certbot-nginx

虚拟用户与目录

(这个拉胯点当然可以不建,就直接让自己的账号管理也行)

sudo useradd -r -u 5000 -g 5000 -d /var/vmail -m vmail
sudo chown -R vmail:vmail /var/vmail

数据库(MariaDB)

CREATE DATABASE mailserver;
CREATE USER ‘mailuser’@‘127.0.0.1’ IDENTIFIED BY ‘REPLACE_WITH_STRONG_PASS’;
GRANT SELECT ON mailserver.* TO ‘mailuser’@‘127.0.0.1’;
FLUSH PRIVILEGES;

USE mailserver;
CREATE TABLE virtual_domains (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL);
CREATE TABLE virtual_users (id INT AUTO_INCREMENT PRIMARY KEY,domain_id INT NOT NULL,password VARCHAR(106) NOT NULL,email VARCHAR(100) NOT NULL,FOREIGN KEY (domain_id) REFERENCES virtual_domains(id));
CREATE TABLE virtual_aliases (id INT 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));

INSERT INTO virtual_domains (name) VALUES (‘<MAIL_DOMAIN>’);– 密码用 doveadm pw -s SHA512-CRYPT 生成 hash
INSERT INTO virtual_users (domain_id, password, email)VALUES (1, ‘{SHA512-CRYPT}HASH_HERE’, ‘admin@<MAIL_DOMAIN>’);

Postfix 配置(发件/收件核心)

  • 关键配置路径

    • /etc/postfix/main.cf

    • /etc/postfix/master.cf

    • /etc/postfix/mysql-virtual-domains.cf

    • /etc/postfix/mysql-virtual-users.cf

    • /etc/postfix/mysql-virtual-aliases.cf

  • /etc/postfix/main.cf 关键项

virtual_mailbox_base = /var/vmail
virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual-domains.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual-users.cf
virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual-aliases.cf
virtual_uid_maps = static:5000virtual_gid_maps = static:5000
virtual_transport = lmtp:unix:private/dovecot-lmtp
  • /etc/postfix/master.cf(启用 587 Submission)
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
  • MySQL map 文件示例 /etc/postfix/mysql-virtual-domains.cf
user = mailuser
password = REPLACE_WITH_STRONG_PASS
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name=‘%s’

Dovecot 配置(IMAP + LMTP)

  • 关键配置路径

    • /etc/dovecot/dovecot.conf

    • /etc/dovecot/conf.d/10-mail.conf

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

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

    • /etc/dovecot/conf.d/10-master.conf

    • /etc/dovecot/conf.d/10-ssl.conf

  • SQL 认证(SQL 在前,系统用户在后)/etc/dovecot/conf.d/10-auth.conf

!include auth-sql.conf.ext
!include auth-system.conf.ext
  • LMTP socket(交给 Postfix)/etc/dovecot/conf.d/10-master.conf
service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}
  • SQL 文件/etc/dovecot/dovecot-sql.conf.ext
driver = mysql
connect = host=127.0.0.1 dbname=mailserver user=mailuser password=REPLACE_WITH_STRONG_PASS
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email as user, password FROM virtual_users WHERE email=‘%u’;
  • 生成邮箱目录
sudo mkdir -p /var/vmail/<MAIL_DOMAIN>/admin/Maildir/{cur,new,tmp}
sudo chown -R vmail:vmail /var/vmail/<MAIL_DOMAIN>/admin

OpenDKIM(签名出站邮件)

  • 关键路径

    • /etc/opendkim/KeyTable

    • /etc/opendkim/SigningTable

    • /etc/opendkim/TrustedHosts

  • 生成并配置

sudo mkdir -p /etc/opendkim/keys/<MAIL_DOMAIN>
sudo opendkim-genkey -D /etc/opendkim/keys/<MAIL_DOMAIN> -d <MAIL_DOMAIN> -s mail
sudo chown -R opendkim:opendkim /etc/opendkim/keys/<MAIL_DOMAIN>

  • DNS 使用 etc/opendkim/keys/<MAIL_DOMAIN>/mail.txt 中的 TXT 记录。

SSL(Let’s Encrypt,多域证书)

sudo certbot --nginx -d mail.nju-aia.lsamc.website -d mail.<MAIL_DOMAIN> -d webmail.<MAIL_DOMAIN>
  • Postfix/Dovecot 使用同一证书

    • /etc/letsencrypt/live/mail.nju-aia.lsamc.website/fullchain.pem

    • /etc/letsencrypt/live/mail.nju-aia.lsamc.website/privkey.pem

Roundcube Webmail

  • 配置文件:/etc/roundcube/config.inc.php
$config[‘imap_host’] = [‘ssl://mail.<MAIL_DOMAIN>:993’];
$config[‘smtp_host’] = ‘tls://mail.<MAIL_DOMAIN>:587’;
$config[‘smtp_user’] = ‘%u’;
$config[‘smtp_pass’] = ‘%p’;
$config[‘des_key’] = ‘RANDOM_24+_CHARS’;
  • Nginx 站点:/etc/nginx/sites-available/webmail.<MAIL_DOMAIN>

    • 指向 /var/lib/roundcube

    • PHP-FPM 处理 PHP

  • 启用并重载

sudo ln -s /etc/nginx/sites-available/webmail.<MAIL_DOMAIN> /etc/nginx/sites-enabled/
sudo systemctl reload nginx

验证步骤

  • DNS 验证

dig +short MX <MAIL_DOMAIN>
dig +short A mail.<MAIL_DOMAIN>

  • 端口监听

sudo ss -ltnp | egrep ‘:25|:587|:993|:443’

  • SMTP/IMAP 测试

nc -vz mail.<MAIL_DOMAIN> 25
openssl s_client -connect mail.<MAIL_DOMAIN>:587 -starttls smtp
openssl s_client -connect mail.<MAIL_DOMAIN>:993

  • 日志查看

    • /var/log/mail.log

嗯实际上,上面的SOP是我让GPT根据我的操作记录生成的SOP,要是有什么BUG欢迎捉虫~ (以及如果有问题可以让codex来帮你排查,我就是codex帮安装的,比之前对着GPT的建议一点一点改快了不只一星半点哈哈,而且应该比大多数一知半解状态下配出的千奇百怪的安全漏洞配置高到不知道哪去了 :laughing: )不过既然是自己的服务器那发生了什么,每步在干什么还是要知道的,发生问题了也能第一时间有思路,AI做综合检查太慢了。

另外codex附赠了一段参考脚本:

#!/usr/bin/env bash
set -euo pipefail

if [[ "${EUID}" -ne 0 ]]; then
  echo "Please run as root (sudo bash $0)."
  exit 1
fi

# ====== Defaults (edit or override via prompts) ======
DOMAIN_DEFAULT="test.lsamc.website"
ADMIN_USER_DEFAULT="admin"
DB_NAME="mailserver"
DB_USER="mailuser"
VMAIL_UID="5000"
VMAIL_GID="5000"
VMAIL_HOME="/var/vmail"
OPENDKIM_KEYDIR="/etc/opendkim/keys"

read -r -p "Mail domain [${DOMAIN_DEFAULT}]: " DOMAIN
DOMAIN="${DOMAIN:-$DOMAIN_DEFAULT}"
MAIL_HOST="mail.${DOMAIN}"
WEBMAIL_HOST="webmail.${DOMAIN}"

read -r -p "Admin mailbox user [${ADMIN_USER_DEFAULT}]: " ADMIN_USER
ADMIN_USER="${ADMIN_USER:-$ADMIN_USER_DEFAULT}"
ADMIN_EMAIL="${ADMIN_USER}@${DOMAIN}"

read -r -s -p "DB password for ${DB_USER}: " DB_PASS
echo
read -r -s -p "Admin mailbox password (${ADMIN_EMAIL}): " ADMIN_PASS
echo

CERT_NAME="${MAIL_HOST}"
CERT_DOMAINS=("${MAIL_HOST}" "${WEBMAIL_HOST}")

echo "Using:"
echo "  Domain: ${DOMAIN}"
echo "  Mail host: ${MAIL_HOST}"
echo "  Webmail host: ${WEBMAIL_HOST}"
echo "  Admin email: ${ADMIN_EMAIL}"
echo "  Cert name: ${CERT_NAME}"

echo
echo "== Install packages =="
apt update
DEBIAN_FRONTEND=noninteractive apt install -y \
  postfix dovecot-core dovecot-imapd dovecot-lmtpd \
  mariadb-server opendkim opendkim-tools \
  nginx php-fpm php-mysql roundcube roundcube-core roundcube-mysql \
  certbot python3-certbot-nginx

echo
echo "== Create vmail user =="
if ! getent passwd vmail >/dev/null; then
  groupadd -g "${VMAIL_GID}" vmail
  useradd -r -u "${VMAIL_UID}" -g "${VMAIL_GID}" -d "${VMAIL_HOME}" -m vmail
fi
chown -R vmail:vmail "${VMAIL_HOME}"

echo
echo "== MariaDB schema/user =="
mysql <<SQL
CREATE DATABASE IF NOT EXISTS ${DB_NAME};
CREATE USER IF NOT EXISTS '${DB_USER}'@'127.0.0.1' IDENTIFIED BY '${DB_PASS}';
GRANT SELECT ON ${DB_NAME}.* TO '${DB_USER}'@'127.0.0.1';
FLUSH PRIVILEGES;
USE ${DB_NAME};
CREATE TABLE IF NOT EXISTS virtual_domains (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50) NOT NULL,
  UNIQUE KEY name (name)
);
CREATE TABLE IF NOT EXISTS virtual_users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  domain_id INT NOT NULL,
  password VARCHAR(106) NOT NULL,
  email VARCHAR(100) NOT NULL,
  UNIQUE KEY email (email),
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS virtual_aliases (
  id INT AUTO_INCREMENT PRIMARY KEY,
  domain_id INT NOT NULL,
  source VARCHAR(100) NOT NULL,
  destination VARCHAR(100) NOT NULL,
  UNIQUE KEY source (source),
  FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
);
INSERT INTO virtual_domains (name) VALUES ('${DOMAIN}')
  ON DUPLICATE KEY UPDATE name=VALUES(name);
SET @did = (SELECT id FROM virtual_domains WHERE name='${DOMAIN}');
INSERT INTO virtual_users (domain_id, password, email)
  VALUES (@did, '{SHA512-CRYPT}$(doveadm pw -s SHA512-CRYPT -p "${ADMIN_PASS}")', '${ADMIN_EMAIL}')
  ON DUPLICATE KEY UPDATE password=VALUES(password), domain_id=VALUES(domain_id);
SQL

echo
echo "== Postfix MySQL maps =="
cat >/etc/postfix/mysql-virtual-domains.cf <<EOF
user = ${DB_USER}
password = ${DB_PASS}
hosts = 127.0.0.1
dbname = ${DB_NAME}
query = SELECT 1 FROM virtual_domains WHERE name='%s'
EOF

cat >/etc/postfix/mysql-virtual-users.cf <<EOF
user = ${DB_USER}
password = ${DB_PASS}
hosts = 127.0.0.1
dbname = ${DB_NAME}
query = SELECT 1 FROM virtual_users WHERE email='%s'
EOF

cat >/etc/postfix/mysql-virtual-aliases.cf <<EOF
user = ${DB_USER}
password = ${DB_PASS}
hosts = 127.0.0.1
dbname = ${DB_NAME}
query = SELECT destination FROM virtual_aliases WHERE source='%s'
EOF

echo
echo "== Postfix main.cf =="
postconf -e "myhostname = ${MAIL_HOST}"
postconf -e "mydomain = ${DOMAIN}"
postconf -e "myorigin = \$mydomain"
postconf -e "mydestination = \$myhostname, localhost.\$mydomain, localhost"
postconf -e "virtual_mailbox_base = ${VMAIL_HOME}"
postconf -e "virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual-domains.cf"
postconf -e "virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual-users.cf"
postconf -e "virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual-aliases.cf"
postconf -e "virtual_uid_maps = static:${VMAIL_UID}"
postconf -e "virtual_gid_maps = static:${VMAIL_GID}"
postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"
postconf -e "smtpd_sasl_type = dovecot"
postconf -e "smtpd_sasl_path = private/auth"
postconf -e "smtpd_sasl_auth_enable = yes"
postconf -e "smtpd_tls_security_level = may"
postconf -e "smtpd_milters = unix:/opendkim/opendkim.sock"
postconf -e "non_smtpd_milters = unix:/opendkim/opendkim.sock"
postconf -e "milter_default_action = accept"
postconf -e "milter_protocol = 6"

echo
echo "== Postfix submission (587) =="
if ! grep -q '^submission' /etc/postfix/master.cf; then
  cat >>/etc/postfix/master.cf <<'EOF'

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
EOF
fi

echo
echo "== Dovecot SQL auth =="
cat >/etc/dovecot/dovecot-sql.conf.ext <<EOF
driver = mysql
connect = host=127.0.0.1 dbname=${DB_NAME} user=${DB_USER} password=${DB_PASS}
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';
user_query = SELECT '/var/vmail/%d/%n' as home, 'maildir:/var/vmail/%d/%n/Maildir' as mail, ${VMAIL_UID} as uid, ${VMAIL_GID} as gid FROM virtual_users WHERE email='%u';
EOF
chown root:dovecot /etc/dovecot/dovecot-sql.conf.ext
chmod 0640 /etc/dovecot/dovecot-sql.conf.ext

echo
echo "== Dovecot config tweaks =="
sed -i 's/^#listen = .*/listen = */' /etc/dovecot/dovecot.conf
sed -i 's|^#\!include_try /usr/share/dovecot/protocols.d/\*\.protocol|!include_try /usr/share/dovecot/protocols.d/*.protocol|' /etc/dovecot/dovecot.conf

if ! grep -q 'auth-sql.conf.ext' /etc/dovecot/conf.d/10-auth.conf; then
  sed -i 's/^!include auth-system.conf.ext/!include auth-sql.conf.ext\n!include auth-system.conf.ext/' /etc/dovecot/conf.d/10-auth.conf
fi

if ! grep -q 'dovecot-lmtp' /etc/dovecot/conf.d/10-master.conf; then
  cat >>/etc/dovecot/conf.d/10-master.conf <<'EOF'

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}
EOF
fi

if ! grep -q 'ssl_min_protocol' /etc/dovecot/conf.d/10-ssl.conf; then
  cat >>/etc/dovecot/conf.d/10-ssl.conf <<'EOF'
ssl_min_protocol = TLSv1.2
ssl_cipher_list = HIGH:!aNULL:!MD5
EOF
fi

echo
echo "== Create Maildir =="
MAILDIR="${VMAIL_HOME}/${DOMAIN}/${ADMIN_USER}/Maildir"
mkdir -p "${MAILDIR}"/{cur,new,tmp}
chown -R vmail:vmail "${VMAIL_HOME}/${DOMAIN}/${ADMIN_USER}"

echo
echo "== OpenDKIM =="
mkdir -p /opendkim
chown opendkim:opendkim /opendkim

mkdir -p "${OPENDKIM_KEYDIR}/${DOMAIN}"
if [[ ! -f "${OPENDKIM_KEYDIR}/${DOMAIN}/mail.private" ]]; then
  opendkim-genkey -D "${OPENDKIM_KEYDIR}/${DOMAIN}" -d "${DOMAIN}" -s mail
  chown -R opendkim:opendkim "${OPENDKIM_KEYDIR}/${DOMAIN}"
fi

grep -q "${DOMAIN}" /etc/opendkim/KeyTable || \
  echo "mail._domainkey.${DOMAIN} ${DOMAIN}:mail:${OPENDKIM_KEYDIR}/${DOMAIN}/mail.private" >>/etc/opendkim/KeyTable
grep -q "${DOMAIN}" /etc/opendkim/SigningTable || \
  echo "*@${DOMAIN} mail._domainkey.${DOMAIN}" >>/etc/opendkim/SigningTable
grep -q "${DOMAIN}" /etc/opendkim/TrustedHosts || \
  echo "${DOMAIN}" >>/etc/opendkim/TrustedHosts

echo
echo "== Nginx sites =="
PHP_FPM_SOCK="$(find /run/php -name 'php*-fpm.sock' 2>/dev/null | head -n1)"
if [[ -z "${PHP_FPM_SOCK}" ]]; then
  PHP_FPM_SOCK="/run/php/php-fpm.sock"
fi
cat >/etc/nginx/sites-available/"${MAIL_HOST}" <<EOF
server {
  listen 80;
  server_name ${MAIL_HOST};
  return 404;
}
EOF

cat >/etc/nginx/sites-available/"${WEBMAIL_HOST}" <<EOF
server {
  listen 80;
  server_name ${WEBMAIL_HOST};
  root /var/lib/roundcube;
  index index.php;

  location / {
    try_files \$uri \$uri/ /index.php;
  }

  location ~ \\.php\$ {
    include fastcgi_params;
    fastcgi_pass unix:${PHP_FPM_SOCK};
    fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
  }
}
EOF

ln -sf /etc/nginx/sites-available/"${MAIL_HOST}" /etc/nginx/sites-enabled/
ln -sf /etc/nginx/sites-available/"${WEBMAIL_HOST}" /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx

echo
echo "== TLS certs (LetsEncrypt) =="
certbot --nginx --cert-name "${CERT_NAME}" \
  $(printf -- "-d %q " "${CERT_DOMAINS[@]}")

postconf -e "smtpd_tls_cert_file = /etc/letsencrypt/live/${CERT_NAME}/fullchain.pem"
postconf -e "smtpd_tls_key_file = /etc/letsencrypt/live/${CERT_NAME}/privkey.pem"

sed -i "s|^#\\?ssl_cert = .*|ssl_cert = </etc/letsencrypt/live/${CERT_NAME}/fullchain.pem|" /etc/dovecot/conf.d/10-ssl.conf
sed -i "s|^#\\?ssl_key = .*|ssl_key = </etc/letsencrypt/live/${CERT_NAME}/privkey.pem|" /etc/dovecot/conf.d/10-ssl.conf

echo
echo "== Roundcube config =="
RC_CONF="/etc/roundcube/config.inc.php"
if [[ ! -f "${RC_CONF}" ]]; then
  cp /etc/roundcube/config.inc.php.dist "${RC_CONF}"
fi
DES_KEY=$(openssl rand -base64 24)
perl -0777 -i -pe "s|\\$config\\['imap_host'\\].*?;|\\$config['imap_host'] = ['ssl://${MAIL_HOST}:993'];|s" "${RC_CONF}"
perl -0777 -i -pe "s|\\$config\\['smtp_host'\\].*?;|\\$config['smtp_host'] = 'tls://${MAIL_HOST}:587';|s" "${RC_CONF}"
perl -0777 -i -pe "s|\\$config\\['smtp_user'\\].*?;|\\$config['smtp_user'] = '%u';|s" "${RC_CONF}"
perl -0777 -i -pe "s|\\$config\\['smtp_pass'\\].*?;|\\$config['smtp_pass'] = '%p';|s" "${RC_CONF}"
perl -0777 -i -pe "s|\\$config\\['des_key'\\].*?;|\\$config['des_key'] = '${DES_KEY}';|s" "${RC_CONF}"

echo
echo "== Optional UFW rules =="
if command -v ufw >/dev/null 2>&1; then
  ufw allow 25/tcp
  ufw allow 587/tcp
  ufw allow 993/tcp
  ufw allow 80/tcp
  ufw allow 443/tcp
fi

echo
echo "== Restart services =="
systemctl restart opendkim
systemctl restart postfix
systemctl restart dovecot
systemctl reload nginx

echo
echo "== Done =="
echo "DNS required:"
echo "  A  ${MAIL_HOST} -> <your_public_ip>"
echo "  A  ${WEBMAIL_HOST} -> <your_public_ip>"
echo "  MX ${DOMAIN} -> ${MAIL_HOST} (priority 10)"
echo "  SPF TXT: v=spf1 mx -all"
echo "  DKIM TXT: $(cat "${OPENDKIM_KEYDIR}/${DOMAIN}/mail.txt" 2>/dev/null | tr -d '\"' | tr -d '\n')"
echo "  DMARC TXT (optional): v=DMARC1; p=none; rua=mailto:postmaster@${DOMAIN}"
6 个赞

太详细了!伟大 :smiling_face_with_three_hearts:

2 个赞

非常有价值的记录:heart_eyes:

1 个赞

确实很有帮助,落地性强

1 个赞

https://linux.do/t/topic/1666961

也可以看看cloudflare搭建域名邮箱,免费额度够够的。现在都用域名邮箱白嫖typeless

我就是从那里转过来的
cf那个首先得让cf托管你的域名
然鹅这样可能会让你的网站在大陆直接访问不到:(

我现在用的飞书的邮箱,感觉不搭这种服务就够了()

我的个人邮箱就是基于飞书的服务,所以我会赞同你;
不过对于我们论坛,飞书一天只能发200封就完全不够了,所以这正是我探索自建邮箱系统的初心:face_blowing_a_kiss: