一、邮件系统组成

  1. MUA(Mail User Agent)邮件用户代理。用户通过MUA使用邮件系统。
  2. MTA(Mail Transfer Agent)邮件发送代理。使用SMTP(Simple Mail Transfer Protocol)在服务器之间传送邮件。
  3. MDA(Mail Delivery Agent)邮件传送代理。Delivery有传送、投递的意思,跟transfer意思相近,在这里delivery主要是指投递,MDA的作用是根据邮件表头或内容数据,决定邮件走向——本地客户发出的邮件如果收件地址是本地,则由MDA直接投递,MTA收到的远程邮件如果收件地址是本地,也交由MDA投递。简而言之,MDA就是快递小哥,收发都要通过他。而MTA就是邮局(快递公司),一封邮件可能会经过多个MTA,大概流程是MUA->MDA->MTA->……->MTA->MDA->MUA这样。实际上MDA往往是MTA下挂的一个小程序,但是也有的MTA可以配置为外挂功能更强大的MDA,实现强大的邮件过滤及自动回复等功能。
  4. MRA(Mail Retrieval Agent)邮件接收代理。不能直接登录服务器的用户,通过MUA使用POP3(Post Office Protocol version 3)或IMAP(Internet Messages Access Protocol)协议与MRA通信,实现邮件接收。

二、软件安装

Postfix实际上只是一个MTA+MDA,要支持客户端远程收发邮件还需要Dovecot作为MRA,如果不需要用客户端远程收发文件,比如采用基于Web的邮件客户端,也可以不用。MUA的话,服务器上最好安装一个简易的mailx进行测试,实际使用的如Outlook、Outlook Express、Foxmail、Thunderbrid都很常见,只是对服务器功能的支持略有不同。

Postfix Admin是一个基于PHP的邮件服务器管理工具,主要提供对Postfix邮件服务器的虚拟域名及虚拟用户管理功能。但是要使用Postfix Admin需要安装一个Web服务器、PHP、Mysql或Postgres等数据库。

dnf install mailx #mail这个命令其实是在mailx这个包里
dnf install mysql-server #服务器上安装这个就行了,其他的依赖会自动解决;
dnf install postfix-mysql #因为要用到mysql数据库,所以直接安装这个包,同样,依赖会自动解决;
dnf install dovecot-mysql #同上
dnf groupinstall 'Basic Web Server' #安装Apache,也可以用dnf install httpd
dnf install php php-mbstring php-mysqlnd

安装好之后,以服务方式启动这几个服务,注意Mysql的服务名

systemctl start mysqld
systemctl start postfix
systemctl start dovecot
systemctl start httpd

再用systemctl status servicename检查一下是否正常。可能会有一些错误,一般都是文件读写权限方面的问题,对于postfix,可以用postfix set-permissions命令修复权限。有时候会有一个pid.master不能读写的错误,重新安装postfix可以解决这个问题。

Postfix Admin一般安装在/srv目录下,所以直接下载压缩文件到/srv目录下,并解压缩

$ cd /srv/
$ wget -O postfixadmin.tgz https://github.com/postfixadmin/postfixadmin/archive/postfixadmin-3.2.tar.gz
$ tar -zxvf postfixadmin.tgz
$ mv postfixadmin-postfixadmin-3.2 postfixadmin
$ ln -s /srv/postfixadmin/public /var/www/html/postfixadmin #通过软链接发布到Web服务器。

$ chcon -R -t httpd_sys_content_t /srv/postfixadmin #Postfix Admin运行时会读取这个目录下的php配置文件,所以需要修改SELinux目标
$ semanage fcontext -a -t httpd_sys_content_t "/srv/postfixadmin/templates_c(/.*)?"
$ mkdir -p /srv/postfixadmin/templates_c #Postfix Admin运行时会读取这需要写这个目录,所以单独创建出来并修改拥有者
$ chown -R apache:apache /srv/postfixadmin/templates_c
$ chcon -R -t httpd_sys_content_rw_t /srv/postfixadmin/templates_c
$ semanage fcontext -a -t httpd_sys_content_rw_t /srv/postfixadmin/templates_c

