在sendmail 郵件伺服器中限定用戶郵箱的大小
---- 隨著國際互聯網的不斷普及,電子郵件(E_mail)服務已成為應用最為廣泛的服務之一。目前,在LINUX平台上,sendmail郵件伺服器應用的最普遍。但是因為sendmail本身並不能限定用戶郵箱的大小,所以,如果某些用戶長時間不取信的話,他(她)的信件將在伺服器上不斷堆積,以致其郵箱越來越大,佔用大量的硬碟空間。因此,郵件伺服器的管理員應採取必要的措施,限定用戶郵箱的大小,避免這種情況的發生。這裡介紹一種簡單實用的方法。
---- 一. 基本思路:
---- 先設定用戶郵箱的最大值,然後定期檢查郵箱文件的大小,將所有超過這一上限的郵箱文件名寫進某一特定的文件中;再利用sendmail 的 blacklist_recipients 功能,讀取該文件,從而使郵件伺服器拒收該用戶的新郵件。
---- 二. 運行環境
---- 1. Redhat5.1 或以上
---- 2. Sendmail.8.9.3以上
---- 若無該版本的sendmail 運行軟體,可到freesoft.cei..gov.cn站點下載,按README的提示進行編譯、安裝。
---- 3. Perl5
---- 三.具體方法:
---- 1.重新配置 sendmail.cf文件
---- (如果原有的 sendmail.cf文件已經包含了 blacklist_recipinets 功能,可免此步驟)
---- 假定 sendmail-8.93 的軟體包在/home/sendmail-8.9.3目錄下展開、編譯,並進行預設安裝。
# cd /home/sendmail-8.9.3/cf/domain
# vi linux.m4
在文件的末尾增加:
FEATURE(`access_db'',`hash -o /etc/mail/access'')dnl
FEATURE(`blacklist_recipients'')dnl
# cd ../cf
# m4 ../m4/cf.m4 ./linux.mc > ./sendmail.cf
# cp ./sendmail.cf /etc/
2.生成 access.db 文件
# cd /etc/mail
# makemap hash access < /dev/null
3. 重啟sendmail
# /etc/rc.d/init/sendmail restart
4. 定時執行本文提供的PERL代碼
# limit_mailbox.pl -s
---- 附錄.limit_mailbox.pl 源代碼
#!/usr/bin/perl
#
# limit_mailbox.pl
# Usage:
# limit_mailbox.pl-s
# searching the mailboxes larger than
maxsize such as 5M, then setting
# them full to reject new mails
# limit_mailbox.pl -a
# appending the records into
access.db from the STDIN
# limit_mailbox.pl -r
# removing the records in access.db
according the users'' name input from
# the STDIN
# limit_mailbox.pl -c
# cleaning access.db
# limit_mailbox.pl -p
# printing all the records in access.db to the STDOUT
# settings
$access_dbm="/etc/mail/access.db";
$maildrop="/var/spool/mail";
$maxsize=5*1024*1024; # the maximum size of mailbox
$dbtype="DB_HASH";
# Modules
use Getopt::Std;
use Fcntl;
use DB_File;
use POSIX;
# Variables
undef %db;
# Subroutines
sub opendb_read {
tie(%db,"DB_File",$access_dbm,
O_RDONLY,0,$$dbtype) || die "Can''t open $access_dbm\n";
}
sub opendb_trunc {
tie(%db,"DB_File",$access_dbm,
O_TRUNC,0,$$dbtype) || die "Can''t open $access_dbm\n";
}
sub opendb_write {
tie(%db,"DB_File",$access_dbm,O_RDWR||O
_CREAT,0640,$$dbtype) || die "Can''t open $access_dbm\n";
}
sub adddb {
my $rec=$_[0];
my @list;
($key,@list)=split(/\s+/,$rec);
if ( defined( $db{$key} ) ) {
print "Warning: $rec duplicated, adding failed! \n";
} else {
$db{$key}=join('' '',@list) || die "can''t add record into $access_dbm\n";
}
}
sub removedb {
my $user=$_[0];
if ( defined($db{$user}) ) {
delete $db{$user} && die "Can''t delete
$user in $access_dbm \n";
} else {
print " $user is not existed in $access_dbm \n";
}
}
sub closedb {
untie %db;
}
sub search_box {
chdir($maildrop) || die "Can''t change into $maildrop!\n";
while (< ./* >) {
s?.*/??;
( /^[:|.]/ ) && next;
$mailuser=$_;
$boxsize=(POSIX::stat("./".$mailuser))[7];
( $boxsize >= $maxsize ) && adddb("$mailuser 550 ERROR: this user\''s Mailbox is full");
}
}
# Main Program
getopts(''sarpc'') || die "Usage: limit_mailbox.pl [-s] [-a] [-r] [-p] [-c] \n";
if ($opt_a) {
# append the records from stdin into /etc/mail/access.db
print "Please input the records, ended by cntl-D\n";
opendb_write;
foreach $rec (< STDIN >) {
chop($rec);
adddb $rec;
}
closedb;
} elsif ($opt_r) {
# remove the records in /etc/mail/access.
db according to the STDOUT
print "Please input the removed users , ended by cntl-D\n";
opendb_write;
foreach $rec (< STDIN >) {
chop($rec);
@users=split(/\s+/,$rec);
foreach $user (@users) {
removedb($user);
}
}
closedb;
} elsif ($opt_p) {
# print all the records in /etc/mail/access.db
opendb_read;
while ( ($key,$value)=each(%db) ) {
print "$key\t\t$value\n";
}
} elsif ($opt_c) {
# clean the /etc/mail/access db
opendb_trunc;
closedb;
} elsif ($opt_s) {
# search all the mailbox which are over
Maxsize, then set those boxes full
opendb_write;
# clean db
( defined %emptydb ) && undef %emptydb;
%emptydb;
%db=%emptydb;
# search larger boxes
search_box;
closedb;
} else {
# No options given
die "Usage: limit_mailbox.pl [-s] [-a] [-r] [-p] [-c] \n";
}
exit 0;