#! /usr/bin/perl

##################################################################
# NetMail 3.5.2 Cleanup Routine - FINAL                          #
#                                                                #
# Author: Tim Patterson                                          #
# Email:  tjpatter@svsu.edu                                      #
#                                                                #
# This is a tool used to delete mail from NetMail mailboxes      #
# using user-defined parameters.                                 #
#                                                                #
# This tool will run against NetWare or Linux, but must be ran   #
# from a Linux machine.                                          #
#                                                                #
# Feel free to contact me with any questions.                    #
#                                                                #
##################################################################

## Configuration Options:

$server = "127.0.0.1";                         # NetMail Server (Must be a Trusted Host in WebAdmin)
$port = 689;                                   # NMAP Protocol Port

$path = "/var/opt/novell/netmail/users/";      # Path to Mailbox Data Store

$simulation = 1;                               # Performs a "Simulation" run when set to 1. Set to 0 to enable deletion

$targetdays = 90;                              # Delete Mail Older than this Number of Days

$whattoremove = "UNREAD";                      # Either "UNREAD" or "ALL".  Determines what is to be removed
                                               # the "UNREAD" option removes unread mail and mail marked as 
                                               # deleted (but not purged).  "ALL" removes all mail older than
                                               # specified date.                                            

$cleanfolders = "ALL";                         # Either "INBOX" or "ALL" (Case Sensitive)

$cleansent = 0;                                # 1 = True.  Cleans all folders that contain "sent" in the folder name

$debugmode = 0;                                # 1 = True.  Prints actual NMAP commands when set to true

############## DO NOT CHANGE ANYTHING BELOW THIS LINE!!! ##############
#######################################################################

use Socket;
use Date::Manip;
use Number::Bytes::Human qw(format_bytes);

$targetdaystotal = $targetdays * 86400;

$totalsize = 0;
$totaldelcount = 0;
$totalusers = 0;
$totalboxes = 0;

system("clear");

print "\nNetMail 3.5.2 Cleanup Routine\n";
print "-----------------------------\n\n";

if ( $simulation == 1 )
{
   print "Running in SIMULATION mode.\n";
} else {
   print "Running in DELETE mode.\n";
}

if ( $cleanfolders eq "INBOX" )
{
   print "Cleaning only INBOX.\n";
} else {
   print "Cleaning ALL Folders.\n";
   if ($cleansent == 1)
   {
      print "   Cleaning 'Sent Items' Folders\n";
   } else {
      print "   Excluding 'Sent Itmes' Folders\n";
   }
}

if ( $whattoremove eq "UNREAD" )
{
   print "\nRemoving only UNREAD mail\n";
} else {
   print "\nRemoving ALL mail\n";
}

print "Removing Mail Older Than $targetdays Days.\n";

print "\nGetting List of Users...   ";

opendir(DIRHANDLE, "$path") || die "Cannot open dir $path: $!";

$a=0;
foreach $name (grep { !/^\.\.?$/ && -d "$path/$_" } sort readdir(DIRHANDLE)) 
{
   $master[$a] = $name;
   $a++;
}

closedir(DIRHANDLE);

print "DONE!\n";

