We needed a method to keep our NAS cleaned up. This script does the following: - Moves inactive customers past due by 60 days to a backup location. - Searches the directories (both on the domain level and user level) for orphaned folders and moves these to a backup location. - Creates a full logfile of all actions. - Emails a summery of the actions (showing in the $messageX variables below). Orphaned folders happened when a domain or username no longer exists within our database. # User Variables $startDir = "M:\\IMail"; $tossDate = 60; $message1 = "The following directories have been moved to the Inactive Folder:\n"; $message2 = "The following folders were found to be orphaned:\n"; $message3 = "The following users or domains were saved by being inactive less than $tossDate days:\n"; $totalUsers = 0; $totalDomains = 0; use Date::Pcalc qw(:all); ($Second, $Minute, $Hour, $day, $month, $year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); $year = $year + 1900; $month = $month + 1; $todaysDate = $year .substr("0" x 2 .$month, -2) .substr("0" x 2 .$day, -2); $endDir = "M:\\Inactive\\$todaysDate"; my $localTime = localtime time; my $startTime = time(); use Win32::ODBC; $odbcId = "sa"; $odbcPwd = "********"; $odbcDatabase = "XxXxXxX"; # Load the Platypus Database for All Domains. if ( !($db1 = new Win32::ODBC("DSN=$odbcDatabase;UID=$odbcId;PWD=$odbcPwd;"))) { die "Unable to connect to DSN $odbcDatabase" . Win32::ODBC::Error( ) . "\n"; } $SqlStatement1 = "SELECT d_custid, d_active, domain FROM domain_item ORDER BY domain_item.domain"; if ($db1->Sql($SqlStatement1)) { print "SQL failed.\n"; print "Error: " . $db1->Error() . "\n"; $db1->Close(); exit; } open LOGFILE, ">M:\\Inactive\\$todaysDate\logfile.txt"; while($db1->FetchRow()) { my @DData = $db1->Data("d_custid", "d_active", "domain"); $d_custid = $DData[0]; $d_active = $DData[1]; $domain = $DData[2]; push (@domains, $domain); $totalDomains++; print "CHECKING DOMAIN:$domain\t $d_custid\t"; print LOGFILE "CHECKING DOMAIN:$domain\t $d_custid\t"; if ($d_active eq "Y") { print "Active.\n"; print LOGFILE "Active.\n"; print "\tChecking users:\n"; print LOGFILE "\tChecking users:\n"; userCheck($domain); } else { print "Inactive.\n"; print LOGFILE "Inactive.\n"; if (-e "$startDir\\$domain") { print "\tFolder exists on the Mailserver\n"; print LOGFILE "\tFolder exists on the Mailserver\n"; # Load the Platypus Database for domains crossed with LastInvoice. if ( !($db2 = new Win32::ODBC("DSN=$odbcDatabase;UID=$odbcId;PWD=$odbcPwd;"))) { die "Unable to connect to DSN $odbcDatabase" . Win32::ODBC::Error( ) . "\n"; } $SqlStatement2 = "SELECT customer.id, customer.laststmt, domain_item.d_custid, domain_item.domain FROM customer INNER JOIN domain_item ON customer.id = domain_item.d_custid WHERE domain_item.domain = '$domain'"; if ($db2->Sql($SqlStatement2)) { print "SQL failed.\n"; print "Error: " . $db2->Error() . "\n"; $db2->Close(); exit; } $db2->FetchRow(); my @StmtData = $db2->Data("id", "laststmt", "d_custid", "domain"); $db2->Close(); $id = $StmtData[0]; $laststmt = $StmtData[1]; # Compute time difference. $inactiveTotal = daysInactive($laststmt); print "\t$laststmt Inactive: $inactiveTotal Days.\t"; print LOGFILE "\t$laststmt Inactive: $inactiveTotal Days.\t"; if ($inactiveTotal > 60) { print "Moving folders.\n"; print LOGFILE "Moving folders.\n"; moveDir("$startDir\\$domain" ,$endDir ); $message1 = $message1 ."\t$id $startDir\\$domain \t $laststmt\n"; } else { print "Not Past $tossDate.\n"; print LOGFILE "Not Past $tossDate.\n"; $message3 = $message3 ."\t$id $startDir\\$domain \t $laststmt\n"; print "\tChecking users:\n"; print LOGFILE "\tChecking users:\n"; userCheck($domain); } # Inactive. Ending Date Check. } else { print "\tNo folders to move.\n"; print LOGFILE "\tNo folders to move.\n"; } } } # Checking all valid Plat Domains. $db1->Close(); folderCheck($startDir, $endDir, "Domain", @domains); @domains = (); close LOGFILE; my $endTime = time(); my $elapsed = $endTime - $startTime; $message4 = "Total cleanup took $elapsed seconds. $totalDomains Domains and $totalUsers Users verified."; sendMail("\n". $message1 ."\n" .$message2 ."\n" .$message3 ."\n" .$message4); sub userCheck { my ($domain) = @_; chomp($domain); # Load the Platypus Database for User Data. if ( !($db3 = new Win32::ODBC("DSN=$odbcDatabase;UID=$odbcId;PWD=$odbcPwd;"))) { die "Unable to connect to DSN $odbcDatabase" . Win32::ODBC::Error( ) . "\n"; } $SqlStatement3 = "SELECT customer.id, customer.active, customer.laststmt, email_data.d_custid, email_data.data_id, email_data.userdir, email_data.domain, email_data.emailaddr FROM customer INNER JOIN email_data ON customer.id = email_data.d_custid WHERE email_data.domain = '$domain' ORDER BY email_data.data_id"; if ($db3->Sql($SqlStatement3)) { print "SQL failed.\n"; print "Error: " . $db3->Error() . "\n"; $db3->Close(); exit; } while($db3->FetchRow()) { my @UserData = $db3->Data("id", "active", "laststmt", "data_id", "userdir", "domain", "emailaddr"); $active = $UserData[1]; $laststmt = $UserData[2]; $data_id = $UserData[3]; $userdir = $UserData[4]; $emailaddr = $UserData[6]; $totalUsers++; push (@data_id, $data_id); if ($active eq "Y") { # Is the account active? print "\t\t$emailaddr\t $data_id\t Active.\n"; print LOGFILE "\t$emailaddr\t $data_id\t Active.\n"; } else { print "\t$emailaddr\t $data_id\t Inactive.\t"; print LOGFILE "\t$emailaddr\t $data_id\t Inactive.\t"; if (-e $userdir) { print "Folder exists.\n"; print LOGFILE "Folder exists.\n"; $laststmt = $UserData[2]; # Compute time difference. $inactiveTotal = daysInactive($laststmt); print "\t\t$laststmt Inactive: $inactiveTotal Days.\n"; print LOGFILE "\t\t$laststmt Inactive: $inactiveTotal Days.\n"; if ($inactiveTotal > 60) { print "\t\t Moving folders.\n"; print LOGFILE "\t\t Moving folders.\n"; $message1 = $message1 ."\t$emailaddr $userdir $laststmt\n"; moveDir($userdir ,"$endDir\\$domain\\users"); } else { print "\t\t Not Past $tossDate.\n"; print LOGFILE "\t\t Not Past $tossDate.\n"; $message3 = $message3 ."\t$emailaddr $userdir \t $laststmt\n"; } } else { print "No folders to move.\n"; print LOGFILE "No folders to move.\n"; } } } # End While there are rows to fetch. folderCheck("$startDir\\$domain\\users", "$endDir\\$domain\\users\\", "User", @data_id); @data_id = (); } sub folderCheck { # # Used to compare folders listed within Plat versus folders on the servers directory listing. # my ($startDir, $endDir, $type, @elements) = @_; opendir(DIR, $startDir); # Domain: Do not include Directory Names starting with a '.' or those that do not have a '.' somewhere. if ($type eq "Domain") { @directories = grep {!/^\./ && /\./} readdir(DIR); } # Users: Do not include Directory Names starting with a '.' if ($type eq "User") { @directories = grep {!/^\./} readdir(DIR); } closedir(DIR); print LOGFILE "VALID:\n"; print LOGFILE join("\n", @elements),"\n"; print LOGFILE "DIRECTORIES:\n"; print LOGFILE join("\n", @directories),"\n"; my (%h1, %h2); @h1{@directories} = (); @h2{@elements} = (); for my $key (keys %h1) { push @uniq => $key unless exists $h2{$key}; } print "\n\tChecking for orphaned folders:\n"; print LOGFILE "\n\tChecking for orphaned folders:\n"; foreach $uniq (@uniq) { print "\t Folder: $uniq\n"; print LOGFILE "\t Folder: $uniq\n"; $message2 = $message2 ."\t$startDir\\$uniq\n"; moveDir("$startDir\\$uniq", $endDir); } @h1 = (); @h2 = (); @uniq = (); @elements = (); @directories = (); } sub daysInactive { my ($laststmt) = @_; $inactiveYear = substr($laststmt,0,4); $inactiveMonth = substr($laststmt,5,2); $inactiveDay = substr($laststmt,8,2); $inactiveTotal = Delta_Days( $inactiveYear, $inactiveMonth, $inactiveDay, $year, $month, $day); return $inactiveTotal } sub moveDir { my ($startDir, $endDir) = @_; if (! -e $endDir) { print "\t\tCreating " .$endDir ."\n"; print LOGFILE "\t\tCreating " .$endDir ."\n"; mkpath($endDir); } print "\t\t Copying $startDir to $endDir\n"; print LOGFILE "\t\t Copying $startDir to $endDir\n"; DIR_COPY($startDir, $endDir); print "\t\t Removing $startDir\n"; print LOGFILE "\t\t Removing $startDir\n"; DIR_REMOVE($startDir); } sub sendMail { my ($message) = @_; use Net::SMTP; $smtp = Net::SMTP->new('***********'); $smtp->mail('******@evenlink.com'); $smtp->to('********@evenlink.com'); $smtp->data(); $smtp->datasend("To: *******@evenlink.com\n"); $smtp->datasend("Subject: MailServer Cleanup Actions.\n"); $smtp->datasend("\n"); $smtp->datasend($message); $smtp->dataend(); $smtp->quit; }