Created
June 25, 2012 22:30
-
-
Save growse/2991832 to your computer and use it in GitHub Desktop.
A way to incrementally upload a maildir to gmail's IMAP servers. Originally by Andreas Kammlott, with some changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
# by Andreas Kammlott, thanks to perl and its community | |
use IO::Socket::SSL; | |
use Data::Dumper; | |
use HTTP::Date qw(str2time); | |
use HTTP::Date qw(parse_date); | |
use Date::Format; | |
use Mail::IMAPClient; | |
use Mail::Box::Maildir; | |
use Mail::Message::Convert::MailInternet; | |
# Open imap connection, adjust values to your needs | |
my $imap = Mail::IMAPClient->new( | |
User => 'username', | |
Password => 'password', | |
Socket=>IO::Socket::SSL->new(Proto=>'tcp', | |
PeerAddr=>'imap.gmail.com', | |
PeerPort=>993) | |
) || die "Could not connect to IMAP server.\n"; | |
# A maildir contains a subdir "cur" | |
foreach my $dir (`find ./ -type d -name cur|sort`) { | |
my $imdir = "Inbox"; # to store the path on the server (imap-directory) | |
my $fsdir = ""; # to store the path of the maildir (filesystem) | |
# Bring the path to an array, each directory needs to be handled | |
my @fspath = split(/\//, $dir); | |
# Replace the leading point and the tailing .directory to acquire | |
# the path, which has to be created in imap, the "cur" don't need | |
# to be stored | |
for (my $i = 1; $i < @fspath-1; $i++) { | |
$fsdir = "$fsdir$fspath[$i]/"; | |
if ($fspath[$i] =~ /\..*\.directory/) { | |
$fspath[$i] =~ s/^\.(.+)\.directory$/$1/; | |
} | |
#$imdir = "$imdir$fspath[$i]/"; | |
} | |
# Create the mdir object, this object contains all the messages from | |
# the filesystem's maildir | |
my $mdir = Mail::Box::Maildir->new(folder => $fsdir, access => 'rw') | |
or print "Failed to create mdir object from \"$fsdir\"\n"; | |
# Process this directory only if it contains messages | |
if (!$mdir->messages() > 0) { | |
#print "Skipping... folder has been detected as empty.\n"; | |
next; | |
} | |
#print Dumper($imap->xlist_folders or die "could not get folder $!"); | |
#exit; | |
# Check for the folder on the server (imap) and create if necessary | |
if (!$imap->exists($imdir)) { | |
# Jump to next folder if creation of this one fails | |
if (!$imap->create($imdir)) { | |
print "ERROR: Could not create folder \"$imdir\".\n"; | |
next; | |
} | |
} | |
# Now begin to push all messages | |
foreach my $msg ($mdir->messages()) { | |
if ($msg->label(seen) eq 0) { | |
my $subject = $msg->subject; | |
my $msgdate = $msg->head->get('Date'); | |
my $msgid = $msg->messageId; | |
print $subject." - ".$msgid."\n"; | |
# Required date as RFC2060 dd-Mon-yyyy hh:mm:ss +0000 | |
# Provided format is Tue, 20 Jul 2004 09:55:16 +0200 | |
my $time = str2time($msgdate); | |
(undef, undef, undef, undef, undef, undef, $tz) = parse_date($msgdate); | |
my $date = time2str("%d-%h-%Y %H:%M:%S %z",$time,$tz) | |
or print "problem with time: $time and tz: $tz\n"; | |
# Create a converter object | |
my $conv = Mail::Message::Convert::MailInternet->new; | |
# Don't understand why the $conv->export($msg)->as_string() has to be called twice! | |
my $exp = $conv->export($msg)->as_string(); | |
if (!$imap->append_string($imdir, $conv->export($msg)->as_string(), undef, $date)) { | |
print "Failed to append message!\n" | |
."ID:$msgid\n" | |
."SUBJECT:$subject\n" | |
."IMAPDIR:$imdir\n" | |
."MESSAGEDATE:$msgdate\n" | |
."IMPORTDATE:$date\n\n"; | |
} else { | |
# Delete the message now that we've uploaded it. | |
$msg ->label(seen => 1) | |
} | |
} | |
} | |
} | |
$imap->close(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment