背景
在上一篇講到了安裝完postfix之后,我們再服務(wù)器上有有了收發(fā)郵件的能力嘲碧。 然而因為我們只是做了一點微小的工作稻励,功能并不夠強大。只能使用root@example.com這個郵箱來進行收發(fā)。因為這時候郵件地址還是和linux服務(wù)器上的用戶一一對應(yīng)的望抽。并不能滿足筆者的需求加矛。筆者需要的是能夠隨意使用在本域下的任意郵箱的呀,所以本文就來探究如何在前篇的基礎(chǔ)上擴充郵件服務(wù)煤篙,使之具有承載虛擬用戶的能力斟览。
原理分析
postfix只是個MTA服務(wù)軟件,并不是一個真正的MDA軟件辑奈。postfix只是簡單將收到的郵件發(fā)給對應(yīng)用戶組下的郵件目錄中苛茂,以文件形式存儲下來。如果郵箱地址對應(yīng)的不是一個linux存在的用戶鸠窗,那么郵件就會被退回妓羊。如果需要很多虛擬用戶的話,就需要另尋他路了稍计,這里我們用dovecot來充當MDA的角色躁绸,來進行對虛擬用戶的操縱,并投遞到相應(yīng)虛擬用戶的目錄中臣嚣。而虛擬用戶的賬號净刮、別稱數(shù)據(jù)需要mysql來進行存儲。既然用mysql來進行存儲硅则,就要有賬號管理的應(yīng)用(注意dovecot只是從數(shù)據(jù)庫中讀取虛擬用戶的數(shù)據(jù)傳遞給postfix使用淹父,并不能很方便的創(chuàng)建和管理虛擬用戶的數(shù)據(jù)),這時候我們就可以使用postfixadmin來進行管理了抢埋。
因此本文所涉及到的是4個應(yīng)用
postfix(MTA) 負責郵件的傳輸
dovecot(MDA) 負責從mysql中讀取數(shù)據(jù)弹灭,轉(zhuǎn)發(fā)給postfix提供虛擬用戶的數(shù)據(jù)用以路由與驗證。
mysql(database) 負責存儲用戶數(shù)據(jù)揪垄。
postfixadmin 負責賬號的創(chuàng)建與管理穷吮,只是存儲數(shù)據(jù)庫的數(shù)據(jù),并不參與到郵件的轉(zhuǎn)發(fā)工作中饥努。
操作步驟
- step1 配置服務(wù)器用戶
為了安全起見捡鱼,我們要新配置一個用戶來管理這個郵件的收發(fā),我們叫vmail好了酷愧。
$ groupadd -g 5000 vmail #組號為5000,組名為vamil
$ useradd -u 5000 -g vmail -s /usr/bin/nologin -d /home/vmail -m vmail #用戶號為5000驾诈,屬于用戶組vmail,沒有登錄shell的權(quán)限溶浴,主目錄為/home/vmail并自動創(chuàng)建乍迄,最后這個用戶就叫vamil了。
- step2 使用postfixadmin配置虛擬域名以及虛擬用戶
$ apt-get install postfixadmin
安裝完以后士败,phpadmin就會彈出一個配置向?qū)斫o我們進行配置闯两。跟著操作來就好了褥伴,一般用默認配置就好了。postfixadmin會在數(shù)據(jù)庫中創(chuàng)建一個名字為postfixadmin的用戶漾狼,同時創(chuàng)建一個相應(yīng)的名字為postfixadmin的數(shù)據(jù)庫重慢。接著其就會自己進行配置和初始化了。
可以在安裝記錄的提示中看到數(shù)據(jù)庫創(chuàng)建的提示和配置文件所在目錄
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的方式在網(wǎng)頁上進行配置了似踱。postfixadmin的目web配置文件在/usr/share/postfixadmin/目錄下,我們要把其映射web服務(wù)器的可訪問目錄下稽煤。如果是用apache那么就自動配置好了核芽,只要訪問yourdomain/postfixadmin/index.php就好了,然而筆者用的nginx念脯,所以要自己額外映射一發(fā)狞洋。我們新開一個端口映射到域名下,那么我們訪問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
吉懊,看是否都配置成功。
筆者就悲傷的發(fā)現(xiàn)mysql這一塊失敗了
Error: Can't connect to database
Please edit the $CONF['database_*'] parameters in config.inc.php.
看了一下原因假勿,原來是我使用的是mysqli而不是mysql借嗽,然后我在dbconfig.inc.php里面改了一下type類型就就可以正常使用了。
修好以后转培,又發(fā)現(xiàn)初始化數(shù)據(jù)庫的時候執(zhí)行失敗了恶导,找了一下原因,是因為postfixadmin的bug浸须,日期的地方默認值填的是0惨寿,然而數(shù)據(jù)庫版本使用的strict模式,就執(zhí)行失敗了(后來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文件就可以發(fā)現(xiàn)數(shù)據(jù)庫都加載好了。配置好密碼后站宗,就愉快地訪問你的鏈接吧https://yourdomain:1234/index.php
闸准。
-
setup3 使用postadmin的web界面進行配置虛擬用戶
在經(jīng)過上一步之后,我們就可以從web界面進行配置了梢灭,那么登錄到https://yourdomain:1234/index.php
就可以看到下述界面夷家。
進去之后可以添加域和虛擬用戶腕唧。先創(chuàng)建一個hello@example.com的賬號進行后續(xù)使用 setup4 配置dovecot以及相應(yīng)的sasl
我們?nèi)绻邮軄碜酝庥虻泥]件,我們還要配置一個dovecot來管理外部郵件到虛擬用戶的映射瘾英。注意在前幾步中,我們只是添加postfixadmin來管理虛擬用戶颂暇,然而郵件是外域接受并傳遞到虛擬用戶這個過程并沒有被實現(xiàn)缺谴。所以我們就需要用dovecot來實現(xiàn)這個過程。
先安裝一下dovecot相關(guān)的包
$ 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/ssl/private/yourca.crt
ssl_key = </etc/ssl/private/yourca.key
接著配置一下/etc/dovecot/dovecot-sql.conf县爬,讓dovecot能夠訪問數(shù)據(jù)庫
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那一套财喳,然而我并沒有成功察迟,總是提示找不到對應(yīng)的文件。
- step5 配置postfix耳高,使得postfix通過dovecot來代理郵件到虛擬用戶的分發(fā)
配置/etc/postfix/main.cf扎瓶,在末尾加上
relay_domains = $mydestination
virtual_alias_maps = proxy:mysql:/etc/postfix/virtual_alias_maps.cf #數(shù)據(jù)庫的連接文件,后面要創(chuàng)建的
virtual_mailbox_domains = proxy:mysql:/etc/postfix/virtual_mailbox_domains.cf #數(shù)據(jù)庫的連接文件泌枪,后面要創(chuàng)建的
virtual_mailbox_maps = proxy:mysql:/etc/postfix/virtual_mailbox_maps.cf #數(shù)據(jù)庫的連接文件概荷,后面要創(chuàng)建的
virtual_mailbox_base = /home/vmail
virtual_mailbox_limit = 512000000
virtual_minimum_uid = 5000
virtual_transport = virtual
virtual_uid_maps = static:5000 #這里就是之前創(chuàng)建的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配置的時候緊密相關(guān)的碌燕,通過這個路徑才能進行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三個文件的數(shù)據(jù)庫配置愈捅。
/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中建立的虛擬郵箱hello@example.com用戶發(fā)一封郵件叠殷。就會發(fā)現(xiàn)郵件可以成功發(fā)送了改鲫。
碰到的問題
一路上還是碰到不少問題的,特別是搭建dovecot的時候林束,由于很陌生像棘,各個文檔的說法都不一致碰到過很多問題。這里有一個很有效的調(diào)試方法壶冒,發(fā)一封郵件缕题,然后看/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的接入方式(理論上兩種方式都可以的瘪松,只是兩個程序內(nèi)部的管道數(shù)據(jù)流罷了)。就是在/etc/dovecot中unix_listener的地方改成/var/spool/postfix/private/auth锨阿,同時在/etc/postfix/main.cf的smtpd_sasl_path改成private/auth宵睦。重啟兩個服務(wù)就可以了 - dovecot: auth: Fatal: Unknown database driver 'mysql'
這個是由于沒有安裝dovecot-mysql組件的原因,用aptget-install安裝一下就好了 - Temporary lookup failure
這個導(dǎo)致的原因多種多樣墅诡,我的原因是因為我在/etc/postfix/main.cf中同時開了virtual_transport和transport_maps壳嚎。前者是虛擬轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)到虛擬用戶末早,而后者是真實地路由到其他的服務(wù)器烟馅。所以把后者注釋掉了,就可正常接收郵件了然磷。否則由于我沒有transport.db文件郑趁,就會報錯收不到郵件。