# Drop into first user's folder:
foreach $dir (@master)
{
   @folders = "";

   chomp($dir);

   print "\nFinding Mailboxes for user: $dir...   ";

   $totalusers++;

   open(LIST, "ls --show-control-chars $path$dir|");
   
   print "DONE!\n";
   print "   Mailboxes Found:\n";

   $i = 0;
   foreach $name (<LIST>)
   {
      if ( $name =~ s/$\.box// )
      {
         $name =~ s/\n//;
         $folders[$i] = "$name";
         print "     $name\n";
         $i++;
      }
   }
   close(LIST);

   if ( $cleanfolders eq "INBOX" )
   {
      $totalboxes++;
      print "\n   Cleaning INBOX\n";

      &connect;

      @out = nmap("USER $dir");
      @out = nmap("MBOX INBOX");

      @out = nmap("GINFO Date");   

      #print @out;

      pop @out;
      $usersize = 0;
      $delcount = 0;

      foreach $message (@out)
      {
         @split = split(/-/, $message);

         @data = split(/ /, $split[1]);

         if ( ($data[4] == 4 || $data[4] == 6) || ($whattoremove eq "ALL") )
         {
            $remove = 1;
         } else {
            $remove = 0;
         }

         if ( $remove == 1 )
         {
            $string = $data[10] . $data[11] . $data[12];
            $older = calcdate($string);

            if ( $older == 1 )
            {
               $totalsize = $totalsize + $data[1];
               $usersize = $usersize + $data[1];

               $totaldelcount++;           
               $delcount++; 

               if ( $simulation == 1 )
               {
                  print "     Delete: $data[0]\n";
               } else {
                  print "     Delete: $data[0]\n";
                  @del1 = nmap("DELE $data[0]");
                  print "     Delete Output: @del1\n";
                  @del2 = nmap("PURG $data[0]");
                  print "     Purge Output: @del2\n";
                  @out = nmap("GINFO Date");   
               }
            }
         }
      }

      if ( $delcount == 0 )
      {
         print "     No mail to delete here!\n";
      }

      print "\n   Messages Removed: $delcount\n";
      
      $size = format_bytes($usersize);
      print "   Disk Space Freed: $size\n";

      &disconnect;

   } else {
      print "\n   Cleaning ALL Mailboxes\n";

      &connect;

      @out = nmap("USER $dir");

      $usersize = 0;
      $delcount = 0;

MBOX: foreach $mbox (@folders)
      {
         if ( $cleansent == 0 )
         {
            if ( $mbox =~ m/[S|s][E|e][N|n][T|t]/ )
            {
               print "\n   Skipping Sent Items: $mbox\n";
               next MBOX;
            }
         }

         @boxresponse = nmap("mbox $mbox");

         if ( $boxresponse[0] == 4224 )
         {
            print "      MBOX Does Not Exist\n";
         } else {
            $totalboxes++;
            print "\n   Cleaning $mbox\n";
           
            @list = nmap("GINFO Date");
         
            pop @list;
            
            foreach $message (@list)
            {
               @split = split(/-/, $message);
               @data = split(/ /, $split[1]);

               if ( ($data[4] == 4 || $data[4] == 6) || ($whattoremove eq "ALL") )
               {
                  $remove = 1;
               } else {
                  $remove = 0;
               }

               if ( $remove == 1 )
               {
                  $string = $data[10] . $data[11] . $data[12];
                  $older = calcdate($string);

                  if ( $older == 1)
                  {
                     $totalsize = $totalsize + $data[1];
                     $usersize = $usersize + $data[1];

                     $totaldelcount++;
                     $delcount++;

                     if ( $simulation == 1 )
                     {
                        print "     Delete: $data[0]\n";
                     } else {
                        print "     Delete: $data[0]\n";
                        @del1 = nmap("DELE $data[0]");
                        print "        Delete Output: @del1\n";
                        @del2 = nmap("PURG $data[0]");
                        print "        Purge Output: @del2\n";
                        @list = nmap("GINFO Date");
                     }
                  }
               }
            }

         }

         @out = nmap("RSET MBOX");
      }

      &disconnect;
   }
}

close(LIST);

print "\n---------   DONE   ----------\n\n";

print "Total Users Cleaned:     $totalusers\n";
print "Total Mailboxes Cleaned: $totalboxes\n\n";
print "Total Messages Removed:  $totaldelcount\n";

$size = format_bytes($totalsize);
print "Total Disk Space Freed:  $size\n\n";

sub calcdate($datestring)
{
   my $datestring = shift;

   $today = UnixDate("today","%o");
   $mail = UnixDate("$datestring","%o");

   if ( ($today - $mail) > $targetdaystotal )   
   {
      return 1;
   } else {
      return 0;
   }
}

sub connect()
{
   &connectToserver();
   $status = <NMAP>;

   if ( $status != '1000 lan8-28.svsu.edu Novonyx NMAP server ready' )
   {
      print "\nNMAP Agent is not running on: $server:$port\n";
      exit 0;
   }
}

sub disconnect()
{
   close NMAP;
}

sub nmap($command)
{
   @output = ();
   $response = "";

   my $command = shift;

   if ($debugmode == 1)
   {   
      print "\nNMAP: $command\n";
   }

   print NMAP "$command\n";

   $i = 1;
   $a = 0;
   while ( $i != 0 )
   {
      if ($i == 1000)
      {
         print "\n\nFATAL Error - Did not receive 1000 status!!!\n\n";
         exit 1;
      }

      $response = <NMAP>;

      if ( $response =~ /^1000/ )
      {
         $output[$a] = $response;
         return @output;
      } 

      if ( $response =~/^4224/ )
      {
         return 4224; 		#Mailbox Doesn't Exist Error
      }

      $output[$a] = $response;

      $i++;
      $a++;
   }
}

sub connectToserver()
{
   if (open_TCP(NMAP,"$server",$port)==undef)
   {
      print "Could not contact server";
      exit(-1);
   }
}

sub open_TCP
{
   my ($FS, $dest, $port) = @_;

   my $proto = getprotobyname('tcp');
   socket($FS, PF_INET, SOCK_STREAM, $proto);
   my $sin = sockaddr_in($port,inet_aton($dest));
   connect($FS,$sin) || return undef;

   my $old_fh = select($FS);
   $| = 1;                       # don't buffer output
   select($old_fh);
1;
}


