转载:原文链接

前言

关于邮件服务器的工作原理我就不再赘述了。Postfix是优秀的MTA,而Dovecot则是优秀的MDA。前者负责发信、收信,提供smtp服务;后者负责邮件保存到邮箱,提供pop3和imap服务。

这里介绍使用Postfix+Dovecot模式的邮件服务系统,同时Postfix使用Dovecot提供的SASL完成用户认证。用户使用MySQL存储的虚拟用户,而不是服务器的实际用户。同时使用opendkim完成邮件的dkim签名,SpamAssassin完成反垃圾邮件。也会阐述如何为smtp、pop3和imap配置SSL。

准备一台服务器

  1. 需要一台服务器,尽量使用有公网ip的服务器而不是使用内网穿透(否则发邮件的时候对方发现ip是非静态ip可能会当作垃圾邮件)。

  2. 要保证服务器的25端口开放。我选择了腾讯云的服务器,1核1G,申请开放了25端口(腾讯云申请比阿里云容易)。

  3. 主机名设置为你的域名或者mx.xxxx.com这样的子域名。

  4. 修改主机的时区,设为北京时间。

准备一个域名

准备一个域名,最好已经申请超过28天(否则容易被当作垃圾邮件)。

  1. 添加一个A记录(例如mx.xxxx.com)指向服务器的ip,添加一个mx记录(主机记录为@)指向上述添加的A记录(优先级可设定为5,具体作用可自行百度)。

  2. 可以为smtp、pop3和imap分别添加一些记录(例如smtp.xxxx.com),指向你的服务器(你也可以不这么做,这个看个人喜好,在登录邮箱的时候需要输入smtp服务器的地址,你可以输入ip也可以输入你现在设定的域名,如果要做SSL则最好是设定域名。你也可以smtp,pop3和imap都是用mx.xxxx.com这个域名)。

  3. 添加一个txt记录作为SPF记录(主机记录为@),内容可以写v=spf1 mx ~all。这表示当对方收到一封来自你这个域名的邮件时,先检查发件方对方的ip是否为mx记录中定义的ip(或A记录对应的ip),如果不是则标记为软拒绝。具体可以自行查询SPF记录的语法。如果你发邮件的机器没有公网ip,也就是你是通过本地机器内网穿透实现的邮件服务,那么SPF则写为v=spf1 +all表示接受所有的ip。

  4. 添加一个txt记录为DMARC记录(主机记录为_dmarc),内容可以写v=DMARC1; p=reject; fo=1; rua=mailto:你的邮箱。表示当出现仿造的邮件时,对方reject邮件,并通知你的邮箱。具体可以百度DMARC的语法。

申请SSL证书

如果不想使用SSL也可以跳过这一步骤。

  1. 申请一个SSL证书,包括上面步骤所创建的所有A记录(例如mx.xxxx.comsmtp.xxxx.com)。可以使用acme.sh在Let's或者ZeroSSL申请证书,我是在后者申请的。

  2. 证书的fullchain文件放到服务器的/etc/ssl/certs/xxxx.com.pem下。

  3. 证书的密钥文件放到服务器的/etc/ssl/private/xxxx.com.key下。

  4. 上述二者权限设置为400,属主设置为root:root

配置postfix和dovecot

  1. 安装postfix和dovecot
apt update
apt install postfix postfix-mysql dovecot-core dovecot-pop3d dovecot-imapd dovecot-lmtpd dovecot-mysql
  1. 安装配置MySQL,新建数据库mailserver(名字可以根据喜好来,下同),并创建用户mail,注意分配权限。

  2. 创建数据表:

CREATE TABLE `virtual_domains` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `virtual_users` (
`id` INT NOT NULL AUTO_INCREMENT,
`domain_id` INT NOT NULL,
`password` VARCHAR(106) NOT NULL,
`email` VARCHAR(120) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 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
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  1. 为数据库添加内容,具体按照自己喜好来
-- 插入一个域名(1表示序号, 注意递增)
insert into virtual_domains values(1,'xxxx.com') -- 插入用户(1表示序号, 注意递增)
insert into virtual_users values(1,域名序号,md5('密码'),'yyyy@xxxx.com'); -- 为用户设置一个别名(1表示序号, 注意递增),发送给zzzz的邮件都会发给yyyy了。
-- 注意这一步好像要先为zzzz插入一个用户,你也可以试一下不这么做,具体要不要我没试验过
insert into virtual_aliases values(1,域名序号,'zzzz@xxxx.com','yyyy@xxxx.com')
  1. 配置/etc/postfix/main.cf,这是postfix的主配置文件。

    1. 添加SSL代码
```
smtpd_tls_cert_file=/etc/ssl/certs/xxxx.com.pem
smtpd_tls_key_file=/etc/ssl/private/xxxx.key
smtpd_use_tls=yes
#smtpd_tls_auth_only = yes
smtp_tls_cert_file=/etc/ssl/certs/xxxx.com.pem
smtp_tls_key_file=/etc/ssl/private/xxxx.com.key
smtp_use_tls=yes smtpd_tls_CApath=/etc/ssl/certs
smtpd_tls_security_level=may
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_CApath=/etc/ssl/certs
smtp_tls_security_level=may
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
```
2. 使用dovecot来做身份认证
```
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
# smtpd_client_restrictions = permit_mynetworks permit_sasl_authenticated reject_rbl_client reject_rhsbl_client reject_unknown_client
# smtpd_sender_restrictions = reject_unknown_sender_domain
smtpd_recipient_restrictions = permit_sasl_authenticated permit_mynetworks reject_unauth_destination
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
```

restrictions结尾的是一些规则,表示smtp处理怎样的邮件。有兴趣的可以百度一下

3. 其次是域名的一些配置和一些常规配置
```
myhostname = xxxx.com
myorigin = $myhostname
mydomain = $myhostname
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = localhost
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_command = procmail -a "$EXTENSION"
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all
smtp_helo_name = xxxx.com
```
其中,myhostname设置为主机名,myorigin和mydomain设置为邮箱的域名(yyyy@xxxx.com的那个xxxx.com)。mynetworks指定来自哪里的ip允许直接发邮件,不需要SASL认证。如果你使用内网穿透,需要把mynetworks设置为空,否则经过内网穿透下来的请求来自的ip都会变成127.0.0.1,这样他们就统统不用走SASL就能发邮件了。 4. 最后设置一些和Dovecot以及MySQL协同工作所需要的选项。
```
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
virtual_transport = lmtp:unix:private/dovecot-lmtp
```
  1. 配置Postfix的MySQL文件
  2. 创建/etc/postfix/mysql-virtual-mailbox-domains.cf,内容如下:
 user = admin
password = 123456
hosts = 127.0.0.1:3306
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'
  1. 创建/etc/postfix/mysql-virtual-mailbox-maps.cf,内容如下
 user = admin
password = 123456
hosts = 127.0.0.1:3306
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email='%s'
  1. 最后创建/etc/postfix/mysql-virtual-alias-maps.cf,内容如下:
 user = admin
password = 123456
hosts = 127.0.0.1:3306
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'
  1. 重启服务(systemctl restart postfix),然后做一些验证
postmap -q xxxx.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
# 输出1 postmap -q yyyy@xxxx.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
# 输出1 postmap -q zzzz@xxxx.com mysql:/etc/postfix/mysql-virtual-alias-maps.cf
# 输出zzzz是谁的别名
  1. 配置/etc/postfix/master.cf文件

    1. 取消注释submission,开启587端口的服务,后面的inet, n, y, -o等可看作是参数
    submission inet n       -       y       -       -       smtpd
    -o syslog_name=postfix/submission
```
2. 取消smtps,开启SSL的465端口的服务
```
smtps inet n - y - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
```
  1. 配置/etc/dovecot/dovecot.conf,确保有如下内容:
!include conf.d/*.conf
protocols = imap lmtp pop3
  1. 创建一个用户,用户名和组名可以自己喜好决定,Home目录可放在/var/mail或者/home/mail。下文以/var/mail为例。
groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /家目录
chown -R vmail:vmail /家目录
  1. 修改/etc/dovecot/conf.d/10-mail.conf,确保配置为(注意/var/mail为上文所说的家目录,mail_privileged_group的值为mail是固定的,不是上文所创建的组名):
mail_location = maildir:/var/mail/vhosts/%d/%n
mail_privileged_group = mail
  1. 修改/etc/dovecot/conf.d/10-auth.conf,确保配置为
disable_plaintext_auth = no
auth_mechanisms = plain login

有的教程把disable_plaintext_auth设置为yes,这表示拒绝明文密码登录,会使得一些客户端登陆不上,所以我选择为no。

拖动到最下方,确保启用SQL设置,其他注释掉。

#!include auth-system.conf.ext
!include auth-sql.conf.ext
#!include auth-ldap.conf.ext
#!include auth-passwdfile.conf.ext
#!include auth-checkpassword.conf.ext
#!include auth-vpopmail.conf.ext
#!include auth-static.conf.ext
  1. 修改/etc/dovecot/conf.d/auth-sql.conf.ext,确保如下配置:
passdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
driver = static
args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
}

其中,vmail、/var/mail为上面步骤创建的用户的相关信息。

  1. 修改/etc/dovecot/dovecot-sql.conf.ext,确保如下配置,connect表示mysql的登录信息
driver = mysql
connect = host=127.0.0.1 port=3306 dbname=mailserver user=xxxx password=xxxx
default_pass_scheme = MD5
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';
  1. 修改/etc/dovecot/conf.d/10-master.conf,确保存在配置:
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
} # Create inet listener only if you can't use the above UNIX socket
#inet_listener lmtp {
# Avoid making LMTP visible for the entire internet
#address =
#port =
#}
} service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
} unix_listener auth-userdb {
mode = 0600
user = vmail
#group =
} user = dovecot
} service auth-worker {
# Auth worker process is run as root by default, so that it can access
# /etc/shadow. If this isn't necessary, the user should be changed to
# $default_internal_user.
user = vmail
}
  1. 修改/etc/dovecot/conf.d/10-ssl.conf,以开启ssl认证,确保存在一下配置
ssl = required
ssl_cert = <fullchain位置
ssl_key = <密钥位置

ssl使用required应该是说ssl是必须的意思,也可以使用yes表示开启ssl也允许非ssl。

ssl_cert和ssl_key的<符号是必须的,位置写绝对路径

 1. `ssl=no`: SSL/TLS 完全禁用。

 2. `ssl=yes` 且 `disable_plaintext_auth=no`: SSL/TLS 提供给客户端,但客户端不需要使用它。即使在连接上未启用 SSL/TLS,客户端也可以使用纯文本身份验证登录。这是不安全的,因为明文密码暴露在互联网上。

 3. `ssl=yes` 且 `disable_plaintext_auth=yes`: SSL/TLS 提供给客户端,但客户端不需要使用它。不允许客户端使用明文身份验证,除非先启用 SSL/TLS。但是,如果启用了非明文身份验证机制,即使没有 SSL/TLS,它们仍然是允许的。根据它们的安全程度,身份验证要么是完全安全的,要么可能有一些方法使其受到攻击。

 4. `ssl=required`:即使使用非明文身份验证机制,也始终需要 SSL/TLS。任何在启用 SSL/TLS 之前进行身份验证的尝试都将导致身份验证失败。请注意,此设置与 STARTTLS 命令无关 - 允许使用隐式 SSL/TLS 或 STARTTLS 命令。
  1. 修改/etc/dovecot的权限,其中vmail为上面创建的用户
chown -R vmail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot
  1. 重启postfix和dovecot,如此一postfix和dovecot就配置完成了。

    * OpenDKIM配置

    1. 安装OpenDKIM
    sudo apt install opendkim opendkim-tools
    1. 修改配置文件/etc/opendkim.conf,确保有以下内容
    Domain                  xxxx.com
    KeyFile /etc/dkimkeys/dkim.key
    Selector dkim
    SOCKET inet:8891@localhost

    其中,SOCKET的端口可以使用8891,也有人使用8892,我没发现区别。

    1. 修改/etc/default/opendkim,确保有以下内容
    SOCKET="inet:8891@localhost"
    1. 生成dkim密钥对(一般在用户的家目录下生成,再复制到指定位置)
    sudo opendkim-genkey -t -s dkim -d xxxx.com

    然后执行移动操作

    sudo mv dkim.key /etc/dkimkeys/
    sudo chown opendkim:opendkim dkim.key
    1. 在postfix的配置文件/etc/postfix/main.cf添加如下配置
    smtpd_milters = inet:localhost:8891
    non_smtpd_milters = inet:localhost:8891
    milter_protocol = 2
    milter_default_action = accept
    1. 关注到第四步生成密钥对时产生的dkim.txt文件。
    dkim._domainkey IN      TXT     ( "v=DKIM1; k=rsa; t=y; "
    "p=xxxxxxxxxx" ) ; ----- DKIM key dkim for Example Domain

    复制双引号的内容,去除双引号和换行,整理为:v=DKIM1; k=rsa; t=y; p=xxxxxxxxxx的形式。在域名添加为txt记录(主机记录为dkim._domainkey)。

    1. 重启postfix和opendkim,如此一来就配置完成了。
* 配置SpamAssassin

  SpamAssassin为Postfix实现反垃圾的功能。

  1.  安装SpamAssassin
```
sudo apt-get install spamassassin spamc
```
2. 添加用户
```
sudo adduser spamd --disabled-login
```
3. 修改配置文件`/etc/default/spamassassin`,确保有如下配置:
```
ENABLED=1
SAHOME="/var/log/spamassassin/"
OPTIONS="--create-prefs --max-children 5 --username spamd --helper-home-dir /home/spamd/ -s /home/spamd/spamd.log"
PIDFILE="/var/run/spamd.pid"
CRON=1
```
4. 修改`/etc/spamassassin/local.cf`,确保有如下配置:
```
rewrite_header Subject ***** SPAM _SCORE_ *****
required_score 5.0
use_bayes 1
bayes_auto_learn 1
```
5. 修改`/etc/postfix/master.cf`文件 添加配置: ```
spamassassin unix - n n - - pipe
user=spamd argv=/usr/bin/spamc -f -e
/usr/sbin/sendmail -oi -f ${sender} ${recipient}
```
为smtp,smtps和submission添加参数
```
-o content_filter=spamassassin
```
有些教程只为smtp添加参数,我认为应该都添加。 添加之后,应该看上去像:
```
smtp inet n - y - - smtpd
-o content_filter=spamassassin
```
6. 执行`update-rc.d spamassassin enable`,然后重启postfix和spamassassin即可完成配置。

客户端连接服务器

客户端可以使用FoxMail或者雷鸟。

填写登录名为yyyy@xxxx.com以及密码,然后输入正确的smtp和pop3服务器地址以及端口号即可。

  1. smtp默认25端口,SSL则是465端口。

  2. pop3默认110端口,SSL则是995端口。

  3. imap默认143端口,SSL则是993端口。

写在最后

以上是根据我配置邮件服务器的过程所总结的文章,我也折腾了快两个星期了。可能会有错误,欢迎留言咨询也以便我更正错误。

Ubuntu搭建邮件服务器的更多相关文章

  1. Ubuntu安装邮件服务器

    Ubuntu搭建邮件服务器 此文我们使用Postfix来搭建邮箱服务器,Postifx是一个SMTP服务器.SMTP服务器也被称为MTA(message transfer agent) 一.安装pos ...

  2. kubuntu+roundcube搭建邮件服务器(包含LAMP)

    好久之前写的了,偶然翻到然后拿出来看看,里面文字图片都没改,有错误请见谅 步骤: 一.关于ubuntu的安装二.ubuntu配置LAMP(Linux+Apache+Mysql+Perl/PHP/Pyt ...

  3. Postfix+Dovecot+MySQL搭建邮件服务器

    网上有很多使用Postfix搭建邮件服务器的文章,但目前貌似没有看到较为完整的一篇.本例将尝试在Ubuntu系统中使用Postfix+Dovecot+MySQL搭建邮件服务器. 说到邮件服务器,网上有 ...

  4. CentOS利用postfix搭建邮件服务器

    之前我用nodemailer通过163邮箱来发送邮件,不过没过几天就一直ETIMEDOUT,不知道什么原因,想着还是自己搭一个来发邮件可能靠谱点(flag?) 安装postfix CentOS 7 自 ...

  5. Windows Server 2003搭建邮件服务器

    Windows Server 2003搭建邮件服务器 由于Windows Server 2003默认是没有安装我们搭建邮件服务器所需要的POP3和SMTP服务的,因此需要我们自己来安装.方法如下: 1 ...

  6. ubuntu搭建svn服务器并htpp访问版本库并svn与web同步

    Ubuntu搭建SVN服务器多版本库 1  介绍   Subversion是一个自由,开源的版本控制系统,这个版本库就像一个普通的文件服务器,不同的是,它可以记录每一次文件和目录的修改情况.这样就可 ...

  7. Ubuntu搭建Anki服务器

    Ubuntu搭建Anki服务器 第一步安装Anki 阿里云的服务器,xshell远程登录上 #以root用户进行操作 #安装Akni服务 easy_install AnkiServer #添加名为an ...

  8. Ubuntu搭建NFS服务器,NFS协议详细分析

    目录 1. Ubuntu搭建NFS服务器 2. NFS协议分析 2.1 实验拓扑: 2.2 在kali抓包分析 1. Ubuntu搭建NFS服务器 ​ NFS(Network FileSystem,网 ...

  9. 阿里云CentOS Linux服务器上搭建邮件服务器遇到的问题

    参考文章: 阿里云CentOS Linux服务器上用postfix搭建邮件服务器 Linux系统下邮件服务器的搭建(Postfix+Dovecot) 本来想自己搭建邮件服务器,但是看到一篇资料表示阿里 ...

  10. 使用hMailServer搭建邮件服务器

    本文没有什么高深的技术内容,只是使用hMailServer,介绍搭建邮件服务器的全过程,供参考. 一.安装邮件服务器组件 打开软件,点下一步 选择存储数据的数据库,这里有两种选择, 一种是使用嵌入型数 ...

随机推荐

  1. jdk8环境变量

    JAVA_HOME C:\Program Files\Java\jdk1.8.0_333 Path%JAVA_HOME%\bin%JAVA_HOME%\jre\bin CLASSPATH.%JAVA_ ...

  2. Springboot+Mybatisplus+ClickHouse集成

    核心依赖引入 <dependency> <groupId>ru.yandex.clickhouse</groupId> <artifactId>clic ...

  3. Go 语言开发环境搭建

    Go 语言开发环境搭建 目录 Go 语言开发环境搭建 一. GO 环境安装 1.1 下载 1.2 Go 版本的选择 1.3 安装 1.3.1 Windows安装 1.3.2 Linux下安装 1.3. ...

  4. VS Code SSH

    VS Code SSH 连接需要下载 VS Code Server,这是因为 VS Code Server 是在远程服务器上运行的,而不是在本地计算机上运行的.每次连接到不同的远程服务器时,都需要下载 ...

  5. Linux 在多个文件中搜索关键字

    摘要:使用grep或者rg在当前目录下所有文件中查找关键字.   在Linux操作系统下,搜索文件中的关键字可帮助用户快速找到所需的信息,满足快速排查问题的需求.在大型系统中,文件可能被保存在多个目录 ...

  6. C#学习笔记--进阶

    C#进阶 简单数据结构类 ArrayList 元素类型以Object类型存储,支持增删查改的数组容器. 因而存在装箱拆箱操作,谨慎使用. //ArrayList ArrayList array=new ...

  7. AtCoder Beginner Contest 321(ABC321)

    A. 321-like Checker 直接模拟. Code B. Cutoff 直接暴力枚举 \([0\sim100]\),每次把第 \(n\) 个数当作当前枚举的 \(i\),然后看看条件是否满足 ...

  8. Prometheus+Grafana实现服务性能监控:windows主机监控、Spring Boot监控、Spring Cloud Alibaba Seata监控

    1.Prometheus介绍 Prometheus使用Go语言开发,中文名称叫:普罗 米修斯.Prometheus是一个开源系统最初在SoundCloud构建的监控和警报工具包.自 2012 年成立以 ...

  9. 通过HTML和JavaScript实现随机抽取幸运员工

    需求描述: 公司经常会要求IT部门做一个随机抽取员工页面,今天我们通过HTML和JavaScript来实现 HTML 结构 首先,我们需要编写 HTML 代码来定义页面结构和元素.下面是 HTML 代 ...

  10. 使用 Vue 3 插件(Plugin)实现 OIDC 登录和修改密码(OIDC 系统以 Keycloak 为例)

    背景 目前单位系统常用 Keycloak 作为认证系统后端,而前端之前写的也比较随意,这次用 Vue 3 插件以及 Ref 响应式来编写这个模块.另外,这个可能是全网唯一使用 keycloak 的 O ...