繁體 | 簡體
Install and configure Postfix with Cyrus-SASL + Cyrus-IMAP + MySQL v1

*********************************************************************************
作者:正港 (LanceLoTest)
Mail: LanceLoTest@hotmail.com
Msn: LanceLoTest@hotmail.com

版權宣告:
這是篇共享的文件,任何人都歡迎轉載,請 保持文章的完整性 以及 出處連結
好讓後來讀這篇 Howto 的人可以尋線找到這篇 Howto 的最新版本,僅供學術用途,謝謝。

這份 Howto 的最新版本,可以由此查閱 (不定期更新)
繁體 Howto: http://doc.uniorg.net/postfix/index.php
簡體 Howto http://doc.uniorg.net/postfix/index1.php
UO-小築 http://www.uniorg.net/viewthread.php?tid=14062
最後更新日期:August 08, 2004
*********************************************************************************


注意事項

在開始之前,請先更新你的 ports
# cd /usr/ports ; make update

顏色與標記
紅色:要下的指令
綠色:有兩種可能,一為 系統 output 的訊息 ,二為 要增加至檔案的內容
黃色:不確定是否可省下的步驟,可以先照做無妨
##:雙井號為註解


目鍵 Table of Contents

適用對象與目標
感謝
記錄
前言
簡介
安裝前的緩身
寫這份 Howto 時所使用的軟體版本
安裝與設定 MySQL
安裝與設定 pam_mysql
安裝 cyrus-sasl2-saslauthd
用 TLS 來建立 SMTP 和 IMAP 的安全連線
安裝與設定 cyrus-imap
安裝與設定 postfix
使用 Expect + script + PHP 完成信箱的建立
資源


適用對象與目標

此份 Howto 適用於 FreeBSD 4.x/5.x 的使用者,小弟在此兩種版本皆測試過,本 Howto 的目標在建立一個完善的郵件伺服器 (Mail server) 系統,通過 SASL 認證 (authentication) 來收發郵件、TLS 加密連線,和使用 MySQL 做為儲存使用者帳號/密碼等資料的資料庫,以及搭配 PHP 完成一系列的帳號和信箱的建立 (如會員在PHP論壇註冊後可立即啟用信箱)。


感謝

cdr, 星雨, 青島的天空 的幫助,好讓這篇 Howto 越來越完整


記錄


前言

這份 Howto 是小弟這一個月半以來,第一次玩 Mail server 的一點私人心得筆記,在過程中,不知有多少個夜晚是泡麵和牛奶陪我渡過,到處搜尋相關資料,看遍了 google 及許多 mailing-list 的文件,也有耐心的反反覆覆的安裝所有相關軟體數十遍,但它不動就是不動。經過一翻的折騰,所有的功能一項項的慢慢正常啟動服務了,心裡甚是高興。也許是那不服輸的精神感動了老天爺,讓小弟的 Mail server 得以服役執勤中,小弟始終深信老天爹是疼憨小孩的 ^_^

有鑑於各軟體官網文件的說明不夠淺顯易懂(也許小弟程度差) 以及網路上的相關資料不夠齊全 or 已過時不適用於新版本上,中文的相關資料更是少之又少,於是乎,小弟興起了寫 Howto 的念頭,把這一個月半以來花的長時間與精神寫份心得分享給大家,好讓各位少走一點冤枉路,省去些寶貴時間與精神,在此也感謝軟體開發者以及書寫文件的前輩們,好讓我們這些後生晚輩們有個指引的方向來使用這優秀的 Mail server。

另外,小弟想讓這份 Howto 變成一份好的文件資源,但小弟懂得實在不多,菜得很,在此希望眾前輩們能多多提供點意見及補充說明,請不吝惜指令,小弟尤衷的敬佩也感激各位點點滴滴的貢獻,也希望中文使用者群的水平能越來越高,謝謝。


簡介

建構一個完善安全的郵件伺服器系統,需要包含 SMTP, POP3/IMAP, SASL, TLS, Anti-Virus/Spam。

現存有好多種不同的 SMTP server 舉凡 Sendmail, QMail, Exim, and Postfix,為何小弟獨忠於 Postfix ,選它做為 MTA (Mail Transfer Agent) 呢?小弟查閱了許多國外的討論區,對 Postfix 評價都是蠻高的,它的速度快、可擴充、有彈性 (flexibility)、模組化 (modular) 以及高安全性 (security),吸引了我,它人性化的設定也挺容易上手。

IMAP server 的部分,比較有名的幾套 Courier-IMAP, UW-IMAP, and Cyrus-IMAP,會選擇 Cyrus-IMAP 也是因在國外討論區看了許多的討論,總觀各方的優缺點所做的決定。關於信件儲存的方式,Courier-IMAP 使用 MailDir,UW-IMAP 使用 standard, low performance Unix Mailbox style,而 Cyrus 則是使用它自己獨立的資料庫。Courier-IMAP 和 Cyrus-IMAP 有提供 容量限制 (quotas) 的功能來替代系統中原有的 filesystem quotas,而 filesystem quotas 它不會提醒你容量是否快要滿了,當容量滿時,filesystem quotas 就立即停止接收新的 mail,另一方面,Cyrus-IMAP 提供的 "soft-quotas" 功能,它會偵察使用了多少空間以及數量,當接近容量限制 (quota) 時,它會親切的提醒你,要你做好準備。一旦 quota 界滿時,它會再次的向 user 發出警告,期間如有 mail 傳入,它會退回 (bounced back) 該 mail,並且解釋說該使用者信箱已滿。這樣貼切的功能,讓遺失 mail 的機率降為更低。


安裝前的緩身

什麼是 MTA, MDA, MUA ?
MTA (Mail Transfer Agent) 這服務可幫我們把 mail 傳送給其它 mail server ,它也可幫我們接受外部主機寄來的信件,所有的 SMTP servers 都可稱為 MTA。

MDA (Mail Delivery Agent) 這服務是用來把 MTA 所接受的 mail 傳遞 至 使用者 mailbox 的裡頭,所有的 SMTP servers 也都可稱為 MDA,但並非所有的 MDA 都是 SMTP server,舉例如 procmail 則是個單純的 MDA。

MUA (Mail User Agent) 就是 mail client 端的軟體,它幫我們傳送與接受 mail,使用者透過它來跟 mail server 溝通,一般使用者與它有最直接的接觸,也是最熟悉的,常見的 MUA 有 Outlook express, Kmail, Mozilla Thunderbird 等,小弟在此推薦使用 Open Source 的 Mozilla-Thunderbird ,它有 for Windows, Linux, Mac OS X 等的版本。
Mozilla Thunderbird 官網: http://www.mozilla.org/products/thunderbird/
中文站: http://www.csie.ntu.edu.tw/~r91034/mozilla/

什麼是 SMTP ?
SMTP (Simple Mail Transfer Protocol) 簡言之是用來發送 mail 的協定,一般使用 port 25。

什麼是 POP3 ?
POP3 (Post Office Protocol, Version 3) 簡言之是用來接收 mail 的協定,一般使用 port 110。

什麼是 IMAP ? 跟 POP3 類似,但功能更強大,一般使用 port 143。

POP3 vs. IMAP
POP3 儲存 mail 的方式是把所有的 mails 存於一個 File 裡面。而 IMAP 儲存 mail 的方式是每封 mail 即是一個檔案,這樣有個好處是,如果硬碟有某一段壞軌,也不致於損失慘重。

POP3 client 端連線到 POP3 server 端時,會把 mail 下載至本地端的電腦裡頭,下載完成後,server 即會把這些 剛下載的 mails 給刪除,這樣一來的缺點是,你只能在這台電腦上閱讀你的 mail,如果你是需要到處跑,隨時隨地要收取 mail 的人,那麼 POP3 便不符合你的需求,因為你無法在別台電腦閱讀先前下載好的 mails。

IMAP4 儲存所有用戶的 mails 於 server 中,IMAP client 端連線到 IMAP server 端時,會下載該 mail 的 標頭檔 (header),如果你想要閱讀該封 mail 的內容,你則會從 server 下載備份(copy) 的 mail 至你的本機,然後你便可閱讀它了。如果你(client) 刪除了某一封 mail,同樣的 server 端也會刪除此封 mail。由於所有的 mail 都是儲存於 server 中,所以你可以在任何異地,經過認證 (authenticate) 後下載/閱讀你的 mail。

如果你 or 你的用戶經常不固定使用同一台電腦來收取 mail,那麼,IMAP 會是比較好的選擇。反之,如果你只想要個比較簡易的郵件系統,那麼選擇 POP3 就夠了。小弟建議使用 IMAP server,因為它也同樣可以提供 POP server 的服務,如此一來,你可以比較有選擇性的來設定其功能。


寫這份 Howto 時所使用的軟體版本

FreeBSD 4.x/5.x
mysql-server-4.0.20 (Cyrus-SASL 尚不支援 MySQL 4.1 版)
cyrus-sasl-2.1.19
cyrus-sasl-saslauthd-2.1.19
cyrus-imapd-2.2.8
db41-4.1.25_1
postfix-2.1.4,1
expect-5.38.0_3

請確認 /etc/services 裡頭是否有下列的 services,沒有的話請自行新增:
smtp 25/tcp
smtp 25/udp
pop3 110/tcp
pop3 110/udp
imap 143/tcp
imap 143/udp
imsp 406/tcp
acap 674/tcp
imaps 993/tcp
pop3s 995/tcp
kpop 1109/tcp
sieve 2000/tcp
lmtp 2003/tcp
fud 4201/udp


安裝與設定 MySQL

安裝 MySQL 前,變更一下 MySQL 預設的安裝路徑 (非必要,依個人喜好)
# ee /usr/ports/databases/mysql40-server/Makefile
DB_DIR?= /var/db/mysql
改成 DB_DIR?= /usr/local/mysql

開始安裝 MySQL,第一次安裝的話需要花比較久的時間,可以趁此時休息一會兒。
# cd /usr/ports/databases/mysql40-server;make install clean

安裝完後,如果是第一次安裝的話,請執行以下指令來建立儲存 MySQL 基本資料的資料庫
# /usr/local/bin/mysql_install_db

改變 MySQL 相關目錄檔案之存取權限
# chown -R mysql:mysql /usr/local/share/mysql ##參數 -R 指說該將目錄下所有的檔案/目錄 owner 改為一樣的
# chown -R mysql:mysql /usr/local/mysql
# chmod -R 755 /usr/local/mysql
# chmod 744 /usr/local/share/mysql/mysql.server
# chmod 750 /usr/local/etc/rc.d/mysql-server.sh


啟動 mysql
# /usr/local/share/mysql/mysql.server start

登入資料庫,如果是第一次登入的話,請直接執行 mysql ,無需密碼。
# mysql

設定 MySQL 的 root 權限,設完後,下次登入 MySQL 請用此指令 mysql -u root -p
mysql> SET PASSWORD FOR root=PASSWORD('MyPassword');

