#!/usr/bin/perl #----------------------------------------------------------------------------- # # POPular -- A POP3 server and proxy for large mail systems # # $Id: checksize,v 1.3 2001/02/09 15:59:07 sqrt Exp $ # # http://www.remote.org/jochen/mail/popular/ # #----------------------------------------------------------------------------- # # checksize # # This script checks the size of all mailboxes. Mailboxes who are above # or near the quota are logged. Additionally a message is put into the # mailbox to notify the user about his full mailbox. # #----------------------------------------------------------------------------- # # Copyright (C) 1999-2001 Jochen Topf # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA # #----------------------------------------------------------------------------- use strict; my $POPDIR = "/pop"; my $MAXFILES = 2000; my $WARNFILES = 1500; my $MAXSIZE = 50_000_000; my $WARNSIZE = 40_000_000; my $DEFAULTQUOTA = 50; # Default quota in MB. my $WARNPERCENT = 90; # Warn when X % of quota are reached my $BOXLIST = "/etc/popular/mb"; # Directory with mailbox lists my $FROM = "Mail Delivery System "; my $SUPPORTMAIL = "support\@example.com"; #----------------------------------------------------------------------------- chdir($POPDIR) or die("Can't chdir to $POPDIR: $!\n"); my $all_number = 0; my $all_size = 0; my %sumhist; my ($num, $sum, %num, %sum); my ($numflag, $sizeflag); my $mailbox; my @wday = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"); my @month = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); my $hostname = `hostname`; chop $hostname; my %boxhash; foreach my $d (0x0..0xf) { open(LIST, "$BOXLIST/$d") or die("Can't open $BOXLIST/%d: $!\n"); while() { next if (/^$/); next if (/^#/); chomp; my ($box, $quota) = split(/:/, $_, 2); $boxhash{$box} = $quota; } close LIST; } print <<"EOF"; Fl NSum NNew NCur SizeSum SizeNew SizeCur Mailbox ------------------------------------------------------------------------------ EOF foreach my $h (0x0 .. 0xf) { foreach my $d (0x00 .. 0xff) { my $dir = sprintf("%x/%02x", $h, $d); opendir(DIR, $dir) or die("Can't opendir $dir: $!\n"); my @boxes = grep(!/\d$/, grep(!/^\./, readdir(DIR))); closedir(DIR); foreach my $box (@boxes) { CheckBox("$dir/$box", ($boxhash{$box} ? $boxhash{$box} : $DEFAULTQUOTA) * 1024 * 1024); } } } print <<"EOF"; ------------------------------------------------------------------------------ Number of Mailfiles: $all_number Bytes in Mailfiles: $all_size EOF print "Mailbox histogram:\n"; foreach my $c ("Empty", "< 10 kBytes", "< 100 kBytes", "< 1 MByte", ">= 1 MByte") { print "$c\t$sumhist{$c}\n"; } exit 0; #----------------------------------------------------------------------------- sub CheckBox { my($dir, $quota) = @_; $mailbox = $dir; $num = 0; $sum = 0; $num{new} = 0; $num{cur} = 0; $sum{new} = 0; $sum{cur} = 0; foreach my $sd ("new", "cur") { opendir(DIR, "$dir/$sd") or die("Can't opendir $dir/$sd: $!\n"); my @files = grep(!/^\./, readdir(DIR)); closedir(DIR); $num += ($#files + 1); $num{$sd} += ($#files + 1); foreach my $file (@files) { if ($file =~ /_(\d+)$/) { $sum += $1; $sum{$sd} += $1; } else { my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime, $ctime,$blksize,$blocks) = stat("$dir/$sd/$file"); die("Can't stat $dir/$sd/$file: $!\n") unless (defined $dev); $sum += $size; $sum{$sd} += $size; } } } $sizeflag = ($sum >= $quota) ? "S" : ($sum >= $quota * $WARNPERCENT / 100 ? "s" : " "); $numflag = ($num >= $MAXFILES) ? "N" : ($num >= $WARNFILES ? "n" : " "); $all_number += $num; $all_size += $sum; if ($sum == 0) { $sumhist{"Empty"}++; } elsif ($sum < 10240) { $sumhist{"< 10 kBytes"}++; } elsif ($sum < 102400) { $sumhist{"< 100 kBytes"}++; } elsif ($sum < 1024 * 1024) { $sumhist{"< 1 MByte"}++; } else { $sumhist{">= 1 MByte"}++; } if (($sizeflag ne " ") || ($numflag ne " ")) { write; quotamail($dir, $sizeflag, $numflag, $quota); } } sub quotamail { my ($maildir, $sizeflag, $numflag, $quota) = @_; my $time = time(); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time); # BUG: this only works for the MET timezone my $timestring = sprintf("%s, %d %s %4d %02d:%02d:%02d %s", $wday[$wday], $mday, $month[$mon], $year+1900, $hour, $min, $sec, $isdst ? "+0200" : "+0100"); my $mailbox = $maildir; $mailbox =~ s|=.*||; $mailbox =~ s|.*/||; my $subject = ($sizeflag eq "S") || ($numflag eq "N") ? "Mailbox-Quota ueberschritten" : "Mailbox-Quota Warnung"; my $summb = int($sum / 1024); my $sumcurmb = int($sum{cur} / 1024); my $text = <<"EOF"; Return-path: <> Delivery-date: $timestring Message-Id: <0QUOTA.$time\@$hostname> From: $FROM To: Mailbox $mailbox Subject: $subject Date: $timestring X-Quotainfo: $numflag$sizeflag $num $num{new} $num{cur} $sum $sum{new} $sum{cur} Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Diese Nachricht wird automatisch einmal pro Nacht erzeugt bzw. aktualisiert. In Ihrer Mailbox können bis zu $MAXFILES Mails mit ingesamt bis zu $quota MByte liegen. Wenn Ihre Mailbox voll ist, dann können Sie keine weiteren Mails empfangen. Weitere Mails, die für Sie ankommen, werden dann an den Absender zurückgeschickt. In Ihrer Mailbox '$mailbox' haben Sie zur Zeit $num Mails mit ingesamt $summb kBytes. EOF if ($num{cur} > 0) { $text .= <<"EOF"; Von diesen Mails haben Sie schon $num{cur} (mit insgesamt $sumcurmb KBytes) gelesen. EOF } if (($numflag eq "N") || ($sizeflag eq "S")) { $text .= <<"EOF"; Sie haben damit die Maximalgröße Ihrer Mailbox erreicht bzw. überschritten. Es werden keine weiteren Mails für Sie angenommen. EOF } else { $text .= <<"EOF"; Sie haben damit $WARNPERCENT% der Maximalgröße Ihrer Mailbox erreicht bzw. überschritten. Diese Mail ist nur eine Hinweis, daß Sie Ihre Mails möglichst bald lesen und löschen sollten. EOF } $text .= <<"EOF"; Bitte lesen und löschen Sie Ihre Mails regelmäßig, dann gehen Sie sicher, daß alle Mails Sie erreichen. Überprüfen Sie bitte, ob Sie Ihr Mailprogramm so eingestellt haben, daß es Mails nach dem Herunterladen vom Server löscht. Diese Mail wird automatisch erzeugt. Bei Fragen wenden Sie sich bitte an $SUPPORTMAIL. Mit freundlichen Grüßen Ihr Mailsystem EOF $text =~ s|\n|\r\n|g; open(QUOTA, ">$maildir/tmp/0QUOTA.$time") or return; print QUOTA $text; close QUOTA; } format = @@ @>>> @>>> @>>> @>>>>>>> @>>>>>>> @>>>>>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $numflag, $sizeflag, $num, $num{new}, $num{cur}, $sum, $sum{new}, $sum{cur}, $mailbox .