三、配置及说明

1.Postfix基本配置说明

Postfix的配置主要是在/etc/postfix/main.cf里,有七百多行,很复杂(据说sendmail更复杂),但是其默认配置很好用,重要的参数有下面几个:

myhostname = hostname.localdomain
mydomain = localdomain
myorigin = $myhostname (or $mydomain)
mydestination = $myhostname localhost.$mydomain localhost
mynetworks_style = subnet  (or host)
mynetworks = 127.0.0.0/8
relay_domains = $mydestination
relayhost = 
proxy_interfaces = 1.2.3.4
inet_interfaces = all

myhostname、mydomain这两个参数就像是变量,主要用于别的参数。起作用的主要是myorigin、mydestination、relay_domains三个,myorigin影响向外发送邮件的域名部分,Email地址可以是“用户名@域名”也可以是“用户名@主机名”,显然“用户名@域名”形式要简洁一些,但是很明显只有MX记录指向的主机才能这么做,而且一般的反垃圾邮件机制也会反解收到的地址看是不是MX记录的主机地址。所以“用户名@域名”是标准的用法,而其他邮件服务器主机就只能采用“用户名@主机名”形式了,其向外发送的邮件可以由MX那台主机转发。mydestination这个参数是影响收到的邮件的,也就是根据这个参数,比较邮件地址@符号后面的部分,判断是不是本机的邮件,很显然,如果是域的MX主机,应该要加上$mydomain才行。

relay_domains决定转发的域,默认就是$mydestination,如果不是MX主机,或者域内没有其他邮件服务器需要帮转,不设也没关系,当然relayhost就是指只帮转几台主机的邮件而已。mynetworks_style和mynetworks指明所在的子网甚至可以指定为一个host,也就是MUA可以从哪些地址接入,当然,本机就是127.0.0.1但是如果要用MUA远程连接邮件服务器的话,这里必须添加局域网地址段。inet_interfaces是外网接口,实际上是SMTP服务监听的接口,如果服务器有多个网口而只想通过一个接口接收邮件的话就设置,否则默认的all就很好。proxy_interfaces是代理服务器接口,如果主要是通过代理服务器连接internet的,那么这里就填代理服务器的地址。

实际上无需修改任何参数,Postfix就已经能支持本机用户间的邮件收发了。可以在服务器上用mail命令测试一下是否工作正常。

echo 'This is Test'|mail -s 'Test Mail' $USER

2.虚拟邮箱配置

Postfix支持虚拟邮箱和别名,使得即使用户没有服务器账号也能收发邮件。别名的作用可以实现邮件转发,甚至可以转发到其他邮件主机上的邮箱中。虚拟邮箱则是在本机上虚拟邮箱。虚拟邮箱需要设置以下参数:

virtual_mailbox_domains = example.com
virtual_mailbox_base = /var/mail
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_minimum_uid = 1
virtual_uid_maps = static:8
virtual_gid_maps = static:12

virtual_mailbox_domains就是虚拟邮箱的域名,不能把这个域名列入mydestination,也不能列入virtual_alias_domains域,换句话说,就是一个域名只能有同一种类型的邮箱。virtual_mailbox_base是邮箱的主目录,具体的虚拟用户和邮箱的对应关系由virtual_mailbox_maps确定。其中的邮箱目录就是相对于virtual_mailbox_base的相对目录,如果相对目录后面带斜杠,表示以目录方式保存邮件,即邮箱为Maildir格式,否则则是以单一文件保存邮件,即邮箱为mbox格式,其他关于邮箱目录的设置基本上都是这个规则。示例中/etc/postfix/vmailbox文件是一个<键>:<值>列表,用postmap /etc/postfix/vmailbox生成/etc/postfix/vmailbox.db文件,然后在配置文件里面用hash:前缀指明文件类型(但是不带.db),这样实际读取的是带.db的文件,查找用户名的效率要高一些。