建立新的 MySQL 使用者,帳號 postfix 密碼 secret
mysql> GRANT ALL ON mailbox.* TO postfix@localhost IDENTIFIED BY "secret";

做完以上動作以後,下此指令做即時更新以上新增的資料
mysql> FLUSH PRIVILEGES;

建立新的資料庫,命名為 mailbox
mysql> CREATE DATABASE mailbox;

建立 mailbox 此資料庫之資料表 user 及欄位 ID,username,password,status
mysql> USE mailbox;
CREATE TABLE user (
ID int(10) unsigned NOT NULL auto_increment,
username varchar(128) NOT NULL default '',
password varchar(40) NOT NULL default '',
status tinyint(4) NOT NULL default '1',
PRIMARY KEY (ID),
UNIQUE KEY username (username)
) TYPE=MyISAM;

新增信箱的使用者,在此我們使用 standard Unix DES-based encryption algorithm 的加密演算法來為我們的密碼加密,我們可以使用 PHP 的 function crypt() 來生成我們要加密的密碼
# ee /www/crypt.php
<?php
$MyPassword = "pass";
echo crypt($MyPassword);
?>

如果你手邊沒有 PHP 可用,這兒也提供給你 http://doc.uniorg.net/postfix/crypt.php 來生成加密碼做測試用。

新增帳號 test 密碼 pass, 加密後為 $1$cFT9pmty$ZyZDAy7x0/PJYRKWA8y9f/,我們把它 insert 進資料庫
mysql> INSERT INTO user (username,password) VALUES ('test','$1$cFT9pmty$ZyZDAy7x0/PJYRKWA8y9f/');

在此,我們一同新增另個帳號 cyrus 密碼 pwd,稍候會用此做為 Cyrus-IMAP 的管理員帳號,加密後的密碼為 $1$JjMXx6cp$yN0jNQK8jUZyDbVETVRy5/,同樣的把它 insert 進資料庫。
mysql> INSERT INTO user (username,password) VALUES ('cyrus','$1$YJioMytK$ChI.ZaAehGbKJnbaAsxm11');


安裝與設定 pam_mysql

安裝 pam_mysql
# cd /usr/ports/security/pam-mysql;make install clean
這兒有一些 pam_mysql 文件 /usr/local/share/doc/pam_mysql

建立捷徑
# ln -s /usr/local/lib/pam_mysql.so /usr/lib/pam_mysql.so

設定 pam
※ for FreeBSD 4.x Users Only! (FreeBSD 5.x 的 user 請看後半段)
接著編輯 ee /etc/pam.conf,如果已經有這個檔的話,找到以下兩行,在其前面加上 # 註解起來
# imap auth required pam_unix.so try_first_pass
# pop3 auth required pam_unix.so try_first_pass


# echo smtp auth required pam_mysql.so user=postfix passwd=secret \
host=localhost db=mailbox table=user usercolumn=username \
passwdcolumn=password crypt=1 sqllog=0 >> /etc/pam.conf

# echo smtp account sufficient pam_mysql.so user=postfix passwd=secret \
host=localhost db=mailbox table=user usercolumn=username \
passwdcolumn=password crypt=1 sqllog=0 >> /etc/pam.conf

# echo imap auth required pam_mysql.so user=postfix passwd=secret \
host=localhost db=mailbox table=user usercolumn=username \
passwdcolumn=password crypt=1 sqllog=0 >> /etc/pam.conf

# echo imap account sufficient pam_mysql.so user=postfix passwd=secret \
host=localhost db=mailbox table=user usercolumn=username \
passwdcolumn=password crypt=1 sqllog=0 >> /etc/pam.conf

# echo auth sufficient pam_unix.so >> /etc/pam.conf

# echo account sufficient pam_unix.so >> /etc/pam.conf


※ for FreeBSD 5.x Users Only!
# echo auth required pam_mysql.so user=postfix passwd=secret \
host=localhost db=mailbox table=user usercolumn=username \
passwdcolumn=password crypt=1 sqllog=0 >> /etc/pam.d/smtp

# echo account sufficient pam_mysql.so user=postfix passwd=secret \
host=localhost db=mailbox table=user usercolumn=username \
passwdcolumn=password crypt=1 sqllog=0 >> /etc/pam.d/smtp

# echo auth sufficient pam_unix.so >> /etc/pam.d/smtp

# echo account sufficient pam_unix.so >> /etc/pam.d/smtp

# ln -s /etc/pam.d/smtp /etc/pam.d/imap

方才 pam 的設定,其中
※ crypt=0 表示儲存的密碼為明碼,這對人類而言,是易讀易懂,但是不安全。
※ crypt=1 表示儲存的密碼為經由 UNIX系統中的 DES 所編碼過的密碼,據悉,它這有兩種加密方式;一種為普通的 DES 加密方式,也叫 crypt(),加密後的密碼有 13 位元長,另一種則為使用 MD5 演算法加密的,也叫 md5 crypt(),可說是 DES 的加強版,特點是以 $1$ 為開頭,加密後的密碼長度不定。
※ crypt=2 表示是用 MySQL 內建的函數 password() 所加密的密碼。


安裝 cyrus-sasl2-saslauthd

安裝 cyrus-sasl2-saslauthd 時,會自動一併安裝 cyrus-sasl2
先編輯它的 Makefile
# cd /usr/ports/security/cyrus-sasl2-saslauthd/ ; ee Makefile
在 CONFIGURE_ARGS 這段新增那三個參數
## CONFIGURE_ARGS=
--enable-sql=mysql \
--with-mysql=/usr/local/ \
--with-dblib=none \

