SF.net SVN: postfixadmin: [133] trunk/ADDITIONS/mailbox_remover.pl
Brought to you by:
christian_boltz,
gingerdog
From: <chr...@us...> - 2007-10-05 00:05:33
|
Revision: 133 http://postfixadmin.svn.sourceforge.net/postfixadmin/?rev=133&view=rev Author: christian_boltz Date: 2007-10-04 17:05:31 -0700 (Thu, 04 Oct 2007) Log Message: ----------- - fix: do not remove . and .. (thanks rschetterer!) - added support for domain subdir style layouts and lots of error checks (thanks abatie!) - added exit status check after archiving mailbox before calling rmtree - references: - https://sourceforge.net/tracker/index.php?func=detail&aid=1750088&group_id=191583&atid=937964 - http://www.rdrop.com/files/mailbox_remover.pl Modified Paths: -------------- trunk/ADDITIONS/mailbox_remover.pl Modified: trunk/ADDITIONS/mailbox_remover.pl =================================================================== --- trunk/ADDITIONS/mailbox_remover.pl 2007-10-04 14:58:38 UTC (rev 132) +++ trunk/ADDITIONS/mailbox_remover.pl 2007-10-05 00:05:31 UTC (rev 133) @@ -3,64 +3,122 @@ # by Petr Znojemsky (c) 2004 # Mailbox remover 0.1a 23/10/2004 - the very first version for MySQL # removes maildirs from disk when they are not found in a database -# Run program and read the $logfile before uncommenting the "rmtree" line! +# +# Added subdir support and pause --- Alan Batie 2007 +# Lists directories to be deleted then pauses for 5 seconds for chance to abort +# $Id: mbox_remover,v 1.4 2007/07/12 22:11:09 alan Exp alan $ +# # All your maildirs or other directories could be accidentally removed. # Use it at own risk. No warranties! +use strict; use DBI; use File::Path; ########## # Set these variables according to your configuration -$maildir_path="/var/mail/virtual/"; -$logfile="/var/log/mail/removed_maildirs"; +# when mailboxes are removed, save their tarballs here +my $archdir="/var/archive/mailboxes"; + +# expected to support z option, tweak invocation if you want different +my $archcmd="/usr/bin/tar"; + +# trailing slash not needed +my $maildir_path="/var/mail"; +# find out if we need to check subdirs for mailboxes or just maildir_path +# $CONF['domain_path'] = 'YES'; +my $pfadmin_config="/usr/local/www/postfixadmin/config.inc.php"; + # database information -$host="localhost"; -$port="3306"; -$userid="postfix"; -$passwd="postfix"; -$db="postfix"; +my $host="localhost"; +my $port="3306"; +my $userid="dbuser"; +my $passwd="dbpw"; +my $db="dbname"; ############ -$connectionInfo="DBI:mysql:database=$db;$host:$port"; +my $connectionInfo="DBI:mysql:database=$db;$host:$port"; # make connection to database -$dbh = DBI->connect($connectionInfo,$userid,$passwd); +my $dbh = DBI->connect($connectionInfo,$userid,$passwd); # prepare and execute query -$query = "SELECT username FROM mailbox"; -$sth = $dbh->prepare($query); +my $query = "SELECT maildir FROM mailbox"; +my $sth = $dbh->prepare($query); $sth->execute(); + # assign fields to variables -$sth->bind_columns(\$username); -# output computer list to the browser +my ($db_maildir, %db_maildirs); +$sth->bind_columns(\$db_maildir); + +# load up directory list while($sth->fetch()) { -push(@usernames, $username); + $db_maildirs{$db_maildir} = 1; } + $sth->finish(); # disconnect from database $dbh->disconnect; -# store maildir list to @directories -opendir(DIRHANDLE, $maildir_path) || die "Cannot open dir $maildir_path: $!"; -foreach $name (sort readdir(DIRHANDLE)) -{ - push (@directories, $name); +# +# find out if we need to check subdirs for mailboxes or just maildir_path +# $CONF['domain_path'] = 'YES'; +# +my $use_subdirs = 0; +open(CONFIG, "<$pfadmin_config") || die "Can't open '$pfadmin_config': $!\n"; +while(<CONFIG>) { + if (/\$CONF\['domain_path'\] *= *'([^']*)'/) { + $use_subdirs = ($1 =~ /yes/i); + } } -closedir(DIRHANDLE); -# eliminate "." and ".." from the maildir list -($dot, $doubledot, @directories) = @directories; +close(CONFIG); +# store maildir list to %directories +# key is path, value is username to use in archive file +my %directories; +opendir(DIR, $maildir_path) || die "Cannot open dir $maildir_path: $!\n"; +foreach my $name (readdir(DIR)) { + next if ($name eq '.' || $name eq '..' || ! -d "$maildir_path/$name"); + if ($use_subdirs) { + opendir(SUBDIR, "$maildir_path/$name") || die "Cannot open dir $maildir_path/$name: $!\n"; + foreach my $subname (readdir(SUBDIR)) { + next if ($subname eq '.' || $subname eq '..' || ! -d "$maildir_path/$name/$subname"); + # db entry has trailing slash... + if (!defined($db_maildirs{"$name/$subname/"})) { + print "marking $maildir_path/$name/$subname for deletion.\n"; + $directories{"$name/$subname"} = "$name-$subname"; + } + } + closedir(SUBDIR); + } else { + # db entry has trailing slash... + if (!defined($db_maildirs{"$name/"})) { + print "marking $maildir_path/$name for deletion.\n"; + $directories{"$name"} = $name; + } + } +} +closedir(DIR); + +print "Ctrl-C in 5 seconds to abort before removal starts...\n"; +sleep 5; + +my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); +# yyyymmddhhmm +my $tstamp = sprintf("%04d%02d%02d%02d%02d", $year+1900, $mon+1, $mday, $hour, $min); + # compare two arrays and erase maildirs not found in database -foreach $maildir (@directories) -{ - if ((grep { $_ eq $maildir} @usernames)==0) - { - # username not found, delete maildir. - # Please read $logfile before uncommenting following line! - # rmtree($maildir_path.$maildir); - open(INFO, ">>$logfile") || die "Cannot write to the logfile: $logfile."; - print INFO localtime()." Maildir ".$maildir_path.$maildir." has been deleted.\n"; - close(INFO); - } +chdir $maildir_path || die "Can't change to maildir '$maildir_path': $!\n";; +my @args; +foreach my $maildir (keys(%directories)) { + my $archive = "$archdir/$directories{$maildir}-$tstamp.tgz"; + # quick permissions check + open(TOUCH, ">$archive") || die "Can't create archive file $archive: $!\n"; + close(TOUCH); + print "Archiving $maildir\n"; + @args = ($archcmd, "cvzf", $archive, $maildir); + system(@args) == 0 or die "Creating archive for $maildir failed: $?" + + rmtree($maildir); + print localtime() . " $maildir has been deleted.\n"; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |