朝伟 的个人资料我的神韵天堂照片日志 工具 帮助

日志


2008/3/8

架构基于FreeBSD和Postfix的邮件系统

出处 作者:杨廷勇

本文介绍使用FreeBSD+Postfix+cyrus-sasl+Courier-imap+igenus+Clamav+amavisd-new来架构一个具有多域名,有webmai防病毒
和垃圾邮件并有web管理界面的邮件系统。
scyzxp, $Revision: 0.1 $Date: 2005-1-25
________________________________________
Table of Contents
1. 系统简介
1.1 系统结构
1.2 软件介绍
2. 系统安装
2.1 安装perl
2.2 安装MySQL
2.3 安装Apache
2.4 安装PHP
2.5 安装openssl
2.6 安装phpMyAdmin
2.7 通过phpMyadmin设置数据库
2.8 安装cyrus-sasl和cyrus-sasl2-saslauthd
2.9 安装pam_mysql
2.10 安装postfix
2.11 安装expect
2.12 安装Courier-imap
3. 设置第一个用户并测试
3.1 设置第一个用户
3.2 用户登录测试
3.3 建立其他用户
4. 防病毒与防垃圾邮件
4.1 安装Clamav
4.2 安装amavisd-new
4.3 安装配置Spamassassin
5. 安装webmail
6. 邮件服务器的管理
6.1 配置apache
6.2 管理程序源代码
6.3 配置文件config.inc.php
6.4 增加域名
6.5 增加用户
6.6 查看系统状态

