Skip to content

Instantly share code, notes, and snippets.

@alexfouche
Created January 4, 2020 19:03
Show Gist options
  • Save alexfouche/9f48d19785a005d56de7e225da372cd1 to your computer and use it in GitHub Desktop.
Save alexfouche/9f48d19785a005d56de7e225da372cd1 to your computer and use it in GitHub Desktop.
Import all the messages from many mailboxes (also the ones in subfolders) into one maildir mailbox, into named folders
#!perl
use common::sense;
#use feature qw(say);
use Mail::Box::MailDir;
use Mail::Box::Manager;
use Config::General qw(ParseConfig SaveConfig);
use Date::Manip qw(UnixDate Date_Cmp);
use Getopt::Std;
#
# Parse options
#
my %opts = ();
getopts('c:s:d:v', \%opts);
unless ($opts{s} && $opts{d} ) {
say "Usage:";
say "[-c <config_file_path>] -s <source_mailbox_folderdir> -d <destination_imap_folder> [-v]";
say 'If no config file, take "~/.transfer_mail_to_folders.conf" as default';
exit 1;
}
my $config_file = glob ( ($opts{c}) ? $opts{c} : "~/.transfer_mail_to_folders.conf" );
my $source_mailbox_folderdir = $opts{s};
my $dest_imap_folder = $opts{d};
my $verbose = 1 if ($opts{v});
#
# Parse config file
#
my %conf=();
my $timestamp_name = "timestamp_$dest_imap_folder";
unless(-f $config_file && (%conf = ParseConfig($config_file) ) && defined $conf{destination_maildir} ) {
$conf{destination_maildir} = "~/.transfer_mail_maildir";
$conf{$timestamp_name} = "Jan 1 00:00:00 1973";
SaveConfig($config_file, \%conf);
print "No configuration was found in file $config_file\n";
print "A sample configuration has been generated and stored in $config_file\n";
print " If it is not what you wanted, delete $config_file and modify the \$config_file variable in this script.\n";
exit 2;
}
if (!defined $conf{$timestamp_name} || Date_Cmp($conf{$timestamp_name}, "Jan 1 0:0:0 1971") <=0 ) {
$conf{$timestamp_name} = "Jan 1 0:0:0 1973";
SaveConfig($config_file, \%conf);
}
#
# Process mailbox
#
my $stopped_at_timestamp=UnixDate($conf{$timestamp_name},"%s") ;
my $new_stop_timestamp=$stopped_at_timestamp;
my $s_mgr = Mail::Box::Manager->new;
sub process_mailbox_folders {
my ($inbox,$outbox, $sub_name,$is_sub) = @_;
# safeguard
#return if ($sub_name eq 'INBOX');
my ($insub,$outsub);
if ($is_sub == 0) {
$insub = $s_mgr->open(folder => glob($source_mailbox_folderdir), access => 'r', save_on_exit => 0);
$outsub = Mail::Box::Maildir->new(folderdir => glob( $conf{destination_maildir}), folder => "=$dest_imap_folder", access => 'rw', create=>1, save_on_exit => 1);
}else{
$insub = $inbox->openSubFolder($sub_name, access => 'r', save_on_exit => 0);
$outsub = $outbox->openSubFolder($sub_name);
}
foreach my $msg ($insub->messages) {
my $msg_timestamp = $msg->timestamp;
next if ($msg_timestamp <= $stopped_at_timestamp);
print "$msg_timestamp ". $sub_name .': ' . $msg->subject .'...' if ($verbose);
$msg->label(seen=>0);
$msg->labelsToStatus;
$msg->copyTo($outsub);
$new_stop_timestamp = $msg_timestamp if ($msg_timestamp>$new_stop_timestamp);
print "OK\n" if ($verbose);
}
process_mailbox_folders($insub, $outsub, $_, 1) foreach ($insub->listSubFolders(skip_empty=>1));
$outsub->close;
$insub->close(write => 'NEVER');
}
process_mailbox_folders('','','' ,0) ; # 0 means we need to open initial root folder (typically 'INBOX')
#
# Save timestamp and quit
#
print "Stopped at timestamp ". scalar( localtime $new_stop_timestamp) if ($verbose);
$conf{$timestamp_name} = localtime $new_stop_timestamp;
SaveConfig($config_file, \%conf);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment