View Single Post
  #2 (permalink)  
Old 09-03-2007, 05:38 PM
boris007 boris007 is offline
Junior Member
 
Posts: 6
Default

Update: I've fixed the problem I was having

Basically, I narrowed it down to the way that Email::Folder parses mbox files. A snippet from the code provided on the mbox migration entry on the Zimbra wiki reads as follows:

Code:
    my $folder = Email::Folder->new($mbox ||
        die "Usage: $0 mbox dest_address [smtp server]
        Forward all mail found in mail file mbox to address.
    ");

    my $count=0;
    my @messages=$folder->messages;
    my $total=@messages;
    }
With my original code (which used the provided code from the wiki including the above), I was finding that
Code:
my @messages=$folder->messages;
wasn't able to properly distinguish all of the messages in the mbox file. For example, working with an mbox file that I know to have 26 messages in, the value of $total was always 2 (only two emails were being properly processed).

After much mucking around, the eventual solution was to drop using Email::Folder and MIME::Parser altogether, and simply use Mail::MboxParser. I'm not saying that this is the best solution for everyone, but it is working perfectly for me where my previous script didn't, not to mention its a little faster and requires less code

See the following if you are interested:
Mail::MboxParser - read-only access to UNIX-mailboxes - search.cpan.org

Anyhow, for those interested here is my script. Again, I stress that I've never done perl before, so its not going to be perfect!

Code:
#!/usr/bin/perl

# mbox to Zimbra mailfile conversion
# last updated 7.9.07
# converts mail files of the mbox format to the Zimbra format

    #-------------------------------------------------------------------------------

    use Email::Folder;
    use Email::FolderType;
    use Email::FolderType::Mbox;
    use Mail::Mailer;
    use Mail::Message;
    use MIME::Parser;
    use Net::SMTP;
    use Fcntl;
    use Getopt::Std;
    use File::Basename;
    use Mail::Box::Mbox;
    use Mail::MboxParser;

    my $email;
    my $user;
    my $temp;
    my $next = "";
    my $where = "";
    my $next2 = "";
    my $where2 = "";
    my $dirname;
    my $dirname2;
    my $tempword;
    my $flagset = 0;
    my $count = 0;
    my $text2;
    my $test_pos2;
    my $subject;
    my @messages2;

    my $parseropts = {
        enable_cache    => 1,
        enable_grep     => 1,
        cache_file_name => 'mail/cache-file',
    };

    #-------------------------------------------------------------------------------

    @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
    @weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
    ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
    $year = 1900 + $yearOffset;
    $theTime = "$hour:$minute:$second, $weekDays[$dayOfWeek] $months[$month] $dayOfMonth, $year";

    system ("mkdir /tmp/mail_output");
    system ("mkdir /tmp/attachments");

    print "Mbox to Zimbra message migration script. Started at $theTime\n";
    print "-------------------------------------------------------------------------------\n"; 

    # Begin reading through the user email subfolders

    if (-d "/tmp/mail") {
      $where2 = "/tmp/mail/";
    } else {
      $where2 = "/tmp/mail/";
    }

   while (defined($next2 = <$where2/*>)) {

   $user = basename($next2);

   $text2 = $user;
   $test_pos2 = index $text2,".";

   if ($test_pos2 == "1") {
     
     $user = basename($next2);
     $email = $user."\<my domain goes here- for cosmetic purposes>";

    print "\nProcessing messages for user: $email\n";

    #-------------------------------------------------------------------------------

    # Process files in current directory, replace spaces with underscores for processing

    opendir(DIR, "/tmp/mail/$user/mail") or die $!;
    my @files = readdir(DIR);
    close(DIR);

    for (@files) {
    next if -d;
    next if /^\./;

    my $new_name = $_; 
    $new_name =~ s/ /_/g;
    rename("/tmp/mail/$user/mail/$_" , "/tmp/mail/$user/mail/$new_name") or die $!;
    } 

    #-------------------------------------------------------------------------------
   
    # Setup directory to store converted mail, begin loop to read through mail
    # in user's folder

    system ("mkdir /tmp/$user");

    if (-d "/tmp/mail/$user/mail/") {
      $where = "/tmp/mail/$user/mail/";
    } else {
      $where = "/tmp/mail/$user/mail/";
    }

    while (defined($next = <$where/*>)) {

    $dirname = basename ($next);
  
        my $folder2 = Mail::MboxParser->new($next, 
                                    decode     => 'ALL',
                                    parseropts => $parseropts);

   #-------------------------------------------------------------------------------

   # Tests to see if the file is a valid mail file, sets a flag if it is

   my $i=0;
   my $text;
   my $test_pos;
   $flagset = 0;

   print "Processing mail file: $dirname\n";

   open (mailfile, "$next")|| die ("Could not open file <br> $!");
   $text = <mailfile>;
   $test_pos = index $text,"F";

    if ($test_pos == "0") {
     $flagset = 1;
     close mailfile;
   }

    if ($test_pos != "0"){
     print("Not a mail file, skipping...\n");
     close mailfile;
   }
    
   #---------------------------------------------------------------------------------

   # If the file has been flagged a mail file, process it
 
   if ($flagset == "1") {
     
    system ("mkdir /tmp/$user/$dirname");
    system ("/opt/zimbra/bin/zmprov -z selectMailbox $user cf /$dirname");
    $count = 0;

  # For every message in the mail file, print the subject, output a text file and add to Zimbra
 
    for my $msg ($folder2->get_messages)
    {
    $count ++;
    $subject = $msg->header->{subject};
    print "Processing message: $subject\n";
    $msg->store_all_attachments(path => '/tmp/attachments');
    $temp = $msg;
    
    open MAILDUMP, ">/tmp/$user/$dirname/mail_$dirname$count.txt";
    print MAILDUMP $temp;
    print MAILDUMP "****END OF MESSAGE****";
    close MAILDUMP;

    system ("/opt/zimbra/bin/zmmailbox -z -m $user addmessage  /$dirname /tmp/$user/$dirname/mail_$dirname$count.txt");

    print "----Done processing message, stored in mail_$dirname$count.txt----\n\n";

    }   

   }
 
 }
 
 print "----Done processing messages for user $email----\n\n";
 print "-------------------------------------------------------------------------------\n";


 # If a folder is not a mail folder, skip it

 }

   if ($test_pos2 != "1"){
    print("$text2 is not a mail folder, skipping...\n");
   }

}

    ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
    $year = 1900 + $yearOffset;
    $theTime = "$hour:$minute:$second, $weekDays[$dayOfWeek] $months[$month] $dayOfMonth, $year";

     print "----Done processing all messages, finished at $theTime----\n";


# EOF
Hope this is useful to someone.

Last edited by boris007 : 09-07-2007 at 12:15 AM. Reason: Update to issue
Reply With Quote