邮箱的所有上级目录必须事先建好,Postfix投递邮件时可以创建邮箱但不会创建邮箱的上级目录,如果邮箱的上级目录不存在,则投递失败。使用Postfix Admin时,其默认的邮箱相对路径是“域名/用户名”,所以在Postfix Admin中新建域之后需要手工创建对应的目录。

virtual_uid_maps、virtual_gid_maps设置虚拟用户的缺省uid和gid,Postfix以这个uid、gid模拟用户来投递邮件,uid或gid需要有该用户邮箱目录的访问权限。如果virtual_mailbox_maps来源是数据库的话,uid、gid是可以被覆盖的。virtual_minimum_uid设定了虚拟用户的最小id,目的是避免虚拟成系统已有的其他用户获得较高的权限。但是,改小一点应该不会有什么问题。

如果不使用Postfix Admin管理邮箱,virtual_mailbox_domains可以设置为固定的值、virtual_mailbox_maps可以用文本文件或postfix支持的hash格式,当然也可以自己建数据库表自己写查询语句来实现。使用Postfix Admin的话,表结构就得按Postfix Admin的来,相应的SQL配置文件可以通过“sh /srv/postfixadmin/DOCUMENTS/POSTFIX_CONF.txt”生成在/tmp目录下,mv到/etc/postfix/sql下就可以了。当然,数据库名、数据库用户名、密码,必须事先确定甚至建好。

建库、用户命令参照以下代码:

  CREATE DATABASE postfix;
  CREATE USER 'postfix'@'localhost' IDENTIFIED BY 'postfix';
  GRANT ALL PRIVILEGES ON `postfix` . * TO 'postfix'@'localhost';

修改/etc/postfix/main.cf,在最后添加:

virtual_mailbox_base = /var/mail
virtual_minimum_uid = 1
virtual_uid_maps = static:8
virtual_gid_maps = static:12
virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf
virtual_alias_maps =
   proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf,
   proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf,
   proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf
virtual_mailbox_maps =
   proxy:mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf,
   proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf

这里直接用系统自建的mail用户及其组作为虚拟用户的用户和组,查得uid、gid分别为8和12,所以virtual_minimum_uid的值改为1。

3.Postfix Admin配置

如果使用Postfix Admin,需要先配置好,才能建虚拟域、虚拟邮箱。

1.配置准备

Postfix Admin的配置主要通过Web界面进行,但是之前需准备好连接数据库的配置文件。新建/srv/postfixadmin/config.local.php文件,包含数据库信息。

<?php
$CONF['database_type'] = 'mysqli';
$CONF['database_user'] = 'postfix';
$CONF['database_password'] = 'postfix';
$CONF['database_name'] = 'postfix';

$CONF['configured'] = true;
?>

这些配置项config.inc.php里面都有说明,其中mysqli就是指mysql 4.1+版本,更低版本的才用mysql表示。还有就是$CONF[‘configured’]必须设为true。

2.启动Web设置界面,检查配置,创建管理员帐号

用浏览器访问:http://yourserver.tld/postfixadmin/setup.php

调试PHP时,可以修改/etc/php.ini文件,将display_errors、log_errors设置为on,这样可以看到错误信息。如果遇到莫名的权限问题,可以试着setenforce 0临时关闭SELinux。实在不行就修改SELinux的配置文件/etc/sysconfig/selinux将”SELINUX=enforcing”改为”SELINUX=Permissive”。

根据提示进行进行修改,一般都是缺少依赖,安装上去刷新就行了。其中有一项php5-imap包,这个需要手工编译PHP才能加上,作用是创建邮箱时创建相应的目录。暂时不管。除了这一项之外,其他问题解决之后,就会自动建表。然后就会要求设置SETUP口令,这个口令设置后,要把页面上显示的一个hash复制粘贴到config.local.php里去,意思是说以后要通过这个界面修改设置的话,就需要知道口令才行。再往下就是设置管理员,这里设置好一个之后还会继续提示设置,不想设就不管了。直接修改地址到http://yourserver.tld/postfixadmin/ 就可以用管理员登录了。

