This week-end, after passing too much time to try to understand contact management in KMail (which was working quite well in KDE 3.x but is completely flawed IMHO in KDE 4.x), I decided with my wife it was time after 8+ years to try another mail reader.
Thunderbird was of course the first candidate, due to the familiarity she had with Firefox, Outlook (at school) and the fact it’s not that different from KMail anyway in its behavior and interface. I must say I was impressed to see my wife just say that she didn’t mind changing Mail reader, in order to get lacking features. Probably her familiarity with Open Source has also created an open mind for computing programs, and the fact she already uses multiple tools without major issue, makes her willing to try new ones.
So I started to work migrating her data from KMail to TB. I found a small program in order to help md2mb.pl. However, it was far from being complete, and I decided to rewrite a new one, based on the ideas from the other one, in order to have a better migration support. So here is a new md2mb.pl which hopefully will be useful for others as well.
#!/usr/bin/perl -w
#
# Program to import a maildir kmail environement into a thunderbird one.
# (c) Bruno Cornec under the GPLv2.
use strict;
use File::Find;
use File::Copy;
use File::Basename;
use File::Path;
my $cmd="formail";
# CHANGE AS YOU WISH
my $oldroot = "/beatrice/.Mail.sav";
my $newroot = "/beatrice/.thunderbird/30cq2rn3.default/Mail/Local Folders/";
# Is the newroot a file (1) or a dir (0)
my $nrisfile = 0;
my $debug = 0;
# END CHANGE
$debug++ if ((defined $ARGV[0]) && ($ARGV[0] eq "-v"));
print "DEBUG MODE, not doing anything, just printing\n" if ($debug);
if ($debug) {
print "CMD1: mkdir -p $newroot\n" if ((not -d "$newroot") && (not $nrisfile));
} else {
mkpath("$newroot",0, 0755) if ((not -d "$newroot") && (not $nrisfile));
}
system("$cmd /dev/null 2>/dev/null") == 0 or die "cannot find formail on your \$PATH!\nAborting";
find(\&md2mb,($oldroot));
sub md2mb {
if (-f $File::Find::name) {
return if (
($File::Find::name =~ /\.ids$/) ||
($File::Find::name =~ /\.sorted$/) ||
($File::Find::name =~ /\.index$/) ||
($File::Find::name =~ /\/cur\//) ||
($File::Find::name =~ /\/new\//) ||
($File::Find::name =~ /\/tmp\//));
}
if (-d $File::Find::name) {
return if (
($File::Find::name =~ /\/cur$/) ||
($File::Find::name =~ /\/new$/) ||
($File::Find::name =~ /\/tmp$/));
}
if ($debug) {
print "CURR: $File::Find::name\n";
}
my $destname = $File::Find::name;
$destname =~ s|^$oldroot||;
$destname =~ s|\.([[:alnum:]éèçàù\s]*)\.directory|$1.sbd|g;
if ($debug) {
print "DEST: $destname\n";
}
my $cdir = dirname("$newroot/$destname");
my $outputfile="$newroot/$destname";
$outputfile="$newroot" if ($destname =~ /^\s*$/);
if (-d $File::Find::name) {
my @files = (,);
if (@files) {
if ($debug) {
print "CMD2: mkdir -p $cdir\n" if (not -d "$cdir");
} else {
mkpath("$cdir",0, 0755) if (not -d "$cdir");
}
}
foreach my $file (@files) {
next unless -f $file; # skip non-regular files
next unless -s $file; # skip empty files
next unless -r $file; # skip unreadable files
$file =~ s/'/'"'"'/; # escape ' (single quote)
# NOTE! The output file must not contain single quotes (')!
my $run = "cat '$file' | $cmd >> '$outputfile'";
if ($debug) {
print "CMD3: $run\n";
} else {
print "Copying maildir content from $File::Find::name to $outputfile\n";
system($run) == 0 or warn "cannot run \"$run\".";
}
}
}
if (-f $File::Find::name) {
if ($debug) {
print "CMD2: mkdir -p $cdir\n" if (not -d "$cdir");
print "CMD3: cp $File::Find::name $cdir\n";
} else {
mkpath("$cdir",0, 0755) if (not -d "$cdir");
copy($File::Find::name,$cdir);
print "Copying mailbox content from $File::Find::name to $outputfile\n";
}
}
}
Warning: this code doesn’t work from the blog as wordpress makes some modifications, so download it from here
Run it first with a -v option in order to see what will be done. Be careful as I’ve just fixed the problems I had on my side, but probably not all of them. Especially, take care of file names with “‘” in them. they won’t work well.
So migration has been done, and of course more re-organization of the mailboxes. But now everything works fine, including contact management (that were imported using the LDIF exchange format).
And my wife has already sent a couple of mails, so I guess it will not take her long to be very familiar with TB.
Once again this shows all the power of FLOSS: freedom of choice, no info hidden, open format, and voilà.
Tags: Linux, perl, script, Thunderbird
2011/01/10 at 16:17 |
[...] Migrating from KMail to Thunderbird [...]
2011/01/10 at 22:12 |
[...] This post was mentioned on Twitter by Dr. Roy Schestowitz, Chad Martin. Chad Martin said: Migrating from KMail to Thunderbird: Migrating from KMail to ThunderbirdThunderbird/Icedove – mail/news client w… http://bit.ly/fNkXZv [...]
2011/02/07 at 20:51 |
This may be the tool I’ve been looking for. When I tried to run it, I got the following (note: I added some blank lines for readbility, so the line number below does not match above):
./md2mb.pl -v
syntax error at ./md2mb.pl line 69, near “(,”
Execution of ./md2mb.pl aborted due to compilation errors.
The line in question is:
my @files = (,);
2011/02/09 at 00:58 |
Inded the script is modified by WordPress
the full correct version is availbale here: http://trac.project-builder.org/browser/projects/md2mb/devel/md2mb/bin/md2mb.pl
Thanks for the feedback.
2011/02/09 at 02:00
Thanks for the link to the correct version. I hope I have some time tomorrow to try it out.
I can’t believe nobody has written one of these before. I have been searching for some time for a migration solution. I switched from Thunderbird to Kmail, but am finding some flaky behaviour with kmail that is frustrating.
2011/02/09 at 21:08
Hmm. Still not working for me.
Line 53 has some strange characters, even in the the download, buy I’m not sure that’s the problem.
I modified $oldroot and $newroot as follows:
my $oldroot = “/home/kevin/.kde/share/apps/kmail/mail”;
my $newroot = “/home/kevin/mailtools/Export/”;
Running with -v for debug I see a number of CURR and DEST lines printed with sensible values. There or no output lines in the debug run containing CMD which means none of the commands that do the work will be executed.
I inserted some print statements to see which sections of code were executing. The program does enter the
if (-d $File::Find::name)
section around line 60 but never enters the
if (@files)
block at line 62 or
foreach my $file (@files)
block at line 70.
Also the
if (-f $File::Find::name)
block at line 84 is never entered.
2011/02/10 at 02:01
Line 53 contains in fact some french accented char éè… So I think you can just remove them on your side.
If you use -v, commands are just printed, and not executed.
lines in 62 are only valid for directories and 84 for files. So if none of the blocks are entered in , it means that it doesn’t find anything in your oldroot.
Could you share the log in debug mode ? (send it by mail: bruno_at_hyper-linux-dot-org) as well as a unix find in the same dir to compare.
2011/02/14 at 15:08 |
Hi Bruno,
I already use Thunderbird, but for user switching from Kmail it’s a good idea (and a good tool I guess).
For french people, through the “download” link (http://trac.project-builder.org/browser/projects/md2mb/devel/md2mb/bin/md2mb.pl), click “Original Format” in order to get the script with the french accents ok ; otherwise line 53 the accents are not ok (through “Plain Text” we get some Ã).
2011/08/10 at 22:10 |
Doesn’t work with spaces in folder names. I use
my @files = (bsd_glob(“$File::Find::name/cur/*”),bsd_glob(“$File::Find::name/new/*”));
to work around that.
2011/08/22 at 02:51 |
Hello Markus
On which platform are you ? On Linux I didn’t get that problem, as I remember that some of the folders of my family users had space in them.
More over I use ‘ when calling the system command to avoid problem. Could you activate logging so I can see what is hapenning ?
2011/11/24 at 19:01
There are problems with this line on linux. Not all files are found. I did a lot of debug, but in some cases I lose E-Mails with your converter.
2011/11/25 at 01:03
I agree. I also found some cases where mail wasn’t migrated correctly. As I plan to migrate my daughter soon, I’ll review and try to fix it.
2011/09/29 at 13:21 |
Hi,
sorry I am not very keen in this. Since Kmail does not work properly anymore on ubuntu without KDE environment, I want definitely to shift to Thunderbird.
I modified this:
my $oldroot = “/home/rossi/.kde/share/apps/kmail/mail”;
my $newroot = “/home/rossi/.thunderbird/wi5scsdd.default/Mail/Local Folders”;
but I get this:
./md2mb.pl -v
DEBUG MODE, not doing anything, just printing
cannot find formail on your $PATH!
Aborting at ./md2mb.pl line 27.
what shall formail be?
/dev/null is there.
Thanks for the help
Andrea
2011/09/30 at 00:10 |
formail is a command provided by the procmail package, which is used to reformat correctly the mail. apt-get install procmail should help.
2011/09/30 at 15:35 |
Thanks Bruno, now it is working for the main folder, but not for the subfolders in kmail, which have hidden subfolders too. well thanks anyway
cheers
Andrea
2011/10/10 at 08:47 |
I also want import subfolder directory ..is possible?
Thx
2011/10/10 at 09:01 |
Ok ..i found fast solution
http://dcwww.camd.dtu.dk/~schiotz/comp/kmail2thunder.html
2012/01/08 at 01:49 |
[...] migrating 2 of my kids and my wife from Kmail to Thunderbird last year, I finally decided this week-end to [...]
2012/01/08 at 01:51 |
I have now fixed the script to support most cases as explained in this new blog entry http://brunocornec.wordpress.com/2012/01/08/migrating-from-kmail-to-thunderbird-the-revenge/
2012/01/08 at 13:59 |
Great tool.
I was looking for a Kmail to Thunderbird converter for a long time for the same reason as you.
Thanks a lot for your work.
2012/01/19 at 21:17 |
I also needed to convert a kmail maildir to thunderbird, but ended up rewriting the script quite a bit, to make it work with nested folders.
The modified script follows below:
(Notice: Option “-v” is verbose, “-d” is dry-run )
#!/usr/bin/perl -w
#
# Program to import a maildir kmail environement into a thunderbird one.
#
# Released under the GPLv2 or the Artistic license at your will.
use strict;
use warnings;
use File::Find;
use File::Basename;
use File::Path;
use IPC::Run qw(run);
#use File::Glob ‘:glob’;
my $cmd=”formail”;
# CHANGE AS YOU WISH
my $oldroot = “/home/someuser/.kde4/share/apps/kmail/mail”;
my $newroot = “/home/someuser/.thunderbird/123f0puf.default/Mail/Local Folders/”;
$newroot =~ s|/?$|/|; # Make sure new root ends in /
my $verbose = 0;
my $dryrun = 0;
# END CHANGE
$verbose++ if @ARGV && $ARGV[0] eq “-v”;
$dryrun++, $verbose++ if @ARGV && $ARGV[0] eq “-d”;
system(“$cmd /dev/null 2>/dev/null”) == 0 or die “cannot find formail on your \$PATH!\nAborting”;
find(\&md2mb,($oldroot));
sub md2mb {
my $name = $File::Find::name;
return if $name =~ /\.(ids|sorted|index)$/;
return if -d $name; # skip directories
return unless -f _; # skip non-regular files
return unless -s _; # skip empty files
return unless -r _; # skip unreadable files
my $dest = $name;
$dest =~ s%^\Q$oldroot\E/?%$newroot% # Target name is under a different root dir
or die “Old root ‘$oldroot’ not found in path: $dest\n”;
$dest =~ s%/(old|new|cur)/[^/]+$%%; # Target does not have old/cur/new indications
$dest =~ s%\.([^/]+)\.directory(/.*$)%$1.add_sbd($2)%ge; # Remove .directory and add .sdb to all folders below
$dest =~ s%/inbox([./])%/Inbox$1%;
print “TRANSFER $name => $dest\n” if $verbose;
return if $dryrun;
my $destdir = dirname( $dest );
mkpath( $destdir, 0, 0755 ) unless -d $destdir;
run([$cmd], “>”, $dest);
}
sub add_sbd {
my $rest = shift;
$rest =~ s%/%.sbd/%g;
return $rest;
}
2012/01/21 at 11:32 |
You should look at th current version described in http://brunocornec.wordpress.com/2012/01/08/migrating-from-kmail-to-thunderbird-the-revenge/ as it fixed also the nested dirs.
2012/01/23 at 00:14 |
Hi Bruno,
Thank you very much for this useful tool. The most current version today (1391) had small issues with subfolders. My folders were all outside the InBox and In the verbose output I saw extra forward slashes before the top level folder. Nevertheless, with a little bit of fiddling I was able to import the created mbox files to Thunderbird and wave Kmail2 goodbye.
2012/01/23 at 01:45 |
Normally the extra ‘/’ are not an issue. Linux supports file name like dir///file without problem. Let me know if there is something else that needs to be fixed (or share a patch
)