#!/usr/bin/perl
#
# By Phil2k@gmail.com ( http://phil.ro/ )
#
# Syntax: mailbox2maildir.pl < mailbox
#  creates maildir structure of directories ( in curent path ): cur/new/tmp, and places one file per message in one of them
# 


use POSIX qw(mktime uname);

@uname = POSIX::uname();
$hostname=$uname[1];

@months=("jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec");
%status_flags=( # flags conversions from sendmail's Status header to Maildir (DJB), no status = new message ( will be placed in "new" directory )
  "F" => "F", # Flagged
  "A" => "R", # Answered/Replied
  "R" => "S", # Read/Seen
  "D" => "T", # Deleted/Trashed
  "O" => "", # Old (not new) => message will not be placed in "new" subdir, but in "cur" subdir !
  "T" => "D", # Draft
  "P" => "P", # Passed (Resent/Forward/Bounced)
  );
@maildir_dirs=("new", "cur", "tmp");

foreach $dir (@maildir_dirs) {
  if (!-d $dir) {
    mkdir($dir);
    }
  }

select STDERR; $| = 1;      # make unbuffered
select STDOUT; $| = 1;      # make unbuffered
                    

#$headers_flag=1;
#$message_flag=0;
$from="";
$status="";
$xstatus="";
$keywords="";
$xuid="";
$mess="";
$time=undef;
$line_cnt=0;
$cnt=0;
while($line=<STDIN>) {
  $line_cnt++;
  #if ($line_cnt==205) {
  #  print "$headers_flag $message_flag $from: $line\n";
  #  exit(1);
  #  }
  #if ($headers_flag) {
    if ($line=~/^From\s(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\d+)/) {
      $new_from=$1;
      $swday=$2;
      $smonth=$3;
      $mday=$4;
      $hour=$5;
      $min=$6;
      $sec=$7;
      $year=$8;
       
      if (length($from)) {
        &do_message();
        }
      $from=$new_from;
        
      $mon=&in_array($smonth, \@months);
      if (!defined($mon)) {
        print STDERR "Invalid month name ($smonth) in: $line";
        next;
        }
      $time = mktime($sec, $min, $hour, $mday, $mon, $year-1900);
      next; # don't store this line
      }
    if (length($from)) {
      if ((!length($status)) && ($line=~/^Subject:(.*)/i)) {
        $subject=&trim($1);
        next; # skip this line
        }
      elsif ((!length($status)) && ($line=~/^Status:(.*)/i)) {
        $status=&trim($1);
        next; # skip this line
        }
      elsif ((!length($xstatus)) && ($line=~/^X-Status:(.*)/i)) {
        $xstatus=&trim($1);
        next; # skip this line
        }
      elsif ((!length($keywords)) && ($line=~/^X-Keywords:(.*)/i)) {
        $keywords=&trim($1);
        next; # skip this line
        }
      elsif ((!length($xuid)) && ($line=~/^X-UID:(.*)/i)) {
        $xuid=&trim($1);
        next; # skip this line
        }
      elsif ($line=~/^\s*$/) { # empty line => end of headers
        $headers_flag=0;
        $message_flag=1;
        }
      }
  #  }
  #elsif ($message_flag) {
  #  if ($line=~/^\s*$/) { # empty line => maybe end of message
  #    $headers_flag=1;
  #    $message_flag=0;
  #    }
  #  }
  
  if (length($from)) {
    $mess.=$line;
    }
  }
if (length($from)) {
  &do_message();
  }
  
exit(0);  


sub in_array {
  my ($element, $ref_array)=@_;
  my $i;
  $element=lc($element);
  for($i=0;$i<=$#$ref_array;$i++) {
    return $i if ($element eq $ref_array->[$i]);
    }
  return undef;
  }

sub do_message {
  $status.=$xstatus;
  print "Message: from=$from time=$time status=$status keywords=$keywords uid=$xuid\n";
  $cnt++;
  if (($cnt eq 1) && (($from eq "MAILER_DAEMON") || ($subject eq "DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA"))) {
    print "Skipping fist message used by sendmail internal data.\n";
    } else {
    $mess=~s/\n\s*\n$/\n/sg; # strip last line
    my $size = length($mess);
    my $i;
    my $path;
    my $filename;
    local *FILE;
    
    # generate file-name
    %flags=();
    $flags_str="";
    for($i=0;$i<length($status);$i++) {
      $c=substr($status, $i, 1);
      if (exists($status_flags{$c})) {
        $c=$status_flags{$c};
        if (!exists($flags{$c})) {
          $flags{$c}=1;
          $flags_str.=$c;
          }
        }
      }
    if (scalar(keys %flags)) {
      $path="cur";
      } else {
      $path="new";
      }
    #$filename=$path."/".time().".".$$."_".$cnt.".".$hostname.",S=".$size.":2,".$flags_str;
    $filename=$path."/".(defined($time)?$time:time()).".".$$."_".$cnt.".".$hostname.",S=".$size.":2,".$flags_str;
    print "Writing $filename ... ";
    
    open FILE, ">$filename";
    print FILE $mess;
    close FILE;
    
    if (defined($time)) {
      utime $time, $time, $filename;
      }
    print "done\n";
    }
  
  # clear message info:
  $from="";
  $time=undef;
  $status="";
  $xstatus="";
  $keywords="";
  $xuid="";
  $mess="";
  }

sub trim() {
  my $str=$_[0];
  
  $str=~s/^\s+//;
  $str=~s/\s+$//;
  return $str;
  }