从零开始学习邮件系统搭建(一)——正经发出一封邮件

2017-04-12  本文已影响0人  Jinglever

前言
  出于工作原因,需要学习搭建邮件系统,为避免日后生疏最后忘了,这里会记录我整个学习的过程,包括中途遇到的不解之处,当然也会有一个完整的搭建成品的步骤。
  网上可以搜到不少关于搭建邮件系统的文章,质量参差不齐,我本人更希望自己能了解到更多,而非照着步骤啪啪啪搭起来就算了,以后遇到问题能比较有效率地寻找解决方案。
  我一边学一边写,会有理解错的,后面发现之后会回头修正。欢迎留言指教。

涉及到概念(ps.直接看没意思,先往后看,发现不明白的英文名词再回来这里查一下吧

名词 解释
MUA (Mail User Agent)用户邮件代理,用于接收邮件。如foxmail。
MTA (Mail Transfer Agent)邮件传输代理,用于接受发邮件请求并完成转发动作。如postfix。
MDA (Mail Delivery Agent)邮件分发代理,用于将收到的邮件放进收件人信箱中,具有过滤邮件、自动回复等功能。主要的MTA程序都有自己的MDA功能,也有比较强大的第三方MDA,如procmail等。
MRA (Mail Retrieval Agent)邮件取回代理,提供POP3/IMAP协议,供MUA将邮件取出。
POP3 (Post Office Protocol version 3)邮局协议第三版。对于MUA拉取邮件到本地的动作,可以设置拉取完后删除拉取后不删除两种方式,对邮件得下载到本地后才能进行管理。
IMAP (Internet Message Access Protocol)网络信息访问协议。相比POP3,可以远程访问邮件服务器管理邮件,不一定非得先下载到本地。
SMTP (Simple Mail Transfer Protocol)简单邮件传输协议。MTA就是SMTP的一个实现,端口号通常是25。SMTP协议很早就出现,比HTTP还早,本身没有对发送方的身份验证,所以后来出现了SPF、DKIM、DMARC等东西来弥补。
Postfix 一个开源的MTA程序,负责通过SMTP协议发送邮件。是作者为改善sendmail开发的,如今很流行。
Cyrus SASL Cyrus Simple Authentication and Security Layer的缩写,是一个辅助的程序,针对SMTP的认证,它提供了saslauthd来进行账号密码的比对。同时,它还支持两个auxprop插件:sasldb,sql。反正就是提供不同方式的身份验证。后面会学到。
Dovecot 一个开源的MRA程序,按照POP3/IMAP协议提供邮件取回服务,同时,它支持对用户的身份进行验证,貌似也用来协助SMTP服务器做身份验证,而且可以做到比cyrus sasl更好?
MX 邮件交换记录。发邮件时,会根据收件人的地址后缀去DNS服务器查到MX记录,从而定位收件地址所在的服务器。
SPF (Sender Policy Framework)是为了防范垃圾邮件而提出来的一种DNS记录类型。用于登记某个域名拥有的用来外发邮件的所有IP地址。收方邮件服务器可能会根据发方的域名向DNS服务器索取发方域名的SPF记录,跟发方的IP做匹配,如果不能匹配上,那么说明这封邮件并非由真正的发方域名的服务器发出,可能会判为垃圾邮件。
PTR 反向域名解析。使得可以通过发方的IP地址反查到域名,也是判断发件人是否正常的手段。

名词的解释暂时到这可好。。另外还有那些DKIM之类,后面要用到的时候再说。

邮件系统工作原理图(ps.看这些图觉得烦,不妨先往后看吧,想要知道收发邮件的背后机制时再来这看

在简书里的这篇文章从零开始邮件服务器搭建给出了几个流程图,特别好地描述了邮件系统的工作原理,推荐过去阅读,有对流程图的详细讲解。我在下面仅把图贴过来(如果原作者不愿我把图贴过来,可以留言,我删掉便是),方便查看。

邮件系统架构
邮件服务器接收邮件
用户查收邮件过程
用户发送邮件过程

我的工作环境

服务器是阿里云上的ECS,操作系统是Centos 6.8 (64位)。下面一步步地,是从一个全新的由公共镜像创建的ECS开始,慢慢部署,琢磨。
首先,为了好看些,vim /etc/bashrc,末尾添加如下代码:

#color

use_color=true

if ${use_color}; then
    if [[ ${EUID} == 0 ]]; then
        PS1='\[\033[01;31m\]\h\[\033[01;34m\] \W \$\[\033[00m\] '
    else
        PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] '
    fi
else
    if [[ ${EUID} == 0 ]]; then
        PS1='\u@\h \W \$ '
    else
        PS1='\u@\h \w \$ '
    fi
fi

alias ll='ls -la'
alias vi='vim'
alias grep='grep --color=auto'

然后,修改hostname,比原先那样好看些吧。虽说Postfix会用到hostname,但因为可以在main.cf(如果你不知道这个,可以先不管,后面会说)里设置,所以,在这里修改hostname,我能想到的好处,就是好看。

vim /etc/sysconfig/network;
        HOSTNAME=mail.howard.org  #修改HOSTNAME
vim /etc/hosts;
        127.0.0.1 mail.howard.org #hosts对hostname本身关系不大,增加一个mapping,便于有些程序对hostsname的dns解析
hostname mail.howard.org;  #上面的修改需要重启主机才会生效,这里不想重启,就直接改内存里的吧。需要退出当前会话重新进来才可以看到生效

hostname要符合FQDN,可以自行百度。比如我这台主机是邮件服务器,hostname写成mail.howard.org,属于全称域名,domain就是howard.org,主机名是mail,表示该主机在域名树的位置。

安装一些软件

说明:下面安装的软件并非全是必要的,为了后面的学习,先装好了。

  1. 安装postfix:yum install postfix。我执行后发现是升级原有的版本。设置开机启动chkconfig postfix on
  2. 删除原有的sendmail:rpm -e sendmail or yum remove sendmail。本ECS没安装sendmail。
  3. 安装Cyrus SASL相关的软件:yum install cyrus-sasl cyrus-sasl-plain cyrus-sasl-md5 cyrus-sase-sql
  4. 安装dovecot:yum install dovecot。我安装的版本是1:2.0.9-22.el6。
  5. 安装MySQL:
    由于ECS默认的源里的MySQL版本是5.1,所以下面先改一下源:
wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm;
wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm;
rpm -ivh *.rpm;
vim /etc/yum.repos.d/remi.repo;
        [remi] enabled=1 #设置remi下面的enabled为1
yum install mysql-server; #现在安装的就是MySQL 5.5版本了
/etc/init.d/mysqld start; #启动MySQL
chkconfig mysqld on; #开机自启动
mysql -u root -p; #看到等待输入密码时,直接按回车,因为是全新安装的,所以无密码。进入后是mysql的控制台
mysql>drop database test; #删除test库
mysql>use mysql; #切换至mysql库
mysql>delete from user where user=''; #删除匿名账户
mysql>update user set password=PASSWORD('123456') where user='root';#设置root密码
mysql>grant all privileges on *.* to root@'%' identified by '123456';#设置允许远程访问(为方便才这样设的,你懂的)
mysql>flush privileges;
mysql>exit

配置防火墙

对于阿里云主机,用安全组也是不错的选择。下面是配置iptables的方法:

ll /etc/sysconfig/iptables; #本ECS默认没有配置iptables,所以这里会报找不到文件
iptables-save > /etc/sysconfig/iptables; #生成一个空的iptables配置文件
#在 :OUTPUT ACCEPT [107:11768] 跟 COMMIT 两行之间插入下面这些内容
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 25 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 993 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 995 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
#上面的意思大概就是,只对tcp连接开放22、3306、25、993、995端口,其他都封禁。
/etc/init.d/iptables restart

下面先让服务器可以正常发出一封邮件

先试试现在能不能发送了(ps.简直迫不及待啊):
  1. 启动postfix:/etc/init.d/postfix start;
  2. netstat -tlnp |grep 25;可以看到
  3. yum install telnet; 我发现ECS还没安装telnet。
  4. 用telnet跟postfix交互(不妨tail -f /var/log/maillog看输出什么log,有时候很有用)
  5. 检查一下收件箱,收到啦!虽然是在垃圾箱里。是的,只需要postfix就可以完成发邮件的事情了!不过我们也发现了两个问题,一个是这个过程没有要求验证身份;第二是在/var/log/maillog里输出不少warning。下面就来做一些配置,让发邮件这个任务完成得更好些。
修改默认邮件传输代理(MTA)

输入alternatives --display mta;看第一行,发现提示的第一行是mta - 状态是自动。现在我们把它改成手动的强制指向postfix:alternatives --config mta,根据提示,选择sendmail.postfix。这个时候再输入alternatives --display mta;,现在可以看到第一行是mta - 状态是手工

配置postfix(/etc/postfix/main.cf)

关于postfix的历史以及/etc/postfix目录下各个文件的意义,请移步看鸟哥的文章鸟哥的Linux私房菜(第二十二章)。这里备注一下修改main.cf需要注意的地方:

  1. 好习惯:cd /etc/postfix; cp main.cf main.cf.bk;
  2. vim main.cfps.如果没能搜到,就在文件末尾添加即可。下面所有的设定项可以通过man 5 postconf查看其意思。
      #主机名;会被后面很多设定项引用,务必使用FQDN,即完整主机名
myhostname = mail.howard.org
      #域名;一般是主机名去掉第一个.前面那截剩下的,后面也被很多设定项引用
mydomain = howard.org
      #发信源主机;对应邮件标头上的“mail from”;默认是$myhostname,如果多台主机使用同一个domain,那么就设成$mydomain
myorigin = $mydomain
      #postfix的监听接口(极重要);默认只开放给本机localhost,如果要监听整个internet的话,设为all
inet_interfaces = all
      #postfix的监听IP协议;默认是all,即同时监听IPv4和IPv6,但如果服务器的网络只支持IPv4,那就设为ipv4
inet_protocols = ipv4
      #能收信的主机名(极重要);DNS里的MX指向的主机名也要写到这里来
      #如果是邮件域网关,要加上$mydomain,其他smtp节点就不用加$mydomain
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
      #约定信任的用户端(极重要);规定了本MTA可以为哪些用户端进行Relay,就是转发了
      #千万不要open relay,会让本MTA的IP进入各种黑名单
      #鸟哥建议下面这种写法,使用hash:/etc/postfix/access,就是个外部的哈希库,可以参考鸟哥的文章👆了解详情
mynetworks = 127.0.0.0/8, hash:/etc/postfix/access
      #默认收件箱在/var/spool/mail/user,所有的邮件存放在同一个文件中
      #改成Maildir/,收件会存储在/home/user/Maildir/下,每封邮件是一个文件
      #如果改成Mailbox,则收件会存储在/home/user/Mailbox中,都存在同一个文件里
home_mailbox = Maildir/
      #在SMTP服务器的欢迎标语上显示软件版本。Postfix本身对这个不关心
smtpd_banner = $myhostname ESMTP
      #邮件最大尺寸,单位:字节
message_size_limit = 52428800
      #规定收件箱最大容量,单位:字节
mailbox_size_limit = 1073741824
  1. 由于mynetworks设置了hash:/etc/postfix/access,所以需要执行postmap hash:/etc/postfix/access来生成对应的哈希库/etc/postfix/access.db
  2. /etc/init.d/postfix restart #使配置文件生效 因为改动了inet_protocols和inet_interfaces,所以需要restart,否则reload即可
  3. 设置DNS解析,增加两条A记录,之所以其中一个主机记录写mail,因为前面$myhostname写了mail.howard.org啊。
  4. 设置DNS解析,增加一条MX记录,记录值跟$myhostname一致。因为只有一条MX记录,所以MX优先级是多少不重要啦。
  5. 设置DNS解析,增加一条SPF记录,其实是按照SPF格式增加一条TXT记录,有助于提高服务器IP信誉度。


  6. 发工单跟阿里云请求对ECS的IP跟主机域名mail.howard.org做反向域名解析,有助于提高服务器IP的信誉度。
关于MX、SPF、PRT

这几项基本都是为了增加服务器IP的信誉度的。参考这个文章的说法:如何避免你外发的电子邮件被误判为垃圾邮件。或者自己网上搜搜,很容易能理解。

关于Open Relay

在上面配置/etc/postfix/main.cf时提到Open Relay这个名词。
  如果开启了Open Relay,那么就是说,任何人都可以连接到你的SMTP服务器进行转发将邮件寄出去,不管客户端是哪里、发件人是谁、收件人是谁。这种情况是非常糟糕的,意味着你的服务器会成为发送垃圾邮件的人的工具。所以绝大部分收件服务器对Open Relay的SMTP服务器是零容忍,同时也有不少第三方机构会扫描记录这种SMTP服务器,并将其扔进黑名单。所以,不要开启Open Relay。
  那么怎么禁止Open Relay呢?换句话说就是,要怎么配置才可以限制不能被随意利用来转发邮件。无非就是,限制客户端、限制发件人、限制收件人等等。其实,现在安装的postfix,默认就是禁止Open Relay的。下面我们来理解一下是怎么禁止Open Relay的。
  在我的理解里,主要通过配置下面三个设定项来达到目的:smtpd_recipient_restrictionssmtpd_client_restrictionssmtpd_sender_restrictions。通过man 5 postconf可以查到这三个设定项的含义和用法。通过postconf -h xxxx可以查看当前配置里设定项xxxx的值。

搭配上面这三个设定项的,一般是mynetworksmydestination。所以这两项的设定极其重要。

正经地发送一封成熟的邮件

行文至此,对于一个内部使用的SMTP服务器已经完成,可以通过mynetworks设置只允许内部使用。那么下面来正经地发一封邮件,还是用telnet,顺便看一下有哪些常见的格式。

正经发一封邮件

最后

上面那个截图,用的都是英文,如果要用中文的话,需要指定编码格式之类,挺烦的,不妨打开一封从公共邮件商寄过来的邮件,看看邮件源代码。不过后面我们会借助第三方的软件来帮忙发送邮件,所以我们这里点到即止吧。
  现在已经可以正常发邮件了,还缺点啥呢?两点:1、如果我想用如foxmail之类的邮件客户端来远程连接到本邮件服务器发邮件,要怎么做呢?毕竟前面的配置,限制了mynetworks,但我们邮件客户端这头的IP可是不定的啊。2、通过TCP来连接这个SMTP服务器发邮件,这中间的数据传输都是明文的,如果邮件内容很私密很重要,就会担心被窃听,怎么办呢?我打算在下一篇文章里了解怎么解决这两个问题。

<br />
<br />
<br />

参考的文章:
  1. 鸟哥的Linux私房菜(第二十二章)
  2. 从零开始邮件服务器搭建
上一篇下一篇

猜你喜欢

热点阅读