From 122910bd596ac2d558d5b53a23f404bfb4274f1f Mon Sep 17 00:00:00 2001 From: VersusBG <47170708+VersusBG@users.noreply.github.com> Date: Tue, 7 Oct 2025 11:55:53 +0300 Subject: [PATCH] Create mailbox_remover_pgsql.pl Mailbox remover for PostgreSQL database. Based on original mailbox remover. --- ADDITIONS/mailbox_remover_pgsql.pl | 138 +++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 ADDITIONS/mailbox_remover_pgsql.pl diff --git a/ADDITIONS/mailbox_remover_pgsql.pl b/ADDITIONS/mailbox_remover_pgsql.pl new file mode 100644 index 00000000..f174a317 --- /dev/null +++ b/ADDITIONS/mailbox_remover_pgsql.pl @@ -0,0 +1,138 @@ +#!/usr/bin/perl +# +# 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 +# +# Added subdir support and pause --- Alan Batie 2007 +# Lists directories to be deleted then pauses for 5 seconds for chance to abort +# +# Changed DBI to PostgreSQL and added user prompt for confirmation +# $Id$ +# +# 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 + +# when mailboxes are removed, save their tarballs here +my $archdir="/var/archive"; + +# 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 +my $dbname="database"; +my $host="localhost"; +my $port="5432"; +my $username="username"; +my $password="password"; + +############ + +# make connection to database +my $dbh = DBI->connect("dbi:Pg:dbname=$dbname;host=$host;port=$port", + $username, + $password, + {AutoCommit => 0} + ); +# prepare and execute query +my $query = "SELECT maildir FROM mailbox"; +my $sth = $dbh->prepare($query); +$sth->execute(); + +# assign fields to variables +my ($db_maildir, %db_maildirs); +$sth->bind_columns(\$db_maildir); + +# load up directory list +while($sth->fetch()) { + $db_maildirs{$db_maildir} = 1; +} + +$sth->finish(); +# disconnect from database +$dbh->disconnect; + +# +# 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() { + if (/\$CONF\['domain_path'\] *= *'(YES|yes)'/) { + $use_subdirs = ($1 =~ /yes/i); + } +} +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 "\n########################################################################\n"; +print "Warning: If you see only /var/mail/domain path then your \$CONF['domain_path']\n"; +print "is not set in postfixadmin/config.inc.php ABORT the removal!!!\n"; +print "########################################################################\n\n"; +print "Do you want to continue with removal of above list (Y/N)?\n"; +my $input = ; + +chomp $input; + +if ($input =~ m/[Y]$/i) { + 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 + 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"; + } +}