转载:原文链接

前言

关于邮件服务器的工作原理我就不再赘述了。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. 在 Net7.0 环境下使用 RestSharp 发送 Http(FromBody和FromForm)请求

    一.简介 最近,在做一个数据传输的服务,我在一个Worker Service里面需要访问 WebAPI 接口,并传输数据,也可以提交数据.由于第一次使用 RestSharp 发送请求,也遇到了很多问题 ...

  2. Python 有趣的模块之pynupt——通过pynput控制鼠标和键盘

    写在前面 Python中有许多有趣和强大的模块,其中一个非常有趣的模块就是pynupt.pynupt是基于pynput模块的一个封装,用于控制鼠标和键盘.它可以实现自动化操作和游戏外挂等功能. 本文将 ...

  3. idea2020.3 安装插件JetBrains 插件市场安装 Cloud Toolkit

    <Cloud Toolkit User Guide> 本文是 Alibaba Cloud Toolkit 的使用文档指引,所有相关的使用参考,都可以在本文中找到.如果在使用中有任何问题,请 ...

  4. CSS 多行文本超链接下划线动效

    先看效果 乍一看,是不是感觉很简单,仔细一瞅发现事情好像没有那么简单. 如果十分钟还没想出怎么实现,那就把简历上的"精通css"改成"了解css"-- 大部分人 ...

  5. 自学一周python做的一个小游戏《大球吃小球》

    需求 1,显示一个窗口. 2,我们要做到的功能有鼠标点击屏幕生成小球. 3,生成的小球大小随机,颜色随机,向随机方向移动,速度也随机. 4,大的球碰到小球时可以吃掉小球,吃掉后会变大. 5,球碰到边界 ...

  6. 传纸条 luoguP1006

    题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排坐成一个 mm 行 nn 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈 ...

  7. vscode双击没反应,后台也看不到进程的解决方案

    百度找的解决方案: cmd窗口执行 netsh winsock reset 重置命令. 删除Romaing下的Code文件夹 修改Code/User/locale.json(我没找到这个文件)中的&q ...

  8. Godot - 创建翻译文件(常量表)

    版本 Godot 3.1.2 背景 Godot的UI系统封装的很难受, 一些东西很难改动, 比如这个AcceptDialog的"确定""取消"按钮, 特别是在编 ...

  9. NewStarCTF 2023 公开赛道 WEEK4|MISC 部分WP

    R通大残 1.题目信息 R通大残,打了99,补! 2.解题方法 仔细分析题目,联想到隐写的R通道. 首先解释一下:R是储存红色的通道,通道里常见有R(红).G(绿).B(蓝)三个通道,如果关闭了R通道 ...

  10. sql server 截断和收缩所有用户数据库日志--用游标循环所有正常状态的用户数据库

    在服务器运维活动中,我们经常需要做一项工具就是将好多年的用户数据库日志文件截断并收缩为最小,以节省大量的磁盘空间.当数据库只有一两个时可以手动操作,但数据库数量众多时,就需要采用sql脚本,批量化执行 ...