開始安裝 Cyrus-sasl2-saslauthd
# make WITH_BDB_VER=41 install clean

設定啟動 FreeBSD 時執行 saslauthd,在 /etc/rc.conf 新增此行 saslauthd_enable="YES"

for FreeBSd 4.x Users 要多下此指令
# ln -s /usr/local/lib/sasl2 /usr/lib/sasl2

請認有無此檔,並且連結到正確路徑
# ls -l /usr/local/lib/sasl2/libsql.so.2
libsql.so.2 -> /usr/local/lib/mysql/libmysqlclient.so.12
如果沒有 libsql.so.2 此檔,或者連到非以上路徑,請下此指令
# ln -s /usr/local/lib/mysql/libmysqlclient.so.12 /usr/local/lib/sasl2/libsql.so.2

啟動 saslauth daemon,注意,saslauthd 必需在 IMAP or POSTFIX 前啟動
# /usr/local/etc/rc.d/saslauthd.sh start

為了要讓 saslauth daemon 支援 PAM,saslauthd 必須隨著 -a pam 參數一同啟動,檢驗看看
# ps ax|grep sasl
10174 ?? Is 0:00.10 /usr/local/sbin/saslauthd -a pam ##後面有 -a pam

每做一個動作後,請查看 log 有無什麼錯誤訊息,用 tail 指令,只會列出最後的幾行
# tail /var/log/maillog
# tail /var/log/messages


用 TLS 來建立 SMTP 和 IMAP 的安全連線

在你設置 TLS 安全連線之前,你必須先建立自己的認證碼 (certificates)。為了要更深入了解 一讀由 O'Reilly 出版,John Viega, Matt Messier, Pravir Chandra 所著作得書 "Network Security with OpenSSL"。但如果你尚抽不出時間的話,你可以用以下的方式來快速的建立你的 CA (Certificate Authority)。
# mkdir /ca
# chown root:wheel /ca
# chmod 0700 /ca
# cd /ca

Create Your Own Certificate Authority
Note: when asked for Common Name (e.g., YOUR name) you have to provide server name, or the request will be useless. Do not enter yours (administrator) name you can create client p12 certificate with openssl pkcs12 -export command

建立你私人的 CA key (請記得你的密碼!):
# openssl genrsa -des3 -out /ca/ca.key 1024
Enter pass phrase for /ca/ca.key: password ##在此輸入你想要的密碼(六碼以上)

Create CA certificate (ca.crt) and sign it with the CA's private key (ca.key)
# openssl req -new -x509 -days 365 -key /ca/ca.key -out /ca/ca.crt
Enter pass phrase for /ca/ca.key: password ##輸入 CA key 的密碼
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----

Country Name (2 letter code) [AU]: TW ##二字母國家代碼
State or Province Name (full name) [Some-State]: Taiwan
Locality Name (eg, city) []: Taipei

Organization Name (eg, company) [Internet Widgits Pty Ltd]: UO ##公司名稱
Organizational Unit Name (eg, section) []: UO
Common Name (eg, YOUR name) []: mydomain.net ##這兒一定要輸入 server name/domain name
Email Address []: mymail@hotmail.com

Create an unsigned certificate (this is for SSL enabling your service)
Create a certificate (server.pem) and a certificate signing request or CSR (req.pem).
# openssl req -new -nodes -out /tmp/req.pem -keyout /ca/server.pem
Country Name (2 letter code) [AU]: TW
State or Province Name (full name) [Some-State]: Taiwan
Locality Name (eg, city) []: Taipei
Organization Name (eg, company) [Internet Widgits Pty Ltd]: UO
Organizational Unit Name (eg, section) []: UO
Common Name (eg, YOUR name) []: mydomain.net
Email Address []: mymail@hotmail.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: password ##輸入個較複雜的密碼,不易被破解的
An optional company name [] ##這可以空著不填

Important:
-nodes option means that your key is sitting unencrypted on your hard disk. That may pose some security risk.

Sign Your Certificate With Your CA's Key
Using your CA's private key (ca.key) and certificate (ca.crt) sign the CSR (req.pem) and create a signed certificate (signed_req.pem)
# cp /tmp/req.pem /ca
# openssl x509 -req -CA /ca/ca.crt -CAkey /ca/ca.key -days 365 -in req.pem -out signed_req.pem -CAcreateserial

Concatenate the signed request with certificate to produce a certificate that can be loaded into your web/mail server
# cat signed_req.pem >> /ca/server.pem

View the fingerprint of a certificate
# cp /usr/src/crypto/openssl/apps/cert.pem /ca
# openssl x509 -subject -dates -fingerprint -in cert.pem

The short can look as follows:
# openssl req -new -nodes -out req.pem -keyout key.pem
Country Name (2 letter code) [AU]: TW
State or Province Name (full name) [Some-State]: Taiwan
Locality Name (eg, city) []: Taipei
Organization Name (eg, company) [Internet Widgits Pty Ltd]: UO
Organizational Unit Name (eg, section) []: UO
Common Name (eg, YOUR name) []: mydomain.net
Email Address []: mymail@hotmail.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: password ##輸入個較複雜的密碼,不易被破解的
An optional company name [] ##這可以空著不填

# openssl rsa -in key.pem -out server.pem
# openssl x509 -in req.pem -out ca-cert -req -signkey server.pem -days 999
# cat ca-cert >> server.pem


安裝與設定 cyrus-imap

安裝任何版本的 cyrus 時,預設會自動安裝 db3,如果你選擇了 db4.x,安裝結果將會是 db3 和 db4.x 皆會安裝於你的系統中。有兩種版本的 Berkeley db 同時存在時,cyrus-sasl 的認證功能將會無法正常使用。基於這個原因,你必須手動的來更改所要使用的 Berkeley db 版本。

這裡我們使用 Berkeley db41:
編輯 cyrus-imapd22 的 Makefile 檔
# cd /usr/ports/mail/cyrus-imapd22;ee Makefile
找到此段
.if defined(WITH_BDB_VER)
USE_BDB_VER= ${WITH_BDB_VER}
.else
USE_BDB_VER= 3
把 USE_BDB_VER= 3 改成 USE_BDB_VER= 41

安裝 Cyrus-IMAP
# cd /usr/ports/mail/cyrus-imapd22 ; make install clean

設定啟動 FreeBSD 執行 imapd,在 /etc/rc.conf 新增此行 cyrus_imapd_enable="YES"

把 postfix 加入 cyrus 群組
# pw groupmod cyrus -m postfix

檢驗 cyrus 群組的使用者有哪些
# pw groupshow cyrus
cyrus:*:60:postfix

建立 cyrus-imapd 所需的目錄
# /usr/local/cyrus/bin/mkimap
# mkdir /var/adm
# touch /var/adm/imapd.log /var/adm/auth.log

# touch /var/imap/annotations.db ; chown cyrus:cyrus /var/imap/annotations.db
# chmod 750 /var/imap
# chmod 750 /var/spool/imap

啟動 cyrus-imap
# /usr/local/etc/rc.d/imapd.sh start

每做一個動作後,請查看 log 有無什麼錯誤訊息,用 tail 指令,只會列出最後的幾行
# tail /var/log/maillog
# tail /var/log/messages

測試 cyrus-imap 是否能正常運作
# telnet localhost imap
Trying ::1...
Connected to localhost.
Escape character is '^]'.
* OK examples.net Cyrus IMAP4 v2.2.8 server ready ##此行一定要有

. logout##要登出請輸入 . logout,[點 . 後面有空白]
如有看到類似以上的訊息,恭喜你,你的 cyrus-imap 正常運作中

每做一個動作後,請查看 log 有無什麼錯誤訊息,用 tail 指令,只會列出最後的幾行
# tail /var/log/maillog
# tail /var/log/messages

建立使用者信箱所需之目錄
# mkdir /var/imap/user
# cd /var/imap/user
# mkdir a b c d e f g h i j k l m n o p q r s t u v w x y z
# chown -R cyrus:cyrus /var/imap/user

設定 cyrus-imap,編輯 imapd.conf
# ee /usr/local/etc/imapd.conf
configdirectory: /var/imap
partition-default: /var/spool/imap
##是否允許匿名登入;認證後才登入是個好主意,請把它設為 no
allowanonymouslogin: no
##是否允許使用明碼;安全因素考量,用加密過後的比較妥,請把它設為 no,不知為何 Cyrus-Imapd 2.2.8 把這設為 no 會有錯誤,所以先把它 # 註解起來
#allowplaintext: no
##限定的信箱容量達多少百分比 (%) 時,系統發出警告
quotawarn: 90
##設置 cyrus server 的管理員為 cyrus
admins: cyrus
##預設的信箱容量 (kilobytes)
autocreatequota: 10000
singleinstancestore: yes
duplicatesuppression: yes
##設為 no 才不會把不是 8-bit 的 characters 給 reject 掉
reject8bit: no
##每封 mail 大小的最大值 (bytes)
maxmessagesize: 7000
sieveusehomedir: false
sievedir: /var/imap/sieve
sasl_minimum_layer: 0
sasl_pwcheck_method: saslauthd
#sasl_auto_transition: no
##此選項列出允許的 mechanisms/authentication methods
sasl_mech_list: plain login cram-md5 digest-md5
tls_cert_file: /var/imap/server.pem
tls_key_file: /var/imap/server.pem
tls_ca_file: /usr/local/etc/postfix/server.pem
lmtp_over_quota_perm_failure: no
lmtp_allowplaintext: no
#tls_cipher_list: TLSv1:SSLv3:!DES:!HIGH:@STRENGTH
tls_cipher_list: ALL:!ADH:RC4+RSA:+SSLv2:@STRENGTH

# SQL info 這些設定目前還用不到
#sasl_auxprop_plugin: sql
#sasl_sql_engine: mysql
#sasl_sql_hostnames: localhost
#sasl_sql_user: postfix
#sasl_sql_passwd: secret
#sasl_sql_database: mailbox
#sasl_sql_statement: select password from user where username = '%u'
#sasl_sql_verbose: true

由於 imapd.conf 有設置啟動 TLS 安全連線,所以請複製之前建立好的 certificate (server.pem)
# cp /ca/server.pem /var/imap/server.pem
# chown cyrus:mail /var/imap/server.pem
# chmod 600 /var/imap/server.pem

設定完後,執行以下指令來重新啟動 cyrus-imap
# /usr/local/etc/rc.d/imapd.sh restart

每做一個動作後,請查看 log 有無什麼錯誤訊息,用 tail 指令,只會列出最後的幾行
# tail /var/log/maillog
# tail /var/log/messages

使用 imtest 此工具來測試 Cyrus-IMAP 的認證是否有正常運作,參數 -a 後接使用者名
# imtest -m login -a test -p imap localhost
S: * OK mydomain.net Cyrus IMAP4 v2.2.8 server ready
C: C01 CAPABILITY
S: * CAPABILITY IMAP4 IMAP4rev1 ACL QUOTA LITERAL+ MAILBOX-REFERRALS NAMESPACE UIDPLUS ID NO_ATOMIC_RENAME UNSELECT CHILDREN MULTIAPPEND BINARY SORT THREAD=ORDEREDSUBJECT THREAD=REFERENCES ANNOTATEMORE IDLE STARTTLS
S: C01 OK Completed

Please enter your password: pass ##在此輸入密碼
C: L01 LOGIN star {4}
S: + go ahead
C: <omitted>
S: L01 OK User logged in
Authenticated.
Security strength factor: 0

. logout ##(要登出請輸入 . logout,[點 . 後面有空白])
* BYE LOGOUT received
. OK Completed
Connection closed.


每做一個動作後,請查看 log 有無什麼錯誤訊息,用 tail 指令,只會列出最後的幾行
# tail /var/log/maillog
# tail /var/log/messages

再次測試 Cyrus-IMAP,參數 -a 後接使用者名
# imtest -t "" -a test localhost
S: * OK mydomain.net Cyrus IMAP4 v2.2.8 server ready
C: C01 CAPABILITY
S: * CAPABILITY IMAP4 IMAP4rev1 ACL QUOTA LITERAL+ MAILBOX-REFERRALS NAMESPACE U
IDPLUS ID NO_ATOMIC_RENAME UNSELECT CHILDREN MULTIAPPEND BINARY SORT THREAD=ORDE
REDSUBJECT THREAD=REFERENCES ANNOTATEMORE IDLE STARTTLS
S: C01 OK Completed
C: S01 STARTTLS
S: S01 OK Begin TLS negotiation now
verify error:num=18:self signed certificate
TLS connection established: TLSv1 with cipher AES256-SHA (256/256 bits) ## TLS 安全連線已建立
C: C01 CAPABILITY
S: * CAPABILITY IMAP4 IMAP4rev1 ACL QUOTA LITERAL+ MAILBOX-REFERRALS NAMESPACE U
IDPLUS ID NO_ATOMIC_RENAME UNSELECT CHILDREN MULTIAPPEND BINARY SORT THREAD=ORDE
REDSUBJECT THREAD=REFERENCES ANNOTATEMORE IDLE AUTH=LOGIN AUTH=PLAIN SASL-IR
S: C01 OK Completed
C: A01 AUTHENTICATE LOGIN
S: + VXNlcm5hbWU6

Please enter your password: testpw ##輸入你的密碼
C: c3Rhcg==
S: + UGFzc3dvcmQ6
C: c3Rhcg==
S: A01 OK Success (tls protection) ##在 TLS 安全連線之下成功登入
Authenticated.
Security strength factor: 256 ##這兒應為 256

. logout ##(要登出請輸入 . logout,[點 . 後面有空白])
* BYE LOGOUT received
. OK Completed
Connection closed.


每做一個動作後,請查看 log 有無什麼錯誤訊息,用 tail 指令,只會列出最後的幾行
# tail /var/log/maillog
# tail /var/log/messages

cyradm 是在安裝 Cyrus-IMAP 時一同安裝上的附屬工具,主要功能是建立及管理信箱,我們在此使用 cyradm 此工具來建立使用者信箱
# cyradm localhost --user cyrus ##參數 --user 後面接管理員帳號 (在 imapd.conf 裡設置的 admins: cyrus),如果一直無法登入的話,請使用此指令 cyradm --auth login localhost --user cyrus
IMAP Password: cyrus ##輸入 IMAP 管理員的密碼

使用 cyradm 的指令 cm (Create mailbox) 建立一個叫 test 的信箱
localhost> cm user.test

使用 cyradm 的指令 lm (List mailbox) 列表信箱。
localhost> lm

如果你的 /usr/local/etc/imapd.conf 裡頭有設 autocreatequota: 10000 此參數的話,那麼預設的信箱容量為 10MB,如你想要為這信箱特別設個不同的容量,可以經由使用 cyradm 的指令 setquota 來設置信箱容量。
localhost> setquota user.test 10000

如果想要刪除信箱的話,必須先設定管理員對該 mailbox 有 all 權限
localhost> setaclmailbox user.test cyrus all ##管理員 cyrus 對 信箱 test 有 all 權限

使用 cyradm 的指令 dm (Delete mailbox) 刪除信箱
localhost> dm user.test

查看更多 cyradm 相關指令
localhost> help

登出 cyradm
localhost> quit

建立完信箱以後可以下此指令看到新建的使用者信箱。
# ll /var/spool/imap/user


安裝與設定 postfix

# cd /usr/ports/mail/postfix ; make install clean ; rehash
選擇這些選項
[X] SASL2
[X] TLS
[X] DB41
[X] MySQL

開始安裝中,需要一些時間,可以趁此時休息一下

接著會問個問題,回答 y
Would you like to activate Postfix in /etc/mail/mailer.conf [n]? y

安裝完後的提示訊息,請跟著訊息指示來做
Also, you will want to disable some Sendmail-specific daily maintenance
routines in your /etc/periodic.conf file:
編輯 periodic.conf,並把原有的選項改成下列
# ee /etc/periodic.conf
daily_clean_hoststat_enable="NO"
daily_status_mail_rejects_enable="NO"
daily_status_include_submit_mailq="NO"
daily_submit_queuerun="NO"

安裝完後執行
# /usr/local/sbin/postalias /etc/aliases
# /usr/local/sbin/postmap /usr/local/etc/postfix/transport

設置開機時啟動 postfix,新建一個捷徑
# ln -s /usr/local/sbin/postfix /usr/local/etc/rc.d/postfix.sh

