Python script to recover shift-end-deleted mails from Thunderbird inbox file

The Bad

Until recently I was having a bad behavior. I found it easy to delete stuffs from my pc by using shift-delete instead of regular delete. And I learnt my lesson.

Every day at work, I spend some quality time dedicated to filter out my inbox from the unwanted invitations to join ‘Daily frogs'

After years of experience, I had mastered the art of detecting spam only by looking at the subject and senders line. Last Monday morning, I had deleted some of the daily spam from my inbox. Things we so natural.

But later that day, I realized that, during the process of pressing the ‘delete’ key, I had accidentally pressed the ‘End’ key also!!!! so the whole thing became, ‘click’ and then ‘Shift-End-Delete’ and then ‘Enter’, so that every message from the beginning to end was gone in 60 seconds.
I just closed the Thunderbird in panic. :-/

But, Thunderbird is no beast a match for my Python skills!!

I am sharing my lazy Python script that I have managed to scramble to recover my Inbox.
This peice of cake, sorry code, is released under GPL.


 #!/usr/bin/python --tt

import sys
import re


# Python Script to recover deleted Thunderbird mails.
# When you shift-delete the mails in Thunderbird inbox. The mails are not immedeately deleted from the inbox file,
# Instead the status bit field of X-Mozilla-Status: of each message is set as deleted.
# So what we need is, just read all the value in after X-Mozilla-Status: and then clear the bit3 of the binary of the value.
# this script goes through the inbox and, reads status of each message and clear the delete bit in the status.
#The new status is written along with the mail to a new file.So the old one is unchanged....

def main():

fr = open ('./inbox' , 'r')
fw = open('./inbox-fixed', 'w')

for line in fr:
 #print line
 ms_match =re.search(r'X-Mozilla-Status: (\w+)',line)
 if (ms_match):
  msgstatus = ms_match.group(1)
  print "status extracted =", msgstatus
  msgstatus_in_int = int(msgstatus,16) #convert string to number for easy anding
  msgstatus_in_int &= ~(0x8) # clear the bit3 ie 3 in [3210]
  msgstatus_new = hex(msgstatus_in_int) #convert back to string
  msgstatus_new = msgstatus_new[2:] # remove the 0x in the string
  #print "length of len(msgstatus_new) ", len(msgstatus_new)
  if ( len(msgstatus_new) ==1 ):
   msgstatus_new = "000" + msgstatus_new
  elif ( len(msgstatus_new) ==2 ):
   msgstatus_new = "00" + msgstatus_new
  elif ( len(msgstatus_new) ==3 ):
   msgstatus_new = "0" + msgstatus_new
  print "new status=", msgstatus_new
  # line.replace(msgstatus,msgstatus_new) #replace the status
  fw.write( line.replace(msgstatus,msgstatus_new)) #replace text and write to file
 else:
  fw.write(line)
  


if __name__ == "__main__":
main()
  

# end of the python script

2 comments:

joeroxy said...

Hi there. Very intestering script, I'd love to give it a try. However, at the risk of asking something silly, how does one run this script on a Mac Lion OS? Can it be done, or do I need to install a Python development environment first? Many thanks.

nfuel900 said...

This is 2007 and by this time I hope you have already mastered Python. If no then I'll tell you how. Install active Perl python or any python in your mac. Then from shell type python scriptfilename.py