Tuesday, 23. January 2007, 01:11:02
qmHandle 是一个Perl程序,用来处理qmail的消息队列。比起 qmail-qread 和 qmail-qstat,qmHandle有更多的特性。
在qmHandle的基础上,作了一个小程序,用来删除包含指定字符串的邮件。
程序如下:
#!/usr/local/bin/perl
use strict;
use vars qw(%Config);
$Config{qmHandle_cmd} = '/var/local/src/qmHandle';
$Config{msg_file} = '/home/ou/qmScript/message_id_list.txt';
$Config{log_file} = '/home/ou/qmScript/log/delete_qmail_msg.' . &get_date() . '.log';
$Config{match_pattern} = '\nTo:\s(.*)\@bad.domain\n';
&main();
sub main()
{
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
&write_log("---------- ". &get_time() . " start delete messages ----------\n");
&analyze_and_delete_msgs();
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
&write_log("---------- ". &get_time() . " end delete messages ----------\n");
}
#-------------------------------------------------------------------
sub analyze_and_delete_msgs()
{
# 执行命令“qmHandle -l -N”结果输出到文件
system("$Config{qmHandle_cmd} -l -N > $Config{msg_file}");
if (-e $Config{msg_file}) {
# 从文件读取消息ID
open (MSG_LIST, $Config{msg_file}) || die "couldn't open $Config{msg_file}!";
while (<MSG_LIST>) {
my ($msg_id, $msg_info) = split(/\s/, $_);
# 根据消息ID分析邮件内容
my $read_cmd = "$Config{qmHandle_cmd} -m$msg_id";
&write_log("$read_cmd\n");
my $msg_txt = `$read_cmd`;
if( $msg_txt =~ /$Config{match_pattern}/ ) {
# 文件内容匹配指定正则表达式的情况下,删除该邮件,并写log
my $del_cmd = "$Config{qmHandle_cmd} -d$msg_id";
system("$Config{qmHandle_cmd} -d$msg_id");
&write_log("message: $msg_id deleted\n");
} else {
# 文件内容匹配指定正则表达式的情况下,写log
&write_log("# message: $msg_id does not match\n");
}
}
close(MSG_LIST);
}
}
#-------------------------------------------------------------------
sub get_date()
{
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
return sprintf("%04d%02d%02d", $year + 1900, $mon +1, $mday);
}
#-------------------------------------------------------------------
sub get_time()
{
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
return sprintf("%02d:%02d:%02d", $hour, $min, $sec);
}
#-------------------------------------------------------------------
sub write_log($)
{
my ($log_msg) = @_;
open(LOG, ">>$Config{log_file}") || die("Cannot open $Config{log_file}\n");
print LOG $log_msg;
close(LOG);
}
以上程序,优点是可以实现复杂条件的删除,缺点是执行速度比较慢。
删除送往特定域名的邮件,有一个更快更好的方法:设置alias本地接收并丢弃邮件
$ echo '#' > /var/qmail/alias/.qmail-baddomain-default
$ vi /var/qmail/control/virtualdomains
(追加)
bad.domain.name:alias-baddomain
$ vi /var/qmail/control/smtproutes
(追加)
bad.domain.name:127.0.0.1
$ /var/qmail/bin/qmail-tcpok
$ kill -HUP qmail-sendのPID
还有一个方法:直接删除queue下面的文件1) 停止qmail
2) 删除queue下面的消息文件
# cd /var/qmail/queue/mess
# find ./ -type f -exec grep "^To: addr@bad.domain" {} \; -print -exec rm {} \; 3) 执行
queue-fix# ./queue-fix -i /var/qmail/queue4) 启动qmail