本文原址在:
http://www.kowee.com/exim/exim002.html
前些天,写了一篇《Exim简介》,简要介绍了Exim这个MTA软件。应网友的要求,这次将理论与实践相结合,在实际的环境中来配置软件,使Exim、Courier-IMAP和MySQL一起工作。
本文中讲述的邮件系统适合于单台服务器,支持多域名、用户磁盘空间限额、自动回复和别名等功能。
测试进行的环境是RedHat Linux 9.0,Exim的版本是4.20,Courier-IMAP的版本是2.1.2。请注意其中的一些命令只在Linux,甚至RedHat Linux上才适用。
写得比较仓促,其中肯定有不少错误,欢迎大家指正。
在参照本文进行配置之前,您必须掌握如下知识:
1. 知道如何安装操作系统,比如Linux或有安装好的操作系统。
2. 知道如何安装和配置MySQL数据库,如何建立用户、给用户授权。
一、准备工作
1、 下载软件
Exim:http://www.exim.org
Courier:http://www.sourceforge.net/projects/courier
2、 建立目录
建立存放源代码的目录,并要在此目录下进行编译。本文假设此目录为:/tmp/mailinst。
3、 释放源代码
#cd /tmp/mailinst
#tar xzvf exim-4.20.tar.gz
#bunzip2 courier-imap-2.1.2.tar.bz2
#tar xvf courier-imap-2.1.2.tar
二、编译和安装Exim
如果决定要使用Exim作为MTA,必须卸载Sendmail或Postfix。比如,要卸载Sendmail,可用如下命令:
#rpm -e `rpm -qa|grep sendmail`
1、 编译Exim
进入Exim的源代码目录,并作必要的修改。
#cd exim-4.20
#cp src/EDITME Local/Makefile
#touch Local/eximon.conf
在Exim源代码目录的src目录下,有一个Makefile的模板,叫EDITME。只要将此文件复制到Local目录下,并根据需要修改即可。修改的条目如下(//开头的行为注释):
BIN_DIRECTORY=/usr/sbin
//编译后执行文件存放的目录
CONFIGURE_FILE=/etc/exim/exim.conf
//运行时配置文件的名称
EXIM_USER=mail
//运行exim的用户
//上述三项是根据RedHat Linux的习惯进行设置的。
LOOKUP_INCLUDE=-I /usr/include/mysql
LOOKUP_LIBS=-L/usr/lib/mysql -lmysqlclient
去掉下列几行行首的#(//开头的行为注释):
# SUPPORT_MAILDIR=yes
//Courier-IMAP只支持maildir,所以Exim必须支持maildir
# LOOKUP_MYSQL=yes
//能够从mysql中查询数据
# AUTH_CRAM_MD5=yes
# AUTH_PLAINTEXT=yes
//支持SMTP AUTH
Exim有一个工具叫Eximon,是一个基于x-windows的队列监测工具。eximon使用单独的Makefile,但可以为空,所以只要touch一下就可以了。
到Exim的源代码目录下,进行编译:
#make
2、安装Exim
#make install
如果要用Exim作为系统的MTA,执行如下操作:
#ln -sf /usr/sbin/exim /usr/lib/sendmail
#ln -sf /usr/sbin/exim /usr/sbin/sendmail
#ln -sf /usr/sbin/exim /usr/bin/mailq
#ln -sf /usr/sbin/exim /usr/bin/runq
#ln -sf /usr/sbin/exim /usr/bin/rsmtp
#ln -sf /usr/sbin/exim /usr/bin/rmail
#ln -sf /usr/sbin/exim /usr/bin/newaliases
由于本系统采用了RedHat标准的系统启动脚本,所以要编辑/etc/sysconfig/exim文件,内容如下:
DAEMON=yes
QUEUE=1h
复制附件中的exim.init文件到/etc/init.d/exim,改变其属性,并加入到系统启动列表
#cp exim.init /etc/init.d/exim
#chmod +x /etc/init.d/exim
#chkconfig --level 35 exim on
三、编译和安装Courier-IMAP
1、编译Courier-IMAP
进入Courier-IMAP的源代码目录
#cd ../courier-imap-2.1.2
#./configure --prefix=/usr/lib/courier-imap --enable-unicode --enable-workarounds-for-imap-client-bugs --disable-root-check --with-redhat
#make
如果当前操作系统不是RedHat Linux系统,可以省略--with-redhat选项;如果当前用户不是root,可能省略--disable-root-check,反之则必须加上。
2、安装Courier-IMAP
#make install
#make install-configure
将源代码目录中的courier-imap.sysvinit复制为/etc/init.d/courier-imap,改变其属性,并加入系统的启动列表:
#cp courier-imap.sysvinit /etc/init.d/courier-imap
#chmod +x /etc/init.d/courier-imap
#chkconfig --level 35 courier-imap on
四、 设置MySQL
1、建立数据库。
本文中假设数据库名为mailit,MySQL数据库服务器为localhost,连接用户名为mailit,密码也为mailit。
#mysqladmin create mailit
2、建立表结构
#mysql mailit < mailit.sql
mailit.sql定义了三个表,分别为domain、account、address。domain定义了域名,account定义了用户的帐号,address定义了用户的邮件地址和别名地址。
domain表:
+-----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| domname | varchar(255) | | PRI | | |
| isdefault | tinyint(1) | YES | | 0 | |
| ctime | datetime | YES | MUL | NULL | |
+-----------+--------------+------+-----+---------+-------+
domname :域名,如mailit.com
isdefault:是否为默认域名
ctime :建立时间
+-----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| domain | varchar(255) | | MUL | | |
| login | varchar(255) | | PRI | | |
| passwd | varchar(32) | | | | |
| replytext | text | YES | | NULL | |
| forwardto | text | YES | | NULL | |
| qtacount | int(11) | YES | | NULL | |
| qtasize | int(11) | YES | | NULL | |
| status | tinyint(1) | YES | | 1 | |
| ctime | datetime | YES | MUL | NULL | |
+-----------+--------------+------+-----+---------+-------+
domain :用户所在的域
login :登录名
passwd :加密后的密码,格式为原密码的md5值(16进制)的base64编译
replytext:自动回复信息。如果不为空,则产生自动回复。
forwardto:自动转发信息
qtacount :配额,最多邮件个数
atasize :配额,最大磁盘空间
status :帐号状态,1为可用,0为不可用
ctime :建立时间
+---------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| address | varchar(255) | | PRI | | |
| login | varchar(255) | | MUL | | |
| ctime | datetime | YES | MUL | NULL | |
+---------+--------------+------+-----+---------+-------+
address:邮件地址
login :地址所对应的登录名
ctime :建立时间
3、给用户授权
#mysql mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 3.23.41
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>grant select,insert,update,delete on mailit.*
>to mailit@localhost identified by 'mailit';
mysql>flush privileges;
五、配置Exim
1、编辑/etc/exim/exim.mysql,内容如下(附件中有不带注释的版本):
hide mysql_servers = localhost/mailit/mailit/mailit
#
# QUERY
#
# MQ开头的表示SQL语句
# MD开头的表示SQL语句执行后的结果
#
#根据邮件地址取得登录名
MQ_ADDR_TO_LOGIN= SELECT login FROM address WHERE address ='${quote_mysql:$local_part@$domain}'
MD_ADDR_TO_LOGIN= ${lookup mysql{MQ_ADDR_TO_LOGIN}}
#根据登录名取得当前帐号的所有信息
MQ_RCPT_USER_DATA= SELECT * FROM account WHERE login = '${quote_mysql:MD_ADDR_TO_LOGIN}' AND status = 1
MD_RCPT_USER_DATA= ${lookup mysql{MQ_RCPT_USER_DATA}}
#SMTP验证
MQ_AUTH_USER_PASS= SELECT passwd FROM account WHERE login = '${quote_mysql:$1}'
MD_AUTH_USER_PASS= ${lookup mysql{MQ_AUTH_USER_PASS} {$value} fail}
Exim将所有以大写字母打头的定义理解为常量,如MD_ADDR_TO_LOGIN,MyConstant等。$loal_part和$domain为Exim的变量,分别表示一个电子邮件地址@前面和后面的部分。${quote_mysql}是String Expansion操作符,将后面的参数按MySQL的格式进行引用。${lookup mysql}表示执行MySQL查询,并将结果返回在=前面定义的常量中。
2、编辑/etc/exim/exim.conf,内容如下(附件中有不带注释的版本):
#包括exim.mysql文件
.include /etc/exim/exim.mysql
#当前机构的主机名
primary_hostname= mail.mailit.com
#定义一个domainlist:local_domains,此list在后面的很多地方用到
domainlist local_domains= @ : mailit.com : imapit.com : eximit.com
#SMTP协议的RCPT命令的ACL定义
acl_smtp_rcpt = acl_check_rcpt
qualify_domain= mailit.com
host_lookup=
rfc1413_hosts=
ignore_bounce_errors_after = 2d
timeout_frozen_after = 7d
#ACL定义
begin acl
acl_check_rcpt:
accept hosts = :
deny local_parts = ^.*[@%!/|] : ^\\.
accept local_parts = postmaster
domains = +local_domains
require verify = sender
accept domains = +local_domains
endpass
message = unknown user
verify = recipient
accept domains = +relay_to_domains
endpass
message = unrouteable address
verify = recipient
accept hosts = +relay_from_hosts
accept authenticated = *
deny message = relay not permitted
#上面定义的ACL是Exim自带的,详细的说明请参见原始的exim.conf文件。
#定义路由器,注意顺序
begin routers
#系统级帐号
localuser:
driver = accept
check_local_user
transport = local_delivery
#自动回复
gen_auto_reply:
driver = accept
transport = auto_reply
senders = !^.*-request@.* : !^owner-.*@.* : !^postmaster@.* : ! ^listmaster@.* : !^mailer-daemon@.*
condition = ${if eq {${extract {replytext}{MD_RCPT_USER_DATA} }}{} {no}{yes}}
unseen
#本域邮件
mydomain:
driver = accept
domains = +local_domains
transport = mydomain_delivery
#非本域邮件,用DNS来投递
dnslookup:
driver = dnslookup
domains = ! +local_domains
transport = remote_smtp
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
no_more
#投递器
begin transports
#自动回复
auto_reply:
driver = autoreply
from = $local_part@$domain
to = $sender_address
subject = "AR: $h_subject"
text = ${extract {replytext}{MD_RCPT_USER_DATA}}
#系统用户
local_delivery:
driver = appendfile
file = /var/mail/$local_part
delivery_date_add
envelope_to_add
return_path_add
#本域名邮件
mydomain_delivery:
driver = appendfile
create_directory = true
mode = 0700
maildir_format = true
directory = /var/data/mail/${extract {domain}{MD_RCPT_USER_DATA}}/${extract {login}{MD_RCPT_USER_DATA}}/Maildir
quota = ${extract {qtasize}{MD_RCPT_USER_DATA} {$value} {QUOTA_SIZE}}
quota_filecount = ${extract {qtacount}{MD_RCPT_USER_DATA} {$value} {QUOTA_FILE_COUNT}}
#非本域邮件,用smtp transport投递
remote_smtp:
driver = smtp
#重试策略
begin retry
* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
#验证
begin authenticators
plain_login:
driver = plaintext
public_name = LOGIN
server_prompts = Username:: : Password::
server_condition = ${if crypteq {$2} {MD_AUTH_USER_PASS} {yes}{no}}
server_set_id = $1
cram_md5_login:
driver = cram_md5
public_name = CRAM-MD5
server_secret = MD_AUTH_USER_PASS
server_set_id = $1
3、建立存放邮件的目录,并改变权限。请注意/var/data/mail目录的所有者与编译Exim时指定的EXIM_USER是一致的。
#mkdir -p /var/data/mail
#chown -R mail.mail /var/data/mail
4、启动Exim:
#/etc/init.d/exim start
六、配置Courier-IMAP
1、进入Courier-IMAP的配置文件目录:/usr/lib/courier-imap/etc。
2、修改authdaemonrc文件,将authmodulelist的值设为authmysql(去掉其它的值,只留下authmysql)。
3、修改authmysqlrc文件,修改选项如下表(附件中有不带注释的版本):
关键字 值 说明
MYSQL_SERVER localhost MySQL服务器地址
MYSQL_USERNAME mailit 连接MySQL的用户名
MYSQL_PASSWORD mailit 连接MySQL的密码
MYSQL_DATABASE mailit 存放数据的数据库名
MYSQL_USER_TABLE account 存放用户信息的表名
MYSQL_CRYPT_PWFIELD passwd 记录加密后密码的字段名
MYSQL_LOGIN_FIELD login 记录登录名称的字段名
MYSQL_UID_FIELD 8 记录UID的字段。注
MYSQL_GID_FIELD 12 记录GID的字段。注
MYSQL_HOME_FIELD CONCAT('/var/data/mail/', domain, '/', login) AS home 存放用户邮件的目录。注
MYSQL_WHERE_CLAUSE status=1 额外的SQL从句。
上面的MYSQL_UID_FIELD被设置为一个数字8。一般来说,Courier-IMAP要求一个单独的字段来表示用户的UID,但在我们这个配置中,所有的用户都共享同一个UID,所以在表中未设置这样一个字段。但Courier-IMAP又必须此字段,所以用一个数字。这样,在选择的时候,总是返回8。MYSQL_GID_FIELD也是如此。需要注意的是,这两个数字必须与操作系统的mail(或Exim的Makefile中EXIM_USER指定的用户)用户UID、GID一致(要取得某用户的UID和GID,可以用命令id $username,如id mail,会显示: uid=8(mail) gid=12(mail) groups=12(mail))。如果不一致,Courier-IMAP将无法工作,因为用户的邮件目录只有mail用户才能读取。
MYSQL_HOME_FIELD字段是表示存放用户邮件的目录。这里,也没有按照一般的办法来一个单独的字段来存储每个用户的邮件目录,而是采用统一的命名规则:/var/data/mail/域名/用户登录名/。此目录与Exim中的配置必须一致:
directory = /var/data/mail/${extract {domain}{MD_RCPT_USER_DATA}}/${extract {login}{MD_RCPT_USER_DATA}}/Maildir
status=1是额外的SQL从句。根据定义,只有status=1时,用户的状态才是可用的。
4、修改imapd文件,将IMAPDSTART设为YES。
5、修改pop3d文件,将POP3DSTART设为YES。
6、启动Courier-IMAP
#/etc/init.d/courier-imap start
七、测试
#telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.mailit.com ESMTP Exim 4.20 Mon, 13 Oct 2003 02:01:54 +0800
ehlo mailit.com
250-mail.mailit.com Hello mailit.com [127.0.0.1]
250-SIZE 52428800
250-PIPELINING
250-AUTH LOGIN CRAM-MD5
250 HELP
mail from: ok@mailit.com
250 OK
rcpt to: xuezs@mailit.com
r250 Accepted
rcpt to: ok@imapit.com
250 Accepted
data
354 Enter message, ending with "." on a line by itself
Subject: Aha, this is just a test mail.
.
250 OK id=1A8kXu-0000Sg-0v
quit
221 mail.mailit.com closing connection
Connection closed by foreign host.
# telnet localhost 110
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
+OK Hello there.
user xuezs@mailit.com
+OK Password required.
pass test
+OK logged in.
uidl
+OK
1 UID1-1065972142
.
quit
+OK Bye-bye.
Connection closed by foreign host.
八、附件
文件名 说明
cmdlist.txt 整个配置过程的命令列表
exim.conf.txt /etc/exim/exim.conf
Exim主配置文件
exim.mysql.txt /etc/exim/exim.mysql
Exim的MySQL配置文件
exim.init.txt /etc/init.d/exim
系统启动Exim的脚本
mailit.sql 建表脚本,包括示范数据
authmysqlrc.txt
/usr/lib/courier-imap/etc/authmysqlrc
Courier-IMAP的authmysql配置