Ubuntu搭建邮件服务器
转载:原文链接
前言
关于邮件服务器的工作原理我就不再赘述了。Postfix是优秀的MTA,而Dovecot则是优秀的MDA。前者负责发信、收信,提供smtp服务;后者负责邮件保存到邮箱,提供pop3和imap服务。
这里介绍使用Postfix+Dovecot模式的邮件服务系统,同时Postfix使用Dovecot提供的SASL完成用户认证。用户使用MySQL存储的虚拟用户,而不是服务器的实际用户。同时使用opendkim完成邮件的dkim签名,SpamAssassin完成反垃圾邮件。也会阐述如何为smtp、pop3和imap配置SSL。
准备一台服务器
需要一台服务器,尽量使用有公网ip的服务器而不是使用内网穿透(否则发邮件的时候对方发现ip是非静态ip可能会当作垃圾邮件)。
要保证服务器的25端口开放。我选择了腾讯云的服务器,1核1G,申请开放了25端口(腾讯云申请比阿里云容易)。
主机名设置为你的域名或者
mx.xxxx.com这样的子域名。修改主机的时区,设为北京时间。
准备一个域名
准备一个域名,最好已经申请超过28天(否则容易被当作垃圾邮件)。
添加一个A记录(例如
mx.xxxx.com)指向服务器的ip,添加一个mx记录(主机记录为@)指向上述添加的A记录(优先级可设定为5,具体作用可自行百度)。可以为smtp、pop3和imap分别添加一些记录(例如
smtp.xxxx.com),指向你的服务器(你也可以不这么做,这个看个人喜好,在登录邮箱的时候需要输入smtp服务器的地址,你可以输入ip也可以输入你现在设定的域名,如果要做SSL则最好是设定域名。你也可以smtp,pop3和imap都是用mx.xxxx.com这个域名)。添加一个txt记录作为SPF记录(主机记录为@),内容可以写
v=spf1 mx ~all。这表示当对方收到一封来自你这个域名的邮件时,先检查发件方对方的ip是否为mx记录中定义的ip(或A记录对应的ip),如果不是则标记为软拒绝。具体可以自行查询SPF记录的语法。如果你发邮件的机器没有公网ip,也就是你是通过本地机器内网穿透实现的邮件服务,那么SPF则写为v=spf1 +all表示接受所有的ip。添加一个txt记录为DMARC记录(主机记录为_dmarc),内容可以写
v=DMARC1; p=reject; fo=1; rua=mailto:你的邮箱。表示当出现仿造的邮件时,对方reject邮件,并通知你的邮箱。具体可以百度DMARC的语法。
申请SSL证书
如果不想使用SSL也可以跳过这一步骤。
申请一个SSL证书,包括上面步骤所创建的所有A记录(例如
mx.xxxx.com和smtp.xxxx.com)。可以使用acme.sh在Let's或者ZeroSSL申请证书,我是在后者申请的。证书的fullchain文件放到服务器的
/etc/ssl/certs/xxxx.com.pem下。证书的密钥文件放到服务器的
/etc/ssl/private/xxxx.com.key下。上述二者权限设置为
400,属主设置为root:root。
配置postfix和dovecot
- 安装postfix和dovecot
apt update
apt install postfix postfix-mysql dovecot-core dovecot-pop3d dovecot-imapd dovecot-lmtpd dovecot-mysql
安装配置MySQL,新建数据库mailserver(名字可以根据喜好来,下同),并创建用户mail,注意分配权限。
创建数据表:
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表示序号, 注意递增)
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')
- 配置
/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
```
- 配置Postfix的MySQL文件
- 创建/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'
- 创建/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'
- 最后创建/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'
- 重启服务(
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是谁的别名
- 配置
/etc/postfix/master.cf文件- 取消注释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
```
- 配置
/etc/dovecot/dovecot.conf,确保有如下内容:
!include conf.d/*.conf
protocols = imap lmtp pop3
- 创建一个用户,用户名和组名可以自己喜好决定,Home目录可放在
/var/mail或者/home/mail。下文以/var/mail为例。
groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /家目录
chown -R vmail:vmail /家目录
- 修改
/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
- 修改
/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
- 修改
/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为上面步骤创建的用户的相关信息。
- 修改
/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';
- 修改
/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
}
- 修改
/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 命令。
- 修改
/etc/dovecot的权限,其中vmail为上面创建的用户
chown -R vmail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot
重启postfix和dovecot,如此一postfix和dovecot就配置完成了。
* OpenDKIM配置- 安装OpenDKIM
sudo apt install opendkim opendkim-tools
- 修改配置文件
/etc/opendkim.conf,确保有以下内容
Domain xxxx.com
KeyFile /etc/dkimkeys/dkim.key
Selector dkim
SOCKET inet:8891@localhost
其中,SOCKET的端口可以使用8891,也有人使用8892,我没发现区别。
- 修改
/etc/default/opendkim,确保有以下内容
SOCKET="inet:8891@localhost"
- 生成dkim密钥对(一般在用户的家目录下生成,再复制到指定位置)
sudo opendkim-genkey -t -s dkim -d xxxx.com
然后执行移动操作
sudo mv dkim.key /etc/dkimkeys/
sudo chown opendkim:opendkim dkim.key
- 在postfix的配置文件
/etc/postfix/main.cf添加如下配置
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
milter_protocol = 2
milter_default_action = accept
- 关注到第四步生成密钥对时产生的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)。- 重启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服务器地址以及端口号即可。
smtp默认25端口,SSL则是465端口。
pop3默认110端口,SSL则是995端口。
imap默认143端口,SSL则是993端口。
写在最后
以上是根据我配置邮件服务器的过程所总结的文章,我也折腾了快两个星期了。可能会有错误,欢迎留言咨询也以便我更正错误。
Ubuntu搭建邮件服务器的更多相关文章
- Ubuntu安装邮件服务器
Ubuntu搭建邮件服务器 此文我们使用Postfix来搭建邮箱服务器,Postifx是一个SMTP服务器.SMTP服务器也被称为MTA(message transfer agent) 一.安装pos ...
- kubuntu+roundcube搭建邮件服务器(包含LAMP)
好久之前写的了,偶然翻到然后拿出来看看,里面文字图片都没改,有错误请见谅 步骤: 一.关于ubuntu的安装二.ubuntu配置LAMP(Linux+Apache+Mysql+Perl/PHP/Pyt ...
- Postfix+Dovecot+MySQL搭建邮件服务器
网上有很多使用Postfix搭建邮件服务器的文章,但目前貌似没有看到较为完整的一篇.本例将尝试在Ubuntu系统中使用Postfix+Dovecot+MySQL搭建邮件服务器. 说到邮件服务器,网上有 ...
- CentOS利用postfix搭建邮件服务器
之前我用nodemailer通过163邮箱来发送邮件,不过没过几天就一直ETIMEDOUT,不知道什么原因,想着还是自己搭一个来发邮件可能靠谱点(flag?) 安装postfix CentOS 7 自 ...
- Windows Server 2003搭建邮件服务器
Windows Server 2003搭建邮件服务器 由于Windows Server 2003默认是没有安装我们搭建邮件服务器所需要的POP3和SMTP服务的,因此需要我们自己来安装.方法如下: 1 ...
- ubuntu搭建svn服务器并htpp访问版本库并svn与web同步
Ubuntu搭建SVN服务器多版本库 1 介绍 Subversion是一个自由,开源的版本控制系统,这个版本库就像一个普通的文件服务器,不同的是,它可以记录每一次文件和目录的修改情况.这样就可 ...
- Ubuntu搭建Anki服务器
Ubuntu搭建Anki服务器 第一步安装Anki 阿里云的服务器,xshell远程登录上 #以root用户进行操作 #安装Akni服务 easy_install AnkiServer #添加名为an ...
- Ubuntu搭建NFS服务器,NFS协议详细分析
目录 1. Ubuntu搭建NFS服务器 2. NFS协议分析 2.1 实验拓扑: 2.2 在kali抓包分析 1. Ubuntu搭建NFS服务器 NFS(Network FileSystem,网 ...
- 阿里云CentOS Linux服务器上搭建邮件服务器遇到的问题
参考文章: 阿里云CentOS Linux服务器上用postfix搭建邮件服务器 Linux系统下邮件服务器的搭建(Postfix+Dovecot) 本来想自己搭建邮件服务器,但是看到一篇资料表示阿里 ...
- 使用hMailServer搭建邮件服务器
本文没有什么高深的技术内容,只是使用hMailServer,介绍搭建邮件服务器的全过程,供参考. 一.安装邮件服务器组件 打开软件,点下一步 选择存储数据的数据库,这里有两种选择, 一种是使用嵌入型数 ...
随机推荐
- SQL函数Intersect,except整理
1. 集合函数使用的规则 ① 每个集合要求列数量相同,列顺序相同. ② 每个集合显示的列,要求数据类型一致或者可隐式转换成同一数据类型 ③ 最终集合列名称与第一个集合的列名称一致 2. ...
- Python并发编程——threading、开启线程 、线程进程对比、线程方法、守护线程、GIL、同步锁、死锁和递归锁、信号量、Event、condition、定时器、queue、concurrent
文章目录 内容回顾 一 threading模块介绍 二 开启线程的两种方式 三 在一个进程下开启多个线程与在一个进程下开启多个子进程的区别 四 练习 五 线程相关的其他方法 六 守护线程 七 Pyth ...
- docker入门加实战—从部署MySQL入门docker
docker入门加实战-从部署MySQL入门docker docker部署MySQL 输入如下命令: docker run -d \ --name mysql \ -p 3306:3306 \ -e ...
- Go函数介绍与一等公民
Go函数介绍与一等公民 函数对应的英文单词是 Function,Function 这个单词原本是功能.职责的意思.编程语言使用 Function 这个单词,表示将一个大问题分解后而形成的.若干具有特定 ...
- 让物体动起来,Unity的几种移动方式
一.前言 在大部分的Unity游戏开发中,移动是极其重要的一部分,移动的手感决定着游戏的成败,一个优秀的移动手感无疑可以给游戏带来非常舒服的体验.而Unity中有多种移动方法,使用Transform, ...
- require()、import、import()有哪些区别?
require().import.import()是我们常用的引入模块的三种方式,代码中几乎处处用到.如果对它们存在模糊,就会在工作过程中不断产生困惑,更无法做到对它们的使用挥洒自如.今天我们来一起捋 ...
- L3-009 长城
#include <bits/stdc++.h> using namespace std; using pii = pair<int, int>; using ll = lon ...
- 在 Ubuntu 22.04 系统上为 SSH 开启基于时间的 TOTP 认证
前言 一次性密码(英语:one-time password,简称OTP),又称动态密码或单次有效密码,是指电脑系统或其他数字设备上只能使用一次的密码,有效期为只有一次登录会话或一段短时间内.基于时间的 ...
- 总结(3)--- 知识总结(内存管理、线程阻塞、GIL锁)
一.Python中是如何进行内存管理的? 垃圾回收:Python不像C++,Java等语言一样,他们可以不用事先声明变量类型而直接对变量进行赋值.对Python而言,对象的类型和内存都是在运行时确定的 ...
- Guava Preconditions类的各种用法
公众号「架构成长指南」,专注于生产实践.云原生.分布式系统.大数据技术分享. Guava Preconditions类 提供静态方法列表,用于检查是否使用有效参数值调用方法或构造函数.如果前提条件失败 ...