import binascii import random from email import policy from email.parser import BytesParser from email.generator import BytesGenerator # Two sample policies, 1 is more linient coming to/from disk, 2 being an crude # example of a destination that cannot handle utf-8. Basically testing how the # email package handles the conversions. There are other policy options, # including changing between \r\n and \n. I am not an expert on the IMAP # protocol, but I imagine the servers capabilities can be mapped to some sort of # policy. p1 = policy.default.clone(cte_type='8bit',utf8=True,refold_source='none') p2 = policy.default.clone(cte_type='7bit',utf8=False,refold_source='none') # Name of a sample input file that contains several different encodings. input_file='testmail-mime' # Establish a parser that can be used to to read messages stored on disk my_parser = BytesParser(policy=p1) # Establish a generator that can convert a message based on policy and write it # to disk. I believe this is equivalent to msg.as_bytes(policy=p1) my_p1_generator = BytesGenerator(open('{}-P1'.format(input_file),'wb'), mangle_from_=None, maxheaderlen=None, policy=p1) my_p2_generator = BytesGenerator(open('{}-P2'.format(input_file),'wb'), mangle_from_=None, maxheaderlen=None, policy=p2) # Parse the test message. Note that the file is read as binary ('rt') and not # text ('rt') as is currently done in OfflineIMAP msg = my_parser.parse(open(input_file, 'rb')) # Generate a random header the same way OfflineIMAP does currently and add it to # the message - retaining the multiple encoding. rand_header = '{}-{}'.format((binascii.crc32(msg.as_bytes(policy=p1)) & 0xffffffff),random.randrange(9999999999)) msg.add_header('X-OfflineIMAP',rand_header) # Display/save the message retaining the original format # A diff between 'testmail-mime' and 'testmail-mime-P1' should show two changes, # 1) The lack of the initial 'From ' mbox delimeter and # 2) The addtional 'X-OfflineIMAP' header print(msg.as_bytes(policy=p1)) my_p1_generator.flatten(msg) # Display/save the message retaining the original format # A diff between 'testmail-mime' and 'testmail-mime-P2' should show the same # changes as -P1 and additional changes to attachments 2 and 3 print(msg.as_bytes(policy=p2)) my_p2_generator.flatten(msg)