#!/usr/bin/perl
#
# $Id: mboxconvert.pl,v 1.4 2003/07/28 12:27:49 eric Exp $
#
# Simple utility for converting mailbox files into maildir format.
#
# -- Eric Jansen <eric@xyrion.org>
#

use strict;
$| = 1;
umask 077;

# Define some variables we're going to use.
my ($body, $filename, $header, $hostname, $id, $mailbox, $maildir, $mb_flags, $md_flags, $msg_num, $time, @dirs);

# Did the user understand our syntax or shall we display a little info?
if($#ARGV == 1) {

	($mailbox, $maildir) = @ARGV;
}
else {

	print "Usage: $0 <mailbox> <maildir>\n";
	exit;
}

# Does the mailbox we're about to convert actually exist?
if(-e $mailbox) {

	print "$mailbox exists... ";
	-r $mailbox or die "no read permission.";
	print "ok\n";

	open MBOX, $mailbox;
}

# Check/create target maildir.
@dirs = ($maildir, "$maildir/cur", "$maildir/new", "$maildir/tmp");
foreach my $dir (@dirs) {

	if(-e $dir) {

		print "$dir exists... ";
		-w $dir or die "no write permission.\n";
		print "ok\n";
	}
	else {

		print "$dir does not exist, creating... ";
		mkdir $dir or die "failed: $!\n";
		print "done\n";
	}
}

# Get our hostname and strip out invalid characters.
$hostname = `hostname`;
$hostname =~ s/[^\w\.]+//g;

# Does the mailbox start with a message like it should?
<MBOX> =~ /^From / or die "Corrupt mailbox file.\n";

# Everything still ok, so let's convert the mail then.
print "Converting mail";

$msg_num = 0;

while(!eof MBOX) {

	# We need these variables inside the loop.
	my ($header, $body, $mb_flags, $md_flags) = ('', '', '', '');

	# Read the header of the message.
	while(<MBOX>) {

		last if /^$/;

		# Collect any status-flags found for later use.
		$mb_flags .= $1 if /^(?:X-)?Status: ([A-Z]+)/;

		# This mail is no longer needed, we convert it and mark it for deletion.
		$mb_flags .= 'D' if /^Subject: DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA$/ and $msg_num == 0;

		$header .= $_;
	}

	# Read the body of the message.
	while(<MBOX>) {

		last if /^From /;

		# No need to escape this when using maildir.
		s/^[ >](From)/$1/;

		$body .= $_;
	}

	# Create a filename for the message.
	$time = time();
	$id = sprintf("%d_%d", $$, ++$msg_num);

	# New messages should go to a different folder, so have we already seen this one?
	if($mb_flags =~ /[RO]/) {

		# Now take a look at the collected flags, we need to put the status info in the filename.
		$md_flags .= 'F' if $mb_flags =~ /F/;		# Flagged
		$md_flags .= 'R' if $mb_flags =~ /A/;		# Replied
		$md_flags .= 'S' if $mb_flags =~ /[RO]/;	# Seen		
		$md_flags .= 'T' if $mb_flags =~ /D/;		# Trashed

		# Already seen messages go to the cur/ folder with their flags appended to the file name.
		$filename = "$maildir/cur/$time.$id.$hostname" . ($md_flags ne '' ? ":2,$md_flags" : '');
	}
	else {

		# No need to check for flags on new messages, just put them in the new/ folder.
		$filename = "$maildir/new/$time.$id.$hostname";
	}

	# Just do a quick check to make sure we're not overwriting anything.
	!-e $filename or die "Perls rand() function doesn't look very random to me on this machine, aborting.\n";

	# And finally, write the mail.
	open FILE,">$filename";
	print FILE "$header\n$body";
	close FILE;

	if($msg_num % 10 == 0) {

		print $msg_num;
	}
	elsif($msg_num % 2 == 0) {

		print ".";
	}
}

print $msg_num == 1 ? " 1 message, done\n" : " $msg_num messages, done\n";
close MBOX;
