<?xml version="1.0" encoding="windows-1252"?>
<node id="535127" title="Mirror/Copy Mozilla thunderbird emails to IMAP server" created="2006-03-08 04:40:17" updated="2006-03-07 23:40:17">
<type id="1748">
sourcecode</type>
<author id="80839">
davis</author>
<data>
<field name="doctext">
&lt;code&gt;
use warnings;
use strict;
use Data::Dumper;
use Mail::MboxParser;
use Mail::IMAPClient;


my $base_dir    = ".thunderbird/profile_path/Mail/Local Folders/";
my $imap_server = "localhost";
my $imap_user   = "username";
my $imap_pass   = "password";
my $parseropts = {
        enable_cache    =&gt; 0,
        enable_grep     =&gt; 0,
        cache_file_name =&gt; 'cache-file',
};

my $skip_deleted = 1;

my $imap = Mail::IMAPClient-&gt;new(
                        Server   =&gt; $imap_server,
                        User     =&gt; $imap_user,
                        Password =&gt; $imap_pass,
)       or die "Cannot connect to $imap_server as $imap_user: $@";

parse_dir($base_dir);

sub parse_dir {
        my $dir = shift;
        opendir my $dir_h, $dir
                or die "Unable to opendir $dir: $!\n";
        print "Reading directory $dir\n";


        ##Dirty, probably IMAP-server dependent stuff.
        #This stuff is for dovecot.
        my $temp_dir = $dir;
        $temp_dir =~ s!\.sbd!!g;
        $temp_dir =~ s!^$base_dir!!;
        $temp_dir =~ s!^/!!;
        $temp_dir =~ s!/!.!g;
        print "Making dir $temp_dir\n";
        $imap-&gt;create($temp_dir);

        foreach my $directory (grep /\.sbd$/, readdir $dir_h) {
                parse_dir($dir."/".$directory);
        }
        seekdir($dir_h, 0);
        foreach my $mail_file (grep !/^\./, grep !/(\.html|\.sbd|\.msf|\.dat)$/, readdir $dir_h) {
                my $mf = $dir."/".$mail_file;
                $mf =~ s!//+!/!g;
                print "Going to parse $mf\n";
                my $mb = Mail::MboxParser-&gt;new($mf,
                                                decode     =&gt; 'ALL',
                                                parseropts =&gt; $parseropts);
                for my $msg ($mb-&gt;get_messages) {
                        #Skip deleted messages...
                        my $folder_name = $temp_dir.".".$mail_file;
                        $folder_name =~ s!//+!/!g;

                        unless($skip_deleted and (hex($msg-&gt;header-&gt;{"x-mozilla-status"}) &amp; 0x0008)) {
                                print "Appending msg " . $msg-&gt;header-&gt;{subject} . " to $folder_name\n";
                                $folder_name =~ s/^\.//;
                                $imap-&gt;create($folder_name)
                                        or warn "unable to create $folder_name: $@\n";
                                unless($imap-&gt;append_string($folder_name, $msg)) {
                                        warn "Couldn't append " . $msg-&gt;header-&gt;{subject} . " to $folder_name: $@\n";
                                        warn "Skipping\n";
                                        next;
                                }
                        } else {
                                warn "Skipping " . $msg-&gt;header-&gt;{subject} . " - deleted message\n";
                        }

                }
        }
        closedir($dir_h);

}



&lt;/code&gt;</field>
<field name="codedescription">
&lt;p&gt;
This script works on Mozilla Thunderbird email stores, and attempts to upload the emails to an IMAP server. Right now, it's not finished, in that it doesn't upload the top-level emails (ie mails from Inbox, Sent etc). It handles subfolders of those just fine.
&lt;/p&gt;
&lt;p&gt;
There's slso some dirty hackery to munge folder paths for dovecot. YMMV
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Update:&lt;/strong&gt; Fixed now, ie it correctly parses email in top-level folders. I'd still call it a quick-and-dirty script though.
&lt;/p&gt;
</field>
<field name="codecategory">
E-Mail Programs</field>
<field name="codeauthor">
/msg davis</field>
</data>
</node>
