背景
在上一篇讲到了安装完postfix之后,我们再服务器上有有了收发邮件的能力。 然而因为我们只是做了一点微小的工作,功能并不够强大。只能使用[email protected]这个邮箱来进行收发。因为这时候邮件地址还是和linux服务器上的用户一一对应的。并不能满足笔者的需求。笔者需要的是能够随意使用在本域下的任意邮箱的呀,所以本文就来探究如何在前篇的基础上扩充邮件服务,使之具有承载虚拟用户的能力。
原理分析
postfix只是个MTA服务软件,并不是一个真正的MDA软件。postfix只是简单将收到的邮件发给对应用户组下的邮件目录中,以文件形式存储下来。如果邮箱地址对应的不是一个linux存在的用户,那么邮件就会被退回。如果需要很多虚拟用户的话,就需要另寻他路了,这里我们用dovecot来充当MDA的角色,来进行对虚拟用户的操纵,并投递到相应虚拟用户的目录中。而虚拟用户的账号、别称数据需要mysql来进行存储。既然用mysql来进行存储,就要有账号管理的应用(注意dovecot只是从数据库中读取虚拟用户的数据传递给postfix使用,并不能很方便的创建和管理虚拟用户的数据),这时候我们就可以使用postfixadmin来进行管理了。
因此本文所涉及到的是4个应用
postfix(MTA) 负责邮件的传输
dovecot(MDA) 负责从mysql中读取数据,转发给postfix提供虚拟用户的数据用以路由与验证。
mysql(database) 负责存储用户数据。
postfixadmin 负责账号的创建与管理,只是存储数据库的数据,并不参与到邮件的转发工作中。
操作步骤
- step1 配置服务器用户
为了安全起见,我们要新配置一个用户来管理这个邮件的收发,我们叫vmail好了。
$ groupadd -g 5000 vmail #组号为5000,组名为vamil
$ useradd -u 5000 -g vmail -s /usr/bin/nologin -d /home/vmail -m vmail #用户号为5000,属于用户组vmail,没有登录shell的权限,主目录为/home/vmail并自动创建,最后这个用户就叫vamil了。
- step2 使用postfixadmin配置虚拟域名以及虚拟用户
$ apt-get install postfixadmin
安装完以后,phpadmin就会弹出一个配置向导来给我们进行配置。跟着操作来就好了,一般用默认配置就好了。postfixadmin会在数据库中创建一个名字为postfixadmin的用户,同时创建一个相应的名字为postfixadmin的数据库。接着其就会自己进行配置和初始化了。
可以在安装记录的提示中看到数据库创建的提示和配置文件所在目录
granting access to database postfixadmin for postfixadmin@localhost: success.
Creating config file /etc/dbconfig-common/postfixadmin.conf with new version
Creating config file /etc/postfixadmin/dbconfig.inc.php with new version
这样我们就基本安装好了postfixadmin,接着我们就可以从web的方式在网页上进行配置了。postfixadmin的目web配置文件在/usr/share/postfixadmin/目录下,我们要把其映射web服务器的可访问目录下。如果是用apache那么就自动配置好了,只要访问yourdomain/postfixadmin/index.php就好了,然而笔者用的nginx,所以要自己额外映射一发。我们新开一个端口映射到域名下,那么我们访问https://yourdomain:1234/index.php
就可以了
在/etc/nginx/sites-available目录下新建一个yourdomain_1234_postfixadmin
server {
listen 1234;
listen [::]:1234;
server_name yourdomain;
root /usr/share/postfixadmin;
index index.html;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
location / {
try_files $uri $uri/ =404;
}
}
然后配置一下重启nginx就好了
$ cd /etc/nginx/sites-enabled
$ ln -s ../sites-available/st0rm23.com_3789_postfixadmin
$ nginx -t
$ /etc/init.d/nginx restart
完了以后,访问一下先访问一下https://yourdomain:1234/setup.php
,看是否都配置成功。
笔者就悲伤的发现mysql这一块失败了
Error: Can't connect to database
Please edit the $CONF['database_*'] parameters in config.inc.php.
看了一下原因,原来是我使用的是mysqli而不是mysql,然后我在dbconfig.inc.php里面改了一下type类型就就可以正常使用了。
修好以后,又发现初始化数据库的时候执行失败了,找了一下原因,是因为postfixadmin的bug,日期的地方默认值填的是0,然而数据库版本使用的strict模式,就执行失败了(后来postfixadmin修了这个bug,然而笔者做的时候,这个bug修好了只在issue里面,还没有release出来)。于是笔者就手工修改了mysql去掉了严格模式。
在/etc/mysql/conf.d/目录下新建一个disable_strict_mode.cnf文件,输入
[mysqld]
sql_mode=IGNORE_SPACE,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
保存后,使用/etc/init.d/mysql restart重启加载配置就好了。这样重新刷新setup.php文件就可以发现数据库都加载好了。配置好密码后,就愉快地访问你的链接吧https://yourdomain:1234/index.php
。
-
setup3 使用postadmin的web界面进行配置虚拟用户
在经过上一步之后,我们就可以从web界面进行配置了,那么登录到https://yourdomain:1234/index.php
就可以看到下述界面。
进去之后可以添加域和虚拟用户。先创建一个[email protected]的账号进行后续使用 setup4 配置dovecot以及相应的sasl
我们如果要接受来自外域的邮件,我们还要配置一个dovecot来管理外部邮件到虚拟用户的映射。注意在前几步中,我们只是添加postfixadmin来管理虚拟用户,然而邮件是外域接受并传递到虚拟用户这个过程并没有被实现。所以我们就需要用dovecot来实现这个过程。
先安装一下dovecot相关的包
$ apt-get install dovecot-common
$ apt-get install dovecot-pop3d
$ apt-get install dovecot-imapd
$ apt-get install dovecot-mysql
然后配置dovecot的配置文件/etc/dovecot/dovecot.conf,注意如果有旧的的dovecot.conf,那么把旧的文件删掉,并不需要旧的那个了
protocols = imap pop3
auth_mechanisms = plain
passdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf
}
userdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf
}
service auth {
unix_listener /var/spool/postfix/private/auth {
group = postfix
mode = 0666
user = postfix
}
user = root
}
mail_home = /home/vmail/%d/%n
mail_location = maildir:~
ssl_cert =
接着配置一下/etc/dovecot/dovecot-sql.conf,让dovecot能够访问数据库
driver = mysql
connect = host=localhost dbname=postfixadmin user=postfixadmin password=password
# It is highly recommended to not use deprecated MD5-CRYPT. Read more at http://wiki2.dovecot.org/Authentication/PasswordSchemes
default_pass_scheme = SHA512-CRYPT
# Get the mailbox
user_query = SELECT '/home/vmail/%d/%n' as home, 'maildir:/home/vmail/%d/%n' as mail, 5000 AS uid, 5000 AS gid, concat('dirsize:storage=', quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'
# Get the password
password_query = SELECT username as user, password, '/home/vmail/%d/%n' as userdb_home, 'maildir:/home/vmail/%d/%n' as userdb_mail, 5000 as userdb_uid, 5000 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'
# If using client certificates for authentication, comment the above and uncomment the following
#password_query = SELECT null AS password, %u AS user
注意,这里我用的是private/auth这一套,有些文档使用的是auth-client那一套,然而我并没有成功,总是提示找不到对应的文件。
- step5 配置postfix,使得postfix通过dovecot来代理邮件到虚拟用户的分发
配置/etc/postfix/main.cf,在末尾加上
relay_domains = $mydestination
virtual_alias_maps = proxy:mysql:/etc/postfix/virtual_alias_maps.cf #数据库的连接文件,后面要创建的
virtual_mailbox_domains = proxy:mysql:/etc/postfix/virtual_mailbox_domains.cf #数据库的连接文件,后面要创建的
virtual_mailbox_maps = proxy:mysql:/etc/postfix/virtual_mailbox_maps.cf #数据库的连接文件,后面要创建的
virtual_mailbox_base = /home/vmail
virtual_mailbox_limit = 512000000
virtual_minimum_uid = 5000
virtual_transport = virtual
virtual_uid_maps = static:5000 #这里就是之前创建的vmail的uid 5000
virtual_gid_maps = static:5000
local_transport = virtual
local_recipient_maps = $virtual_mailbox_maps
transport_maps = hash:/etc/postfix/transport
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth #这里要注意,是和上面dovecot配置的时候紧密相关的,通过这个路径才能进行sasl的认证。
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_sasl_security_options = noanonymous
smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_received_header = yes
smtpd_tls_cert_file = /etc/ssl/private/www.st0rm23.com.crt
smtpd_tls_key_file = /etc/ssl/private/www.st0rm23.com.key
smtpd_sasl_local_domain = $mydomain
broken_sasl_auth_clients = yes
smtpd_tls_loglevel = 1
同时完成/etc/postfix/virtual_alias_maps.cf、/etc/postfix/virtual_mailbox_domains.cf、/etc/postfix/virtual_mailbox_maps.cf三个文件的数据库配置。
/etc/postfix/virtual_alias_maps.cf
user = postfixadmin
password = password #你的密码
hosts = localhost
dbname = postfixadmin
table = alias
select_field = goto
where_field = address
/etc/postfix/virtual_mailbox_domains.cf
user = postfixadmin
password = password #你的密码
hosts = localhost
dbname = postfixadmin
table = domain
select_field = domain
where_field = domain
/etc/postfix/virtual_mailbox_maps.cf
user = postfixadmin
password = password #你的密码
hosts = localhost
dbname = postfixadmin
table = mailbox
select_field = maildir
where_field = username
这样用/etc/init.d/postfix restart 重启完postfix后就可正式生效了。我们可以用公共的邮箱向在step3中建立的虚拟邮箱[email protected]用户发一封邮件。就会发现邮件可以成功发送了。
碰到的问题
一路上还是碰到不少问题的,特别是搭建dovecot的时候,由于很陌生,各个文档的说法都不一致碰到过很多问题。这里有一个很有效的调试方法,发一封邮件,然后看/var/log/mail.log下的日志
$ tail /var/log/mail.log -n 20
很明显能够看到失败的原因,这里分享几个错误和解决的方法。
- postfix/smtpd[19476]: warning: SASL: Connect to /var/run/dovecot/auth-client failed: No such file or directory
这个我也不知道为什么postfix和dovecot在auth-client的文件上找不到。后来我就改成了private/auth的接入方式(理论上两种方式都可以的,只是两个程序内部的管道数据流罢了)。就是在/etc/dovecot中unix_listener的地方改成/var/spool/postfix/private/auth,同时在/etc/postfix/main.cf的smtpd_sasl_path改成private/auth。重启两个服务就可以了 - dovecot: auth: Fatal: Unknown database driver 'mysql'
这个是由于没有安装dovecot-mysql组件的原因,用aptget-install安装一下就好了 - Temporary lookup failure
这个导致的原因多种多样,我的原因是因为我在/etc/postfix/main.cf中同时开了virtual_transport和transport_maps。前者是虚拟转发,转发到虚拟用户,而后者是真实地路由到其他的服务器。所以把后者注释掉了,就可正常接收邮件了。否则由于我没有transport.db文件,就会报错收不到邮件。