#!/usr/bin/perl -w
# http://untroubled.org/mbox2maildir
# put into the public domain by Bruce Guenter <bruceg@em.ca>
# based heavily on code by Russell Nelson <nelson@qmail.org>, also in
# the public domain
# NO GUARANTEE AT ALL
#
# Creates a maildir from a mbox file

# version 0.00 - first release to the public.
# version 0.01 - generate better maildir-compatible filenames
#              - includes ,S=<size> in filename
#              - allow skipping of first message in mbox

use strict;
require 'stat.pl';

# Set this to 1 to ignore the first message in each mailbox
# ("folder internal data" which some mailservers generate)
my $skipfirst = 0;

sub error {
    print STDERR join("\n", @_), "\n";
    exit(1);
}

sub usage {
    print STDERR "usage: mbox2maildir <mbox file> <maildir> [ <uid> <gid> ]\n";
    exit(@_);
}

&usage(1) if @ARGV != 2 && @ARGV != 4;

my $mbox = $ARGV[0];
my $mdir = $ARGV[1];
my $uid = $ARGV[2];
my $gid = $ARGV[3];

&error("can't open mbox '$mbox'") unless
    open(SPOOL, "<$mbox");

-d $mdir || mkdir $mdir,0700 ||
    &error("maildir '$mdir' doesn't exist and can't be created.");
chown($uid,$gid,$mdir) if defined($uid) && defined($gid);
chdir($mdir) || &error("fatal: unable to chdir to $mdir.");
-d "tmp" || mkdir("tmp",0700) || &error("unable to make tmp/ subdir");
-d "new" || mkdir("new",0700) || &error("unable to make new/ subdir");
-d "cur" || mkdir("cur",0700) || &error("unable to make cur/ subdir");
chown($uid,$gid,"tmp","new","cur") if defined($uid) && defined($gid);

use vars qw($stamp $seq);
$stamp = time;
$seq = 1;
sub open_msg {
    my($flags,$msg) = @_;
    my $size = length($msg);
    my $fn;
    my $tmpnam = "tmp/$stamp.${$}_$seq.mbox";
    if($flags) {
        if($flags =~ /RO/) { $fn = "cur/$stamp.${$}_$seq.mbox,S=$size:2,S"; }
	elsif($flags =~ /O/) { $fn = "cur/$stamp.${$}_$seq.mbox,S=$size:2,"; }
	else { $fn = "new/$stamp.${$}_$seq.mbox,S=$size"; }
    } else {
        $fn = "new/$stamp.${$}_$seq.mbox,S=$size";
    }
    $seq++;
    open(OUT, ">$tmpnam") || &error("unable to create new message");
    chown ($uid,$gid,$tmpnam) if defined($uid) && defined($gid);
    print OUT $msg;
    close OUT;
    rename($tmpnam,$fn) || &error("unable to rename message");
}

my $in_header = 0;
my $flags = "";
my $msg;
my $mcount = 0;

while(<SPOOL>) {
    if(/^From /) {
        open_msg($flags, $msg) if $mcount > $skipfirst;
	$flags = "";
	$msg = "MBOX-Line: $_";   # or just $msg = "";
	$in_header = 1;
        $mcount++;
    } elsif($in_header) {
	if(/^\s+$/o) {
	    $in_header = 0;
            $msg .= "\n";
	} elsif (/^Status:\s*(\S+)/oi) {
            $flags = $1;
        } else {
            $msg .= $_;
        }
    } else {
        s/^>From /From /;
        $msg .= $_;
    }
}
close(SPOOL);
open_msg($flags, $msg) if $mcount > $skipfirst;
close(OUT);