新建一个域和一个邮箱,在虚拟邮件的主目录下建一个域名的目录,修改目录所有者为postfix中设置的uid和gid。在服务器上用mail发送一封邮件进行测试,用postqueue -p或mailq命令查看邮件队列,再检查虚拟邮箱下是否有新邮件。如果邮件不能正常投递,通常是邮箱目录路径不存在或者没有访问权的原因。

3.Dovecot配置

1.基本概念及基础配置

Dovecot的配置要复杂一些,主要配置文件是/etc/dovecot/dovecot.conf,但是还有分片的配置文件在/etc/dovecot/conf.d下,在默认的配置文件dovecot.conf里,通过!include conf.d/*.conf !include_try local.conf把分片的配置文件包含进来。当然也可以注释掉这两个语句,直接在dovecot.conf里配置。那就不如不修改原来任何文件,直接新建一个local.conf进行配置。

Dovecot是一个MRA,主要作用是接受远程邮箱用户连接,把远程邮箱用户的邮件发给用户。那么,首先它得知道用户的邮件在哪。官方文档说它会自动诊断用户的邮箱位置,但是当用户邮箱为空时实际没办法诊断,所以需要手工设置。手工设置可以通过mail_location来设置,但这个是全局性的,可以在userdb(用户信息)配置里面被重载。所以,对于Postfix的默认配置,也就是邮箱采用mbox格式的情况下,只需要在local.conf里这样配置:

mail_location=mbox:/var/mail:INBOX=/var/mail/%n

Dovecot还有一个mail_home的概念,用来保存一些个人相关的信息比如回收站、检查邮件重复的数据库等等,这个目录和系统的Home目录并不相关(如:虚拟用户没有系统Home目录,但需要有一个mail_home目录,否则用客户端删邮件都删不掉,因为客户端删邮件实际上是删除到回收站。所以后面建虚拟用户还需要同时创建虚拟用户的主目录),对于通过系统认证的用户,Dovecot会从passwd文件中获取home目录作为用户的mail_home目录,对于虚拟用户,同样可以通过userdb配置重载,所以,并不需要专门设定一个全局mail_home变量。

Dovecot把所有认证的查找分在两个集合中,一个是User Database(userdb),一个是Password Database(passdb),用doveconf -n可以得到默认配置如下:

userdb{
    driver=passwd
}
passdb {
  driver = pam
}

driver=passwd用户数据库就是系统passwd文件中的用户,driver=pam指的是系统提供的可插拨身份认证方式,依赖于/etc/pam.d/dovecot文件中配置的模块,可以简单地理解为用操作系统认证用户的方式来认证用户。也即是说,只需要在local.conf里面添加一条配置,其他不用做任何修改,操作系统用户(root用户除外,可能是基于安全性考虑)此时也已经可以使用imap、pop3收发邮件了的。

2.Dovecot虚拟邮箱用户配置

虚拟邮箱用户的userdb肯定不能再是passwd,密码验证方式也不可能还是pam,userdb的driver有很多种,不同的driver互不影响的,甚至于一个db查找之后还可以接着用另一个db查找以补充完善信息,只不过这种高级功能不知道怎么发挥作用,暂时不管。/etc/dovecot/conf.d/10-auth.conf里面有一行#!include auth-sql.conf.ext去掉注释,再用doveconf -n可以看到多了一段

userdb {
  args = /etc/dovecot/dovecot-sql.conf.ext
  driver = sql
}
passdb {
  args = /etc/dovecot/dovecot-sql.conf.ext
  driver = sql
}

这里,假设所有通过sql查找的用户都采用Maildir格式邮箱且邮箱为/var/mail/virual domain目录中用户同名的目录。不用修改前面的mail_location设置,可以在userdb里用覆盖。mail_home变量也是同样。所以,在auth-sql.conf.ext里找到这一段配置,改成下面这样(passdb不用修改):

userdb {
  args = /etc/dovecot/dovecot-sql.conf.ext
  driver = sql
  override_fields=uid=8 gid=12 home=/var/mail/%n mail=maildir:/var/mail/%d/%n 
}

这些字段都是可以从数据库查询结果集获得,不过没有必要写那么复杂的查询语句。当然,/etc/dovecot/dovecot-sql.conf.ext这个文件是没有的,安装了Postfix Admin之后,/srv/postfixadmin/DOCUMENTS/DOVECOT.txt有说明和语句,参照说明,编辑dovecot-sql.conf.ext文件内容如下:

driver = mysql
default_pass_scheme = MD5-CRYPT 
connect = host=localhost dbname=postfix user=postfix password=postfix 

password_query = SELECT username AS user,password FROM mailbox WHERE username = '%u' AND active='1'
user_query = SELECT CONCAT('/var/mail/vmail/', maildir) AS home, CONCAT('*:bytes=', quota) AS quota_rule FROM mailbox WHERE username = '%u' AND active='1'
#For using doveadm -A:
iterate_query = SELECT username, domain FROM users

主要就是一个连接字符串,一个用户查询语句和一个密码查询语句。default_pass_scheme可选PLAIN、PLAIN-MD5、MD5-CRYPT但需要与Postfix Admin配置中的$CONF[‘encrypt’]相同。如果不用Postfix Admin,则只能选择PLAIN或PLAIN-MD5且PLAIN-MD5需要在自己写入数据库记录时调用MD5函数。选择MD5-CRYPT就需要自己实现算法或用其他支持MD5-CRYPT的软件。

可以用doveadm user user@domain测试查找用户信息;用doveadm auth test user@domain password测试检索用户口令;用doveadm auth login user@domain password测试用户登录。全部测试通过之后真实登录如果还有问题那就是目录以及访问权限方面的问题了。

4.通过客户端远程收发邮件

1.相关设置

Postfix默认是不允许外部访问的,要允许本地局域网访问,需要在mynetwork中添加本地网段。还要修改监听接口,默认是只监听环回接口的,可以简单地改inet_interfaces = all。

Dovecot本身就是提供给邮件客户端使用的,默认允许连接,但是只允许加密的SSL连接。没有配置SSL连接之前,需要ssl=no及disable_plaintext_auth = no。 1.防火墙设置 SMTP、IMAP、POP3这三个服务的端口肯定是要开放。

firewall-cmd --get-active-zones //查看活动的域
firewall-cmd --get-services //查看预定义的服务,SMTP、IMAP、POP3这3个应该是有的
firewall-cmd --zone=public --add-service smtp --permanent
firewall-cmd --zone=public --add-service imap --permanent
firewall-cmd --zone=public --add-service pop3 --permanent
firewall-cmd --zone=public --add-service imaps --permanent
firewall-cmd --zone=public --add-service pop3s --permanent
firewall-cmd --reload //重新加载规则

从外部telnet一下25、143、110。如果不成功,一个是用netstat -lntup检查端口服务是否已启动,一个是检查防火墙,可以把防火墙关掉试试。Foxmail、Thunderbrid在添加邮箱账户时,需要验证邮箱登录,并且收和发都成功才能保存,所以可能需要检查postfix、和dovecot两方面的配置。

2.启用smtp身份认证

Postfix本身并不提供SMTP身份认证,而是用现有的SASL(Simple Authentication and Security Layer)实现,当前支持Cyrus SASL和Dovecot SASL实现。网上介绍Cyrus SASL配置的比较多,但因为又是另一种软件,所以又会有一套相应的配置文件,而Dovecot已经实现了imap/pop3的身份认证,把这个应用到SMTP上就可以减少很多配置,所以,采用这个方案。

首先,修改/etc/postfix/main.cf文件,增加Postfix相关的配置:

 smtpd_sasl_auth_enable = yes
 broken_sasl_auth_clients = yes #这个参数在应答时返回的AUTH之后加上一个等号分隔符。针对不超过2003版(包括2003版)的Outlook和不超过6版的Outlook Express启用此选项。
 smtpd_sasl_type = dovecot #指定SASL实现
 smtpd_sasl_path = private/auth #采用UNIX-domain socket通信
 smtpd_sasl_security_options = noanonymous #禁止匿名登录
 smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination

其次,修改/etc/dovecot/conf.d/10-master.conf文件,找到unix_listener /var/spool/postfix/private/auth这一行,取消注释并修改为:

 service auth {
  ...
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    # Assuming the default Postfix user and group
    user = postfix
    group = postfix        
  }
  ...
}

注意不要把unix_listener userdb这一行改了。mode是指套接字的访问权,如果改为0666则任何用户都能读写,那么就不需要配置user和group了。另外,Outlook Express和Windows Mail只支持LOGIN认证而不是标准的PLAIN,所以要支持的话需要修改/etc/dovecot/conf.d/10-auth.conf文件中的auth_mechanisms = plain login这一行,在后面加上login。

前面的配置完成之后,可以再修改/etc/postfix/main.cf中的mynetwork,把局域网网段去掉(如不去掉,总是会允许mynetwork网段发邮件的),然后重启postfix和dovecot,再次用客户端进行远程收发邮件测试。

3.安全传输

安全传输层协议TLS(Transport Layer Security协议)的前身就是SSL(Secure Sockets Layer),大多数软件即使使用TLS v1但是在说明中仍然使用的是SSL这个术语,混淆这两个概念其实问题并不大,只需要知道在TLS中加密传输不一定要使用另外的端口号,而是采用STARTTLS协商,双方都支持加密传输就使用加密传输,否则还是普通的传输。对于Dovecot来说就是这样,不一定非要启用IMAPs/POP3s端口(默认是启用的),只需要设置ssl这个参数。ssl=no就是不启用,ssl=yes表示启用但并不是强制的,ssl=required是强制使用。TLS/SSL相关配置在/etc/dovecot/conf.d/10-ssl.conf文件里,默认ssl=required改为yes兼容性最好,这个配置文件里还有服务端证书及私钥位置等,可以检查一下,但是无需修改。

ssl=required的情况下,可以在/etc/dovecot/conf.d/10-master.conf里找到inet_listener imap和inet_listener pop3配置,可以把port改为0也就是关闭imap/pop3的监听,但是意义不大。

启用TLS/SSL需要证书(链)和私钥,postfix和Dovecot安装时就准备并且默认配置好了。对于postfix还可以通过postfix tls new-server-cert和postfix tls new-server-key这两个命令重新生成。甚至可以用postconf -X postconf -nH | egrep '^smtpd(_|_enforce_|_use_)tls'这个命令删除恢复TLS相关配置,重新生成配置及证书、私钥并修改好配置文件。只需要postfix tls enable-server启动就行了。有关的配置如下:

smtpd_tls_security_level = may
smtpd_tls_loglevel = 1
smtpd_tls_cert_file = /etc/pki/tls/certs/postfix.pem
smtpd_tls_key_file = /etc/pki/tls/private/postfix.key
smtpd_tls_auth_only = yes

5.配置及调试建议

配置过程中,最好是一个功能配置完就测试一下,而不要全部一起配置完再测试,那样的话出了问题不好找。测试出了问题就多看看LOG。默认情况下,Postfix和Dovecot的日志都记录在/var/log/maillog里,dovecot还可以用auth_debug=yes、auth_debug_passwords=yes打开调试模式,这样输出的日志更详细一些。

6.其他问题

Foxmail支持TLS/SSL可能有问题,不能连接POPs/IMAPs,用Thunderbrid就可以。但Thunderbrid直接选择IMAPs建帐号就检查通不过,无法保存帐户,如果先连上IMAP,再修改连接方式为安全连接,也可以用,POP3s就没问题。其他客户端还没测试。

开启SMTP身份验证之后,应该是没办法接收其他外部邮件服务器发来的邮件了,除非其他的邮件服务器配置好作为SMTP客户端时的用户信息(Dovecot SASL不支持,Cyrus SASL支持)。所以真实的应用可能需要两台以上的邮件服务器,一台是MX主机,配置成允许所有地址连接,不安装MRA,专门用于转发本域的邮件,其他就可以开启SMTP身份认证甚至SMTPs协议,负责接受客户端连接,收、发用户邮件。