編輯 smtpd.conf
# ee /usr/local/lib/sasl2/smtpd.conf
pwcheck_method: saslauthd
mech_list: plain login cram-md5 digest-md5
## 以下選項還用不到
#log_level: 3
#auxprop_plugin: sql
#sql_engine: mysql
#sql_hostnames: localhost ##"localhost" means that the mysql-libs trys to use a unix-socket. "127.0.0.1" uses inet-sockets.
#sql_user: postfix
#sql_passwd: secret
#sql_database: mailbox
#sql_select: select password from user where username='%u'
#sql_verbose: true


設定 Postfix,它有兩個主要的設定檔 main.cfmaster.cf
編輯 master.cf
# ee /usr/local/etc/postfix/master.cf
ctrl + y 搜尋此字串 /cyrus/bin/deliver 找到後,改為 /usr/local/cyrus/bin/deliver
接著按 ctrl + x 繼續搜尋剛剛的字串,找到後,同樣改為 /usr/local/cyrus/bin/deliver

編輯 main.cf
# ee /usr/local/etc/postfix/main.cf
soft_bounce = no
queue_directory = /var/spool/postfix
command_directory = /usr/local/sbin
daemon_directory = /usr/local/libexec/postfix
mail_owner = postfix
default_privs = nobody
## 本機的 hostname
myhostname = mail.mydomain.net
## 本機的 domain
mydomain = mydomain.net
myorigin = $myhostname
myorigin = $mydomain
##postfix 收信的網卡IP
inet_interfaces = all
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
local_recipient_maps =
unknown_local_recipient_reject_code = 550
relay_domains = $mydestination
mailbox_transport = lmtp:unix:/var/imap/socket/lmtp
luser_relay = $local@other.host
smtpd_banner = $myhostname ESMTP $mail_name
debug_peer_level = 2
debugger_command =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
xxgdb $daemon_directory/$process_name $process_id & sleep 5
sendmail_path = /usr/local/sbin/sendmail
newaliases_path = /usr/local/bin/newaliases
mailq_path = /usr/local/bin/mailq
setgid_group = maildrop
html_directory = no
manpage_directory = /usr/local/man
sample_directory = /usr/local/etc/postfix
readme_directory = no

##設置啟動 SASL 寄件登入認證##
broken_sasl_auth_clients = yes
smtpd_sasl_auth_enable = yes
#smtp_sasl_password_maps = hash:/usr/local/etc/postfix/smtp_sasl_pass
#smtp_sasl_password_maps = mysql:/etc/postfix/mysql_auth.conf
#smtpd_sasl_local_domain = $mydomain
smtpd_sasl_local_domain =

##設置啟動 TLS 安全連線##
##啟用 TLS
smtpd_use_tls = yes
##只有在 user 使用 TLS安全連線時,postfix 才會執行 smtp auth command

smtpd_tls_auth_only = yes
smtpd_tls_loglevel = 3
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 600s
smtpd_tls_cert_file = /usr/local/etc/postfix/server.pem
smtpd_tls_key_file = $smtpd_tls_cert_file
smtpd_tls_dcert_file = /usr/local/etc/postfix/server.pem
smtpd_tls_dkey_file = $smtpd_tls_dcert_file
#smtpd_tls_CApath = /usr/local/etc/postfix
#tls_random_source = dev:/dev/urandom

##檢查寄件人的 email address 與 domain##
smtpd_sender_restrictions = 
	permit_mynetworks
	permit_sasl_authenticated
	reject_non_fqdn_sender
	reject_unknown_sender_domain
	# check_sender_access hash:/usr/local/etc/postfix/access
	# check_client_access hash:/usr/local/etc/postfix/network_table
	# check_relay_domains
	# warn_if_reject

##檢查收件人的 email 與 domain##
smtpd_recipient_restrictions = 
	permit_mynetworks
	permit_sasl_authenticated
	permit_auth_destination
	permit_mx_backup
	check_relay_domains
	reject_unknown_recipient_domain
	reject_non_fqdn_recipient
	reject_unauth_destination
	reject

##檢查SMTP連線來源IP (包括 用戶端Outlook 與 郵件主機Sendmail 等等)##
smtpd_client_restrictions = 
	permit_mynetworks
	permit_sasl_authenticated
	reject_unauth_pipelining
	reject_unknown_client
	# check_client_access hash:/usr/local/etc/postfix/access
	# check_client_access regexp:/usr/local/etc/postfix/access_regexp
	# reject_rbl_client relays.osirusoft.com
	# reject_rbl_client relays.ordb.org
	# check_client_access hash:/usr/local/etc/postfix/network_table
	# check_relay_domains

詳情,請 man smtpd

由於 main.cf 有設置啟動 TLS 安全連線,所以請複製之前建立好的 certificate (server.pem)
# cp /ca/server.pem /usr/local/etc/postfix/server.pem
# chmod 600 /usr/local/etc/postfix/server.pem
# chown cyrus:mail /usr/local/etc/postfix/server.pem

啟動 Postfix
# /usr/local/etc/rc.d/postfix.sh start

每次設完 main.cf, master.cf, smtpd.cf 時都要記得下此指令來重新啟動 postfix
# postfix reload

用此指令列出 Postfix 所支援的 lookup table types,詳請 man postconf
# postconf -m

用此指令列出目前所有在 main.cf available 的設定
# postconf -n

測試 postfix
# telnet localhost 25
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.mydomain.net ESMTP Postfix