Chapter 1. 系统简介
本章介绍了系统的组成。
________________________________________
1.1 系统结构
________________________________________
1.2 软件介绍
________________________________________
Chapter 2. 系统安装
安装之前:因用户数据都保存在/var目录下,因此安装FreeBSD时/var的空间应尽量大。FreeBSD的版本为4.9,按最小化安装,软件包只安装cvsup,安装结束后用cvsup更新ports树。在文档中假设服务器的ip地址为192.168.204.38,域名为test.com,主机名为mail.test.com。
________________________________________
2.1 安装perl
版本为5.8.5,FreeBSD缺省安装的perl版本无法支持目前的amavisd-new。
mail# cd /usr/ports/lang/perl5.8
mail# make install clean
让新版本的perl成为系统的缺省
mail# /usr/local/bin/use.perl port
________________________________________
2.2 安装MySQL
版本为4.0.20,因目前的pam_mysql版本不支持4.1所以安装MySQL40。
mail# cd /usr/ports/databases/mysql40-server
mail# make install clean
________________________________________
2.3 安装Apache
版本为1.3.31_4。
mail# cd /usr/ports/www/apache2
mail# make install clean
编辑/etc/rc.conf,加入
Apache2_enable="YES"
________________________________________
2.4 安装PHP
版本为4.3.10。
mail# cd /usr/ports/lang/php4
mail# make install clean
安装需要的PHP扩展模块
mail# cd /usr/ports/lang/php4-extensions
mail# make install clean
注:gettext需选中
________________________________________
2.5 安装openssl
mail# cd /usr/ports/security/openssl
mail# make install clean
________________________________________
2.6 安装phpMyAdmin
mail# cd /usr/ports/databases/phpmyadmin
mail# make install clean
编辑/usr/local/etc/apache/httpd.conf,加入
Alias /phpMyAdmin/ "/usr/local/www/phpMyAdmin/"
Options Indexes FollowSymlinks
Allowoverride AuthConfig
Order allow,deny
Allow from all
</DIRECTORY />
编辑编辑/usr/local/www/phpMyAdmin/.htaccess
authname "MySQL Admin"
authtype basic
authuserfile /etc/htpasswd
require user admin
运行以下命令生成可访问phpMyadmin的用户:
mail# /usr/local/bin/htpasswd -c /etc/htpasswd admin
修改/usr/local/www/phpMyAdmin/config.inc.php
$cfg['PmaAbsoluteUri'] = 'http://192.168.9.33/phpMyAdmin/';
重启服务器
在浏览器输入http://192.168. 9.33/phpMyAdmin/,修改mysql数据库里user表里的root用户的密码为admin123。
重启MySQL,再编辑/usr/local/www/phpMyAdmin/config.inc.php
$cfg['Servers'][$i]['password'] = 'admin123';
________________________________________
2.7 通过phpMyadmin设置数据库
建立两个数据库用户
#======================postfix==================================
INSERT INTO user (host,user,password) VALUES('localhost','postfix','');
update user set password=password('admin123') where User='postfix';
FLUSH PRIVILEGES;
GRANT ALL ON mail.* TO postfix@localhost IDENTIFIED BY "admin123";
#======================courier==================================
INSERT INTO user (host,user,password) VALUES ('localhost','courier','');
update user set password=password('admin123') where User='courier';
FLUSH PRIVILEGES;
GRANT select,insert,update on mail.* TO courier;
建立数据库
#=======================MAIL.SQL=================================
#Create mail database
CREATE DATABASE mail;
use mail;
#Create the aliases table
CREATE TABLE aliases (
alias varchar(255) NOT NULL default '',
rcpt varchar(255) default NULL,
PRIMARY KEY (alias)
) TYPE=MyISAM;
#Create the transport table
CREATE TABLE transport (
domain char(128) NOT NULL default '',
transport char(128) NOT NULL default '',
UNIQUE KEY domain (domain)
) TYPE=MyISAM;
#Create the virtua_users table
CREATE TABLE virtual_users (
unique_id int(32) unsigned NOT NULL auto_increment,
id char(128) NOT NULL default '',
password char(128) default NULL,
uid int(10) unsigned default '125',
gid int(10) unsigned default '125',
home char(255) default NULL,
maildir char(255) default NULL,
date_add date default NULL,
time_add time default NULL,
domain char(128) default NULL,
name char(255) default NULL,
imapok tinyint(3) unsigned default '1',
###缺省邮箱大小20M
quota char(255) default '20971520',
nickname varchar(10) default NULL,
realname varchar(10) default NULL,
office varchar(20) default NULL,
PRIMARY KEY (id),
KEY unique_id (unique_id)
) TYPE=MyISAM;
________________________________________
2.8 安装cyrus-sasl和cyrus-sasl2-saslauthd
mail# cd /usr/ports/security/cyrus-sasl2-saslauthd
mail# make install clean
编辑/etc/rc.conf,加入
saslauthd_enable="YES"
建立一个目录连接
mail# ln -s /usr/local/lib/sasl2 /usr/lib/sasl2
配置sasl的lib库:在/etc/defaults/rc.conf文件里的ldconfig_paths="/usr/local/lib后面加上/usr/local/lib/sasl2"
运行:
mail# echo pwcheck_method:saslauthd > /usr/lib/sasl2/smtpd.conf
编辑/usr/local/etc/rc.d/saslauthd.sh
command="$/sbin/$"
改成:
command="$/sbin/$ -r"
重启服务器
________________________________________
2.9 安装pam_mysql
mail# cd /usr/ports/security/pam-mysql
mail# make install clean
mail# cp /usr/local/lib/pam_mysql.so /usr/lib/
配置pam.conf调用mysql支持sasl认证。编辑/etc/pam.conf(将pop3 和imap的前面加上#)添加下列代码:
smtp auth sufficient pam_mysql.so user=postfix passwd=admin123 host=localhost db=mail table=virtual_users usercolumn=id passwdcolumn=password crypt=1
注:以上为一行。
smtp account required pam_mysql.so user=postfix passwd=admin123 host=localhost db=mail table=virtual_users usercolumn=id passwdcolumn=password crypt=1
注:以上为一行。
注:用tab键分隔,不是用空格。密码使用crypt加密,如果使用明文密码cyrpt=0,如果
使用password()加密crypt=2
________________________________________
2.10 安装postfix
停止sendmail
mail# killall sendmail
mail# mv /usr/bin/newaliases /usr/bin/newaliases.OFF
mail# mv /usr/bin/mailq /usr/bin/mailq.OFF
mail# mv /usr/sbin/sendmail /usr/sbin/sendmail.OFF
mail# mv /etc/rc.sendmail /etc/sendmail.OFF
开始安装postfix
mail# cd /usr/ports/mail/postfix
mail# make install clean
安装中选中SASL2、MySQL,及回答以下的问题。
You need user "postfix" added to group "mail".
Would you like me to add it [y]? y
Would you like to activate Postfix in /etc/mail/mailer.conf [n]? n
安装完进行一些设置:
mail# cd /usr/local/etc/rc.d
mail# ln -s /usr/local/sbin/postfix postfix.sh
mail# ln -s /usr/local/sbin/sendmail /usr/sbin/sendmail
mail# echo ‘postfix: root’ >> /etc/aliases
mail# /usr/local/bin/newaliases
mail# chown postfix:postfix /etc/opiekeys
编辑/etc/rc.conf
sendmail_enable="YES"
sendmail_flags="-bd"
sendmail_outbound_enable="NO"
sendmail_submit_enable="NO"
sendmail_msp_queue_enable="NO"
编辑//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/etc/postfix/main.cf,在文件最后加入以下内容
#======= BASE ==============
myhostname = mail.test.com
mydomain = test.com
home_mailbox = Maildir/
mydestination = $myhostname, $mydomain, $transport_maps
local_recipient_maps =
mailbox_command= /usr/local/bin/deliverquota -w 90 ~/Maildir
command_directory = /usr/local/sbin
#======= MYSQL =============
transport_maps = mysql:/usr/local/etc/postfix/transport.cf
virtual_gid_maps = mysql:/usr/local/etc/postfix/gids.cf
virtual_mailbox_base = /var/mail
virtual_mailbox_maps = mysql:/usr/local/etc/postfix/mysql_virtual.cf
virtual_maps = mysql:/usr/local/etc/postfix/mysql.aliases.cf
virtual_uid_maps = mysql:/usr/local/etc/postfix/uids.cf
#======= Quota ============
message_size_limit = 4194304 //限制每次发邮件的大小4MB
virtual_mailbox_limit_inbox = no
virtual_mailbox_limit_maps = mysql:/usr/local/etc/postfix/mailboxsize-mysql.cf
virtual_mailbox_limit_override = yes
virtual_maildir_extended = yes
virtual_create_maildirsize = yes
virtual_mailbox_limit = 20971520 //总邮箱的大小20MB
#====== SASL ================
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
broken_sasl_auth_clients = yes
smtpd_recipient_restrictions = permit_sasl_authenticated permit_auth_destination reject
#smtpd_sasl_local_domain = $mydomain
smtpd_client_restrictions = permit_sasl_authenticated
确认/usr/local/etc/postfix/master.cf的配置有如下内容
virtual unix - n n - - virtual
编辑/usr/local/etc/posftix/transport.cf
user = postfix
password = admin123
dbname = mail
table = transport
select_field = transport
where_field = domain
hosts = localhost
编辑/usr/local/etc/postfix/gids.cf
user = postfix
password= admin123
dbname = mail
table = virtual_users
select_field = gid
where_field = id
hosts = localhost
编辑/usr/local/etc/postfix/uids.cf
user = postfix
password= admin123
dbname = mail
table = virtual_users
select_field = uid
where_field = id
hosts = localhost
编辑/usr/local/etc/posftix/mysql_virtual.cf
user = postfix
password= admin123
dbname = mail
table = virtual_users
select_field = maildir
where_field = id
hosts = localhost
编辑/usr/local/etc/postfix/mysql.aliases.cf
user = postfix
password= admin123
dbname = mail
table = aliases
select_field = rcpt
where_field = alias
hosts = localhost
编辑/etc/postfix/mailboxsize-mysql.cf
user = postfix
password = admin123
dbname = mail
table = virtual_users
select_field = quota
where_field = id
hosts = localhost
________________________________________
2.11 安装expect
mail# cd /usr/ports/lang/expect
mail# make install clean
________________________________________
2.12 安装Courier-imap
由于courier-imap 从 4版本开始,把 courier-authlib 独立出来了,需要先安装 courier-authlib. 具体步骤:
mail# cd courier-authlib
mail# make WITH_MYSQL=yes
mail# make install
mail# cd /usr/ports/mail/courier-imap
mail# make WITHOUT_OPENSSL= yes WITH_MYSQL= yes install clean
mail# cd /usr/local/etc/rc.d
mail# mv courier-imap-imapd-ssl.sh.sample courier-imap-imapd-ssl.sh
mail# mv courier-imap-imapd.sh.sample courier-imap-imapd.sh
mail# mv courier-imap-pop3d-ssl.sh.sample courier-imap-pop3d-ssl.sh
mail# mv courier-imap-pop3d.sh.sample courier-imap-pop3d.sh
mail# cd /usr/local/etc/authlih
mail# cd /usr/local/etc/courier-imap
mail# cp authdaemonrc.dist authdaemonrc
mail# cp authmysqlrc.dist authmysqlrc
mail# cd /usr/local/etc/courier-imap
mail# cp imapd-ssl.dist imapd-ssl
mail# cp imapd.cnf.dist imapd.cnf
mail# cp imapd.dist imapd
mail# cp pop3d-ssl.dist pop3d-ssl
mail# cp pop3d.cnf.dist pop3d.cnf
mail# cp pop3d.dist pop3d
编辑修改/usr/local/etc/courier-imap/authmysqlrc 示例:authmysqlrc
##VERSION: $Id: install.sgml,v 1.1 2004/11/01 14:47:56 wt Exp $
#
# Copyright 2000-2004 Double Precision, Inc. See COPYING for
# distribution information.
#
# Do not alter lines that begin with ##, they are used when upgrading
# this configuration.
#
# authmysqlrc created from authmysqlrc.dist by sysconftool
#
# DO NOT INSTALL THIS FILE with world read permissions. This file
# might contain the MySQL admin password!
#
# Each line in this file must follow the following format:
#
# field[spaces|tabs]value
#
# That is, the name of the field, followed by spaces or tabs, followed by
# field value. Trailing spaces are prohibited.
##NAME: LOCATION:0
#
# The server name, userid, and password used to log in.
MYSQL_SERVER localhost
MYSQL_USERNAME courier
MYSQL_PASSWORD admin123
##NAME: MYSQL_SOCKET:0
#
# MYSQL_SOCKET can be used with MySQL version 3.22 or later, it specifies the
# filesystem pipe used for the connection
#
# MYSQL_SOCKET /var/mysql/mysql.sock
##NAME: MYSQL_PORT:0
#
# MYSQL_PORT can be used with MySQL version 3.22 or later to specify a port to
# connect to.
MYSQL_PORT 3306
##NAME: MYSQL_OPT:0
#
# Leave MYSQL_OPT as 0, unless you know what you're doing.
MYSQL_OPT 0
##NAME: MYSQL_DATABASE:0
#
# The name of the MySQL database we will open:
MYSQL_DATABASE mail
##NAME: MYSQL_USER_TABLE:0
#
# The name of the table containing your user data. See README.authmysqlrc
# for the required fields in this table.
MYSQL_USER_TABLE virtual_users
##NAME: MYSQL_CRYPT_PWFIELD:0
#
# Either MYSQL_CRYPT_PWFIELD or MYSQL_CLEAR_PWFIELD must be defined. Both
# are OK too. crypted passwords go into MYSQL_CRYPT_PWFIELD, cleartext
# passwords go into MYSQL_CLEAR_PWFIELD. Cleartext passwords allow
# CRAM-MD5 authentication to be implemented.
MYSQL_CRYPT_PWFIELD password
##NAME: MYSQL_CLEAR_PWFIELD:0
#
#
# MYSQL_CLEAR_PWFIELD clear
##NAME: MYSQL_DEFAULT_DOMAIN:0
#
# If DEFAULT_DOMAIN is defined, and someone tries to log in as 'user',
# we will look up 'user@DEFAULT_DOMAIN' instead.
#
#
# DEFAULT_DOMAIN example.com
##NAME: MYSQL_UID_FIELD:0
#
# Other fields in the mysql table:
#
# MYSQL_UID_FIELD - contains the numerical userid of the account
#
MYSQL_UID_FIELD uid
##NAME: MYSQL_GID_FIELD:0
#
# Numerical groupid of the account
MYSQL_GID_FIELD gid
##NAME: MYSQL_LOGIN_FIELD:0
#
# The login id, default is id. Basically the query is:
#
# SELECT MYSQL_UID_FIELD, MYSQL_GID_FIELD, ... WHERE id='loginid'
#
MYSQL_LOGIN_FIELD id
##NAME: MYSQL_HOME_FIELD:0
#
MYSQL_HOME_FIELD home
##NAME: MYSQL_NAME_FIELD:0
#
# The user's name (optional)
MYSQL_NAME_FIELD name
##NAME: MYSQL_MAILDIR_FIELD:0
#
# This is an optional field, and can be used to specify an arbitrary
# location of the maildir for the account, which normally defaults to
# $HOME/Maildir (where $HOME is read from MYSQL_HOME_FIELD).
#
# You still need to provide a MYSQL_HOME_FIELD, even if you uncomment this
# out.
#
MYSQL_MAILDIR_FIELD maildir
##NAME: MYSQL_DEFAULTDELIVERY:0
#
# Courier mail server only: optional field specifies custom mail delivery
# instructions for this account (if defined) -- essentially overrides
# DEFAULTDELIVERY from $/courierd
#
# MYSQL_DEFAULTDELIVERY defaultdelivery
##NAME: MYSQL_QUOTA_FIELD:0
#
# Define MYSQL_QUOTA_FIELD to be the name of the field that can optionally
# specify a maildir quota. See README.maildirquota for more information
#
MYSQL_QUOTA_FIELD quota
##NAME: MYSQL_AUXOPTIONS:0
#
# Auxiliary options. The MYSQL_AUXOPTIONS field should be a char field that
# contains a single string consisting of comma-separated "ATTRIBUTE=NAME"
# pairs. These names are additional attributes that define various per-account
# "options", as given in INSTALL's description of the "Account OPTIONS"
# setting.
#
# MYSQL_AUXOPTIONS_FIELD auxoptions
#
# You might want to try something like this, if you'd like to use a bunch
# of individual fields, instead of a single text blob:
#
# MYSQL_AUXOPTIONS_FIELD CONCAT("disableimap=",disableimap,",
#disablepop3=",disablepop3,",di
#sablewebmail=",disablewebmail,",sharedgroup=",sharedgroup)
#
# This will let you define fields called "disableimap", etc, with the end result
# being something that the OPTIONS parser understands.
##NAME: MYSQL_WHERE_CLAUSE:0
#
# This is optional, MYSQL_WHERE_CLAUSE can be basically set to an arbitrary
# fixed string that is appended to the WHERE clause of our query
#
# MYSQL_WHERE_CLAUSE server='mailhost.example.com'
##NAME: MYSQL_SELECT_CLAUSE:0
#
# (EXPERIMENTAL)
# This is optional, MYSQL_SELECT_CLAUSE can be set when you have a database,
# which is structuraly different from proposed. The fixed string will
# be used to do a SELECT operation on database, which should return fields
# in order specified bellow:
#
# username, cryptpw, clearpw, uid, gid, home, maildir, quota, fullname, options
#
# The username field should include the domain (see example below).
#
# Enabling this option causes ignorance of any other field-related
# options, excluding default domain.
#
# There are two variables, which you can use. Substitution will be made
# for them, so you can put entered username (local part) and domain name
# in the right place of your query. These variables are:
# $(local_part), $(domain), $(service)
#
# If a $(domain) is empty (not given by the remote user) the default domain
# name is used in its place.
#
# $(service) will expand out to the service being authenticated: imap, imaps,
# pop3 or pop3s. Courier mail server only: service will also expand out to
# "courier", when searching for local mail account's location. In this case,
# if the "maildir" field is not empty it will be used in place of
# DEFAULTDELIVERY. Courier mail server will also use esmtp when doing
# authenticated ESMTP.
#
# This example is a little bit modified adaptation of vmail-sql
# database scheme:
#
# MYSQL_SELECT_CLAUSE SELECT CONCAT(popbox.local_part, '@', popbox.domain_name),
\
# CONCAT('', popbox.password_hash), \
# popbox.clearpw, \
# domain.uid, \
# domain.gid, \
# CONCAT(domain.path, '/', popbox.mbox_name), \
# '', \
# domain.quota, \
# '', \
# CONCAT("disableimap=",disableimap,",disablepop3=", \
# disablepop3,",disablewebmail=",disablewebmail, \
# ",sharedgroup=",sharedgroup) \
# FROM popbox, domain \
# WHERE popbox.local_part = '$(local_part)' \
# AND popbox.domain_name = '$(domain)' \
# AND popbox.domain_name = domain.domain_name
##NAME: MYSQL_ENUMERATE_CLAUSE:0
#
#
# Optional custom SQL query used to enumerate accounts for authenumerate,
# in order to compile a list of accounts for shared folders. The query
# should return the following fields: name, uid, gid, homedir, maildir
#
# Example:
# MYSQL_ENUMERATE_CLAUSE SELECT CONCAT(popbox.local_part, '@',
#popbox.domain_name),
\
# domain.uid, \
# domain.gid, \
# CONCAT(domain.path, '/', popbox.mbox_name), \
# '' \
# FROM popbox, domain \
# WHERE popbox.local_part = '$(local_part)' \
# AND popbox.domain_name = '$(domain)' \
# AND popbox.domain_name = domain.domain_name
##NAME: MYSQL_CHPASS_CLAUSE:0
#
# (EXPERIMENTAL)
# This is optional, MYSQL_CHPASS_CLAUSE can be set when you have a database,
# which is structuraly different from proposed. The fixed string will
# be used to do an UPDATE operation on database. In other words, it is
# used, when changing password.
#
# There are four variables, which you can use. Substitution will be made
# for them, so you can put entered username (local part) and domain name
# in the right place of your query. There variables are:
# $(local_part) , $(domain) , $(newpass) , $(newpass_crypt)
#
# If a $(domain) is empty (not given by the remote user) the default domain
# name is used in its place.
# $(newpass) contains plain password
# $(newpass_crypt) contains its crypted form
#
# MYSQL_CHPASS_CLAUSE UPDATE popbox \
# SET clearpw='$(newpass)', \
# password_hash='$(newpass_crypt)' \
# WHERE local_part='$(local_part)' \
# AND domain_name='$(domain)'
#
重启服务器
________________________________________
Chapter 3. 设置第一个用户并测试
本章介绍如何开通用户,并且测试系统是否正常。
________________________________________
3.1 设置第一个用户
设置第一个用户
mail# mysql
mysql> use mail;
mysql> show tables;
+----------------+
| Tables_in_mail |
+----------------+
| aliases |
| transport |
| virtual_users |
+----------------+
mysql> desc aliases;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| alias | varchar(255) | | PRI | | |
| rcpt | varchar(255) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
mysql> insert aliases values('postmaster@test.com','webmaster@test.com');
mysql> select * from aliases;
+--------------------------+--------------------+
| alias | rcpt |
+--------------------------+--------------------+
| postmaster@test.com | webmaster@test.com |
+--------------------------+--------------------+
mysql> desc transport;
+-----------+-----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-----------+------+-----+---------+-------+
| domain | char(128) | | PRI | | |
| transport | char(128) | | | | |
+-----------+-----------+------+-----+---------+-------+
mysql> insert transport values('test.com','virtual:');
mysql> select * from transport;
+---------------+-----------+
| domain | transport |
+---------------+-----------+
| test.com | virtual: |
+---------------+-----------+
mysql> desc virtual_users;
+-----------+---------------------+------+-----+----------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+----------+----------------+
| unique_id | int(32) unsigned | | MUL | NULL | auto_increment |
| id | char(128) | | PRI | | |
| password | char(128) | YES | | NULL | |
| uid | int(10) unsigned | YES | | 104 | |
| gid | int(10) unsigned | YES | | 104 | |
| home | char(255) | YES | | NULL | |
| maildir | char(255) | YES | | NULL | |
| date_add | date | YES | | NULL | |
| time_add | time | YES | | NULL | |
| domain | char(128) | YES | | NULL | |
| name | char(255) | YES | | NULL | |
| imapok | tinyint(3) unsigned | YES | | 1 | |
| quota | char(255) | YES | | 10485760 | |
+-----------+---------------------+------+-----+----------+----------------+
mysql> INSERT INTO virtual_users
mysql> (id,home,password,maildir,date_add,time_add,domain,name)
mysql> VALUES ('webmaster@test.com','/var/mail/',encrypt('admin123'),
mysql> 'test.com/webmaster/Maildir/','2004-08-08','16:28:24','test.com','webmaster');
mysql> quit
设置用户的目录与权限:
mail# mkdir -p /var/mail/test.com/webmaster
mail# /usr/local/bin/maildirmake /var/mail/test.com/webmaster/Maildir
mail# chmod -R 777 /var/mail/test.com/
mail# chown -R postfix:postfix /var/mail/test.com
至此用户设置完毕,这里只使用一个域名,同理可以设置多个域名。
________________________________________
3.2 用户登录测试
用户登录测试
安装p5-MIME-Base64
mail# cd /usr/ports/converters/p5-MIME-Base64/
mail# make install clean
通过p5-MIME-Base64来取得用户名和密码的base64编码
mail# perl -MMIME::Base64 -e 'print encode_base64("webmaster\@test.com");'
d2VibWFzdGVyQG1za2Uub3Jn
mail# perl -MMIME::Base64 -e 'print encode_base64("admin123");'
bHUwOTIx
发送邮件:
mail# telnet 127.0.0.1 25
Trying 127.0.0.1...
Connected to 0.
Escape character is '^]'.
220 mail.test.com ESMTP Postfix
ehlo mail
250-mail.test.com
250-PIPELINING
250-SIZE 4194304
250-VRFY
250-ETRN
250-AUTH NTLM LOGIN PLAIN OTP
250-AUTH=NTLM LOGIN PLAIN OTP
250 8BITMIME
auth login
334 VXNlcm5hbWU6
d2VibWFzdGVyQG1za2Uub3Jn //此为用户名id:webmaster@test.com
334 UGFzc3dvcmQ6
bHUwOTIx //此为用户密码password:admin123
235 Authentication successful
MAIL FROM:webmaster@test.com //告诉服务器发件人的Email地址
250 Ok
RCPT TO:webmaster@test.com //告诉服务器收件人的地址
250 OK
DATA //告诉服务器开始写信
354 End data with .
SUBJECT:test //subject后面填写的是邮件的主题
test
. //换行后输入.后按回车,表示信件内容书写完毕
250 Ok: queued as 58DC71D5
quit //发送信件,结束对话,退出SMTP服务器
221 Bye
Connection closed by foreign host
收取邮件:
mail# telnet 127.0.0.1 110
Trying 127.0.0.1...
Connected to 0
Escape character is '^]'
+OK Hello there
user webmaster@test.com
+OK Password required
pass admin123
+OK logged in
list
+OK POP3 clients that break here, they violate STD53
1 2217
.
retr 1 //返回第一封信的全部内容
+OK 2217 octets follow.
Return-Path: <webmaster@test.com>
X-Original-To: webmaster@test.com
Delivered-To: webmaster@test.com
Received: from mail (localhost.test.com [127.0.0.1])
by mail.test.com (Postfix) with ESMTP id 58DC71D5
for <webmaster@test.com>; Mon, 9 Aug 2004 21:11:20 +0800 (CST)
SUBJECT:test
Message-Id: <20040809131120.58DC71D5@mail.test.com>
Date: Mon, 9 Aug 2004 21:11:20 +0800 (CST)
From: webmaster@test.com
To: undisclosed-recipients:;
test
.
dele 1 //删除
+OK Deleted
quit
+OK Bye-bye
Connection closed by foreign host
也可以使用任何其它的邮件客户端程序来测试,如foxmail、Outlook Express等等。

2008/2/11

postfix Relay access denied错误的解决方法

发现服务器不能向外域发邮件,日志中有记录如下:

Jan 18 15:20:26 www postfix/smtpd[23419]: NOQUEUE: reject: RCPT from unknown[124.200.70.112]: 554 5.7.1 <wan695@gmail.com>: Relay access denied; from=<from@from.com> to=<to@to.com> proto=ESMTP helo=<[192.168.18.102]>

百思不得其解,放狗也没有找到什么有价值的资源,后来我看到一段注释了的配置

smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination,
reject_unauth_pipelining,
reject_invalid_hostname,
reject_rbl_client cbl.anti-spam.org.cn

这段配置是当时为了搞另外一个反垃圾系统给注释掉的,后来把这个反垃圾系统给去掉了,但是没有把这段配置反注释,于是我的邮件就出问题了,幸好我习惯还比较好,通常都是注释配置文件,要不然一点头绪都找不到.

Postfix Configuration Parameters如是说


smtpd_recipient_restrictions (default: permit_mynetworks, reject_unauth_destination)

The access restrictions that the Postfix SMTP server applies in the context of the RCPT TO command.

By default, the Postfix SMTP server accepts:

IMPORTANT: If you change this parameter setting, you must specify at least one of the following restrictions. Otherwise Postfix will refuse to receive mail:

reject, defer, defer_if_permit, reject_unauth_destination

Specify a list of restrictions, separated by commas and/or whitespace. Continue long lines by starting the next line with whitespace. Restrictions are applied in the order as specified; the first restriction that matches wins.

The following restrictions are specific to the recipient address that is received with the RCPT TO command.

check_recipient_access type:table
Search the specified access(5) database for the resolved RCPT TO address, domain, parent domains, or localpart@, and execute the corresponding action.
check_recipient_mx_access type:table
Search the specified access(5) database for the MX hosts for the RCPT TO address, and execute the corresponding action. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. This feature is available in Postfix 2.1 and later.
check_recipient_ns_access type:table
Search the specified access(5) database for the DNS servers for the RCPT TO address, and execute the corresponding action. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. This feature is available in Postfix 2.1 and later.
permit_auth_destination
Permit the request when one of the following is true:
permit_mx_backup
Permit the request when the local mail system is backup MX for the RCPT TO address, or when the address is an authorized destination (see permit_auth_destination for definition).
  • Safety: permit_mx_backup does not accept addresses that have sender-specified routing information (example: user@elsewhere@domain).
  • Safety: permit_mx_backup can be vulnerable to mis-use when access is not restricted with permit_mx_backup_networks.
  • Safety: as of Postfix version 2.3, permit_mx_backup no longer accepts the address when the local mail system is primary MX for the recipient domain. Exception: permit_mx_backup accepts the address when it specifies an authorized destination (see permit_auth_destination for definition).
  • Limitation: mail may be rejected in case of a temporary DNS lookup problem with Postfix prior to version 2.0.
reject_non_fqdn_recipient
Reject the request when the RCPT TO address is not in fully-qualified domain form, as required by the RFC.
The non_fqdn_reject_code parameter specifies the response code to rejected requests (default: 504).
reject_rhsbl_recipient rbl_domain=d.d.d.d
Reject the request when the RCPT TO domain is listed with the A record "d.d.d.d" under rbl_domain (Postfix version 2.1 and later only). If no "=d.d.d.d" is specified, reject the request when the RCPT TO domain is listed with any A record under rbl_domain.
The maps_rbl_reject_code parameter specifies the response code for rejected requests (default: 554); the default_rbl_reply parameter specifies the default server reply; and the rbl_reply_maps parameter specifies tables with server replies indexed by rbl_domain. This feature is available in Postfix version 2.0 and later.
reject_unauth_destination
Reject the request unless one of the following is true: The relay_domains_reject_code parameter specifies the response code for rejected requests (default: 554).
reject_unknown_recipient_domain
Reject the request when Postfix is not final destination for the recipient address, and the RCPT TO address has no DNS A or MX record, or when it has a malformed MX record such as a record with a zero-length MX hostname (Postfix version 2.3 and later).
The unknown_address_reject_code parameter specifies the response code for rejected requests (default: 450). The response is always 450 in case of a temporary DNS error.
reject_unlisted_recipient (with Postfix version 2.0: check_recipient_maps)
Reject the request when the RCPT TO address is not listed in the list of valid recipients for its domain class. See the smtpd_reject_unlisted_recipient parameter description for details. This feature is available in Postfix 2.1 and later.
reject_unverified_recipient
Reject the request when mail to the RCPT TO address is known to bounce, or when the recipient address destination is not reachable. Address verification information is managed by the verify(8) server; see the ADDRESS_VERIFICATION_README file for details.
The unverified_recipient_reject_code parameter specifies the response when an address is known to bounce (default: 450, change into 550 when you are confident that it is safe to do so). Postfix replies with 450 when an address probe failed due to a temporary problem. This feature is available in Postfix 2.1 and later.

Other restrictions that are valid in this context:

Example:

smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination