#!/usr/bin/perl -w
#
# mbox2imap - convert user mbox files to IMAP mailboxes
# Written by Steve "Pheran" Snodgrass <ssnodgra@fore.com>
# Hacked a little by Danny Howard of Tellme Networks, Inc.
# <dannyman@tellme.com>
#
# This script is public domain; you may do whatever you want with it!
# You must have the NetxAP module from CPAN to run this script.
# Please note that there is a bug in NetxAP 0.01 that causes setquota to
# fail.
# To fix it, change IMAP.pm line 458 to read 'setquota' instead of getquota'
#
# This script accepts a list of mbox file names as parameters.  These names
# are also assumed to correspond to user names.  It will prompt for a
# username
# and password on the IMAP server.  The account you login as will need to
# have admin privileges.  Each mbox file is copied into a folder called
# user.filename, where filename is the name of the mbox file being copied.
#
# Example (assumes no junk files lying around in /var/mail):
# $ cd /var/mail
# $ mbox2imap *

    use File::Basename;
    use Net::IMAP;

# Set the following 2 lines to your Cyrus admin account/password
$user = "ADMIN USER";
$pass = "ADMIN PASS";

    # Set this to the hostname of your IMAP server
    $IMAPSERVER = "YOUR CYRUS SERVER";



    #
    # Dump a Unix-style mbox file into an IMAP folder
    # Arguments: IMAP connection, IMAP mailbox name, mbox file name
    #
    sub TransferMbox {
        my ($imap, $mailbox, $mboxfile) = @_;

        my $blank = 1;
        my $count = 0;
        my $message = "";
        my $response;

$|++;

        print "Transferring $mboxfile \n";
        open(MBOX, "/usr/bin/formail -s < '$mboxfile' |");
        while (<MBOX>) {
            if ($blank && /^From .*?@/ ) {
                if ($message && $message !~ /^X-IMAP: .*$/ms) {
                    chop $message;  # Remove extra blank line before next From
                    $response = $imap->append($mailbox, $message);
		    if( $response->status ne 'OK' ) { print 'X';
			print "\n", $response->status, "-",
			    $response->status_text, "\n$message\n"; } else
			{ print '.'; $count++; }
                }
                $message = "";
            }
            else {
                chop;
                s/$/\r\n/;      # IMAP requires CR/LF on each line
		if( /\000/ ) {
			s/\000//g; 	# NUL is evil
			print "!";
		}
                $message .= $_;
            }
            $blank = /^\r$/ ? 1 : 0;
        }
	if ($message && $message !~ /^X-IMAP: .*$/ms) {
	       	$response = $imap->append($mailbox, $message);
		if( $response->status ne 'OK' ) { print 'X';
			print "\n", $response->status, "-",
			$response->status_text, "\n$message\n"; }
			    else { print "."; $count++ }
	}
    #   print $response->status, "-", $response->status_text, "\n";
        close(MBOX);
	print " DONE!\n";
        print "Transferred $count messages from $mboxfile to $mailbox.\n";

$|--;

    }


    #
    # Main Code
    #

    # Login to IMAP server
    $imap = new Net::IMAP($IMAPSERVER, Synchronous => 1);
    $response = $imap->login($user, $pass);
    print "Login:\t", $response->status, "-", $response->status_text, "\n";

    # Process each filename argument
    foreach $mbox (@ARGV) {
        $mailbox = "user." . basename($mbox);

        # Create the new mailbox
        $response = $imap->create($mailbox);
        print "Create:\t", $response->status, "-", $response->status_text, "\n";

        # Modify the ACL on the mailbox so we can add messages
        $response = $imap->setacl($mailbox, $user, "di");
        print "Set ACL:\t", $response->status, "-", $response->status_text, "\n";

        # Set a 100 Meg quota on the new mailbox
        #$response = $imap->setquota($mailbox, "STORAGE", 100000);
        #print "Set Quota: ", $response->status, "-", $response->status_text, "\n";

        # Copy the mbox
        if (-s $mbox) {
            TransferMbox($imap, $mailbox, $mbox);
        }

        # Fix ACL on mailbox
        $response = $imap->setacl($mailbox, $user, "-di");
        print "Set ACL:\t", $response->status, "-", $response->status_text, "\n";

    }

    # Disconnect from IMAP server
    $response = $imap->logout();
    print "Logout: ", $response->status, "-", $response->status_text, "\n";


