#!/usr/bin/perl

# This script uses the perfect_maildir script to convert mailboxes from 
# mbox to Maildir format. It expects a file in the local directory named 
# userlist.txt that has one username per line. 

# Caveat: I had set up the old inboxes in the user home directory by have qmail
# point to ./INBOX and setting up links from /var/spool/mail pointing to each
# user's INBOX.

# Known bugs (my conversion is done...): If the user does not have anything in 
# their mboxlist file, this script doesn't do anything, even though they 
# probably do have stuff in their INBOX. Also, if the user has modified thier
# .qmail file (in my case, by setting up SpamAssassin going through procmail), 
# the mail delivery path will have to be massaged by hand.

# Script is released under the GPL, blah, blah, blah... if it breaks you get
# to keep both halves...

use strict;

my $username;
my $homedir;
my $qmail;
my $hmdir;
my $newmdir;
my $mblist;
my $inbox_flag;
my $subs;
my $folder;
my $folderpath;
my @parents;
my $cmd;
my $junk;
my $msgcount;
my $time;
my $userfoldercount = 0;
my $usermsgcount = 0;
my $usertime = 0;
my $totalfoldercount = 0;
my $totalmsgcount = 0;
my $totaltime = 0;
my $totalusers = 0;

open (USERS,"userlist.txt") || die "Cannot open userlist.txt\n";

while (<USERS>)
{
	chop();
	next if /^#/;
	next if /^ /;

	$totalusers++;
	$userfoldercount = 0;
	$usermsgcount = 0;
	$usertime = 0;

	$username = $_;
	$homedir = (getpwnam("$username"))[7];
	$mblist = $homedir . "/.mailboxlist";
	$hmdir = $homedir . "/Maildir/";
	$subs = $homedir . "/Maildir/courierimapsubscribed";
	$qmail = $homedir . "/.qmail";
	print "\nUSERNAME: $username\n";
	
	if (-e $mblist) # make sure that they have a .mailboxlist file
	{
		$cmd = "/var/qmail/bin/maildirmake $hmdir";
		system ($cmd);

		$inbox_flag = 0;
		open (SUBS,">$subs");
		print SUBS "INBOX\n";
		close (SUBS);

		open (MBLIST, $mblist);
		while (<MBLIST>) # process each mailbox listed in .mailboxlist
		{
			chop;
			$folder = $_;
			$folderpath = $homedir . "/" . $folder;

			if (-e  $folderpath) # does the original mailfolder actually exist?
			{
				print "Processing folder: $folderpath\n";
				if ($folder eq "INBOX") #  we've already created the new Maildir
				{
					$newmdir = $hmdir;
					$inbox_flag = 1;
				}
				else # some other folder, need to create a new Maildir to hold it
				{

					@parents = split (/\//,$folder);
					$newmdir = $hmdir;
					$folder = 'INBOX';
					while (my $subdir = shift(@parents))  # if they have folder heirarchy, build it
					{
						$newmdir .= "." . $subdir;
						$folder .= "." . $subdir;
						if (-e $newmdir) # already created
						{ 
							next; 
						} 
						else # create the new Maildir and subscribe to it
						{
							$cmd = "/var/qmail/bin/maildirmake \"$newmdir\"";
							system ($cmd);

							open (SUBS,">>$subs");
							print SUBS "$folder\n";
							close (SUBS);
						}
					}
				}

				# now that the Maildir is created, let's move the messages
				$cmd = "/root/bin/perfect_maildir \"$newmdir\" < \"$folderpath\"";
				$junk = `$cmd`;

				# get the statistics from perfect_maildir
				$msgcount = (split / messages/,(split (/Inserted /,$junk))[1])[0];
				$time = (split / seconds/,(split / in /,$junk)[1])[0];
				$usermsgcount += $msgcount;
				$usertime += $time;

				# compress the old mailbox in case we need to revert
				$cmd = "/bin/gzip \"$folderpath\"";
				system ($cmd);
				$userfoldercount++;
			}
			else # the mailbox listed in .mailboxlist doesn't exist
			{
				print "\tFolder $folderpath does not exist!";
			}
		}
		close (MBLIST);

		if ($inbox_flag == 0) # they aren't subscribed to their inbox
		{
			open (MBLIST, ">>$mblist"); # add INBOX to their .mailboxlist
			print MBLIST "INBOX\n";
			close (MBLIST);

			# process the INBOX since we didn't above
			$folderpath = $homedir . "/INBOX";
			$cmd = "/root/bin/perfect_maildir " . $hmdir;
			$cmd .= " < \"$folderpath\"";
			$junk = `$cmd`;

			# get the statistics from perfect_maildir for the INBOX
			$msgcount = (split / messages/,(split (/Inserted /,$junk))[1])[0];
			$time = (split / seconds/,(split / in /,$junk)[1])[0];
			$usermsgcount += $msgcount;
			$usertime += $time;
			$userfoldercount++;

			# compress the old INBOX in case we need to revert
			$cmd = "/bin/gzip \"$folderpath\"";
			system ($cmd);
		}

		# ensure that the new Maildir and its contents are owned by the user
		$cmd = "/bin/chown -R $username:$username $hmdir";
		system ($cmd);

		if ((stat($qmail))[7] != 8) #qmail file is not ./INBOX
		{
			print "\tQmail file has changed!\n";
			open (QMAIL,"$qmail");
			while (<QMAIL>)
			{
				print "\t$_";
			}
			close (QMAIL);
		}
		else # the user didn't modify their .qmail file, update it to point to the Maildir
		{
			print "\tUpdating qmail file\n";
			open (QMAIL,">$qmail");
			print QMAIL "./Maildir/\n";
			close(QMAIL);
		}

		# print out the user stats & update the totals
		print "Total messages for $username: $usermsgcount\n";
		print "Total folders for $username: $userfoldercount\n";
		print "Total time for $username: $usertime seconds\n";
		$totalmsgcount += $usermsgcount;
		$totalfoldercount += $userfoldercount;
		$totaltime += $usertime;
	}
	else  # the user doesn't have a .mailboxlist file
	{	
		print "\tERROR OPENING MAILBOX LIST $mblist!!!\n";
	}
}
close (USERS);

# print out the total stats
print "\n\n";
print "Total Users: $totalusers\n";
print "Total messages: $totalmsgcount\n";
print "Total Folders: $totalfoldercount\n";
print "Total Time: $totaltime seconds\n";