ehlo mydomain.net ##輸入此指令
250-mail.mydomain.net
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS ##確定有無此行,表示 TLS 運作中
250-AUTH PLAIN LOGIN DIGEST-MD5 CRAM-MD5 ##列出允許的 mechanisms/authentication methods
250-AUTH=PLAIN LOGIN DIGEST-MD5 CRAM-MD5 ##如果 smtpd_tls_auth_only = yes 有設的話,這兩行 250-AUTH PLAIN.... 會不見
250 8BITMIME ##接著,底下我們嘗試在本機寄信
mail from:test@mail.mydomain.net ## mail from:寄件人
250 Ok
rcpt to:others@hotmail.com ## rcpt to:收件人
250 Ok
data ##輸入此指令,代表要開始寫 mail 的內容
354 End data with <CR><LF>.<CR><LF>
hi,,this is a test mail ##這裡是 mail 的內容
. ##輸入一個點,表示結束書寫這封 mail,並傳出 mail
250 Ok: queued as 141B3115D7
quit ##登出
221 Bye


查看 log 記錄
# cat /var/log/maillog
postfix/smtp to=<others@hotmail.com>, relay=mx3.hotmail.com, delay=14, status=sent ## status=sent;成功寄出

檢查看有哪些 Mail 沒有 sent 出去
# mailq
Mail queue is empty ## empty 沒有待發郵件。如不是看到此訊息,可稍等一下,有時會 delay 一下

刪除傳不出去的 Mail by Queue_ID
# postsuper -d Queue_ID

也可以一次全部刪除傳不出去的 mail
# postsuper -d ALL


使用 Expect + script + PHP 完成信箱的建立 使用 expect 來實現自動化建立信箱,expect 是用 script 來跟其它的 interactive programs 溝通用的軟體 expect 相關資源

安裝 expect
# cd /usr/ports/lang/expect/
# make install clean

寫個 script 來和 PHP 搭配建立信箱
# ee /tmp/shCyradm.sh
script 內容如下
#!/usr/local/bin/expect
spawn cyradm localhost --user [lindex $argv 0]
set adminpass [lindex $argv 1]
set adduser [lindex $argv 2]
expect "adminpass:"
send "$adminpass\r"
send "cm user.$adduser\r"
send "lm\r"
send "quit\r"
expect eof


存檔後離開,並執行 shCyradm.sh (執行後請稍過幾秒鐘不要動它,expect 會自動為我們輸入)
# /tmp/shCyradm.sh cyrus pwd username ##參數說明,參數 1. cyrus 為我們之前在 imapd.conf 設定的 admins: cyrus 為管理員 參數 2. pwd 是我們之前為 cyrus 建立在 MySQL 裡頭的密碼 參數 3. username 是想要建立的信箱帳號
spawn cyradm localhost --user cyrus
IMAP Password:
localhost> cm user.imlala
localhost> lm
user.username (\HasNoChildren)
##可以看到信箱已建立
更詳細的用法,請 man expect

PHP 搭配 expect 自動建立信箱的簡單範例
<?php
if ($_POST['action']=="ok" && $_POST['adduser']!=""){
echo "Start creating mailbox for $_POST[adduser] , please wait...";
##底下這行的 /www/test/postfix/shCyradm.sh 請改為你的 shCyradm.sh 所在路徑,
## 第一個參數 cyrus 為管理員,第二個參數 pwd 為密碼,log_cyradm.txt 可查看訊息記錄
$cmd = "/www/test/postfix/shCyradm.sh cyrus pwd $_POST[adduser] >> log_cyradm.txt";
exec($cmd);
echo "Done...<br>";
echo "<a href=\"creatembox.php\">返回</a>";
exit;
}
?>
<HTML>
<BODY>
<form action="creatembox.php" method="POST">
建立信箱需等待約十秒
輸入欲建立信箱之帳號: <input type="text" NAME="adduser">
<input type="hidden" name="action" value="ok">
<input type="submit">
</form>
</BODY>
</HTML>


資源

官網網址/文件
Postfix 官網文件
Cyrus-SASL and Cyrus-IMAP
MySQL

相關 Howto
For FreeBSD User 的 Howto,cdr 寫得 Howto,寫得不錯,作者也蠻親切的,小弟有部分 Howto 也是跟著這的
Howto install postfix-cyrus-openldap-sa-amavisd with enabled SSL/TLS ver 2
For FreeBSD User 的 Howto,有不錯的參考價值,其中的解釋讓小弟認知不少
Postfix + Cyrus-SASL + Cyrus-IMAPD + PgSQL HOWTO
For FreeBSD User 的 Howto,教你一步一步怎麼做
安裝 postfix 傻瓜篇
For FreeBSD User 的 Howto
Postfix-Cyrus-MySQL-replex-SquirrelMail
For Linux User 的 Howto,有不錯的參考價值,其中的解釋讓小弟認知不少
Postfix + Cyrus-IMAP + Cyrus-SASL + MySQL + IMP 完全指南
For Linux User 的 Howto,還有特別介紹 Web-Cyradm
Postfix-Cyrus-Web-cyradm-HOWTO
For Linux User 的 Howto,英文
Postfix SMTP AUTH (and TLS) HOWTO
For Debian User 的 Howto,有不錯的參考價值,其中的解釋讓小弟認知不少
Tutorial: ISP-style Email Service with Debian-Sarge and Postfix (2.x)

討論文章
不錯的討論文
www.bsdforum.org
www.bsdforum.org

有關 expect 的網站
expect 官網
ftp下載
怎在一個 shell script 中或在背景執行 'ftp'、'telnet'等程序呢?
expect 範例教學

其它尚未歸類
IMAP transfers from one mailbox to another