#!/usr/bin/perl -w # # kmx2mbox # version 1.0c 5/11/2001 # by: Daniel Mota Leite (higuita@gmx.net) - Portugal # tmp website: http://www.cadernoverde.com/~higuita/ # #---------------------------------------------------------------------------- #This program is protected by the GNU General Public License. Please see #http://www.gnu.org for information regarding the GNU General Public License. #---------------------------------------------------------------------------- # # this little perl script translates the uncompressed kmx mailboxes from # the great email client for window$, Kaufman Mail Warrior 3.61, to the # standard unix mbox. # Most emails clients can read/import this files. # # i made this because the MW was the only thing that force me to boot # to window$ to read my new email and find old emails in my big mailboxes # (fgrep and fetchmail/others could do this was not "easy" and practical) # MW cant work in wine and don't have any export email option and i didn't # want to have some emails in windows and others in Linux # with this i can get the email i get from window$ to Linux and use # the Linux as my main OS and window$ just for some games # Kaufman already said that he will make a Linux version of MW too, but # until it show up this is a easy way to share the MW emails with Linux # # kmx2mbox (name) read the kmx file with that name and writes one mailbox # file to the same dir with the name name.mbox without the .kmx # is up to the user to move and rename the mbox files to use then # ex: kmx2mbox Inbox.kmx will save the file to Inbox.mbox to the same dir # # # To use just make sure the the MW mailbox are uncompressed # (ie: you didn't ever used the compact command in MW) # if they are compressed, create a new mailbox and copy the emails # to that new mailbox and this time don't compact it. 8) # Then in Linux, copy the kmx files to a dir, place the kmx2mbox in that dir # or put it on the path, go to that kmx dir and run: # # for file in *.kmx; do kmx2mbox "$file"; done # # this will convert all the kmx files on the directory # # this is what the main idea from the script: # -search ^(?^@^@^@) -1 random character + 3 null characters at the start # of the line (i call this the start message code) # -ignore until the ++first++ *(!MW36_xMailBoundary)* is found (must ignore # this line too...this is the start email code ) # -Save the email until the next ^(?^@^@^@) is found # -start over again # of course there is small problems (codes), but i think i manage then all # # Known Bugs: # -it doesn't check to see if the name.mbox already exists # -cant rebuild the attach files (hey, search the attach folder, you have # the names at the end of each email # -cant work with compressed kmx # -i think this work only for MW 3.6x mailboxes (not sure) # -don't know if i got all the possible "start message" codes, if you get # any email inside other check to see what i miss... # for now it check for ?^@, ?^A to ?^E and ^^A # # i wrote many comments, this script should be easy to understand (i hope) # # Good luck and enjoy # $nome=shift; unless ($nome) {$nome=""}; $mbox=$nome; $mbox=~ s/.kmx/.mbox/i; $ok=0; $n=0; $i=0; @email=""; $from=""; $date=""; $from_ok=0; $date_ok=0; # protection against screw up files with no kmx extension # without this the script will overwrite all files without .kmx unless ( $nome=~ /.kmx/i) { print " $nome No kmx extension... Aborting\n"; exit; } print "Reading $nome\n\n"; # read the mailbox $nome open(DATA, "< $nome") || die("ERROR - can't open datafile: $!"); @msg=; close(DATA); # Open the file .mbox for write open(DATA , ">$mbox ") || die("ERROR - cant open datafile: $!"); foreach $linha(@msg) { #If found the end of the kmx mailbox, save and exit if ($linha =~ /^QIX/){ &save_exit; } # search for the start of the kmx (QDB) and for the start message codes # we will ignore the next lines (this one included) until the email start code below # when the start message code is found we save the previous email in mailbox format # and reset thing for the next one if ( ($linha =~ /^QDB/ || substr($linha,1,3) eq "\x00\x00\x00" || substr($linha,1,3) eq "\x01\x00\x00" || substr($linha,1,3) eq "\x02\x00\x00" || substr($linha,1,3) eq "\x03\x00\x00" || substr($linha,1,3) eq "\x04\x00\x00" || substr($linha,1,3) eq "\x05\x00\x00" || substr($linha,0,3) eq "\x01\x00\x00") && $ok ==0 ) { $ok=1; $from_ok=0; $date_ok=0; # escape for the first run if ( $i >0 ) { print DATA "\nFrom $from $date\nConverted: kmx2mbox\n"; print DATA @email; } $i=0; @email=""; } # if start of the message was already found (ok=1), start searching for the start # of email codes, then reset the ok code to allow the saving and count the emails found # there is another "start email code", the â@^@^@^@^@ from 7 to 13, but have # more variations elsif ( $ok==1 ) { # if ( $linha =~ /\xe2\x40\x00\x00\x00\x00/ || $linha =~ /\xe1\x40\x00\x00\x00\x00/ || $linha =~ /\xe0\x40\x00\x00\x00\x00/ ) { if ( $linha =~ /!MW36_xMailBoundary/ ) { $ok=0; $n++; print "$n "; } } # Clean the line of the email code if it have any newline code # any email shouldn't have null character (as far as i know) # also, the MW boundary text, so it doesn't show up in the email else{ unless( $linha =~ /\x00/ || $linha =~ /^!MW36_xMailBoundary/ ){ # we strip the carrier return from DOS !!! is this needed?!? # if you plan to use this mbox in window$, you might get better # results if you don't strip this code # for me this works fine with linux email clients $linha =~ s/\r//g; &check_headers; # save the email $email[$i]=$linha; $i++; } # remove the next attach codes and inserts a newline so the mbox knows where # the header finish elsif ( $linha=~/^!MW36_xMailBoundary/){ $email[$i]="\n"; $i++; } } } # shouldn't be needed, but might help in broken kmx, without the QDB end # like those TMP created when the MW crash, this could be a way to recover # the lost emails # i didn't test it yet &save_exit; ###### Modules ######## sub save_exit{ # the mbox format need a "\nFrom name date" at start of each email # the "converted" header is just to fix some incomplete headers # i had only one very old kmx mailbox that had this problem # this helps this emails and doesnt do anything for the others print DATA "\nFrom $from $date\nConverted: kmx2mbox\n"; print DATA @email; close(DATA); print "\n\nConverted $n emails to mbox $mbox\n\n"; exit; } # check the From, Date and Content-Type: multipart (there is no attach, # this can screw some email clients) sub check_headers{ if ($linha =~ /^From: /i && $from_ok==0) { $from= $linha; $from=~ s/^From: //i; $from=~ s/\n//; $from_ok=1; } elsif ($linha =~ /^Date: /i && $date_ok==0) { $date= $linha; $date=~ s/^Date: //i; $date=~ s/\n//; $date_ok=1; } elsif ( $linha=~ /^Content-Type: multipart/i) { $linha=~ s/^Content-Type: multipart/encode-/i; } }