# coding=utf-8 #: ## Lab 6 ## #: #: CS-2910 Network Protocols #: Dr. Yoder (Original template by Dr. Sebern) #: Fall quarter 2014-2015 #: #: | Team members (username) | #: |:------------------------| #: | Brianna Wu (wub) | #: | Steve Lubitz (lubitzs) | #: # If you are curious about the names above, look them up! import imaplib import base64 import quopri import email from email.parser import Parser # Open a file containing the full text of an email message (headers and all). # Display the hierarchy of parts in the message. # Save each "leaf" (non-multipart) part in a file. def main(): email_parser = Parser() with open('imaplib-mail.txt','rb') as input_file: email_message = email.message_from_file(input_file) print "Python's default take:" email.iterators._structure(email_message) print print "Message part hierarchy:" # Process the message parts, starting with [1], which is rendered as "1" # The first child will be [1 1], rendered as "1.1" process_child_parts(email_message,[]) # Recursive function to traverse (depth-first) the message part hierarchy. # # part_num: An array of integers. e.g. [1 2 3] represents part 1.2.3 def process_child_parts(part,part_num): part_type = part.get_content_type(); # Make the part number in dotted decimal notation if len(part_num) > 0: part_num_str = str(part_num[0]) for part_num_component in part_num[1:]: part_num_str += '.' + str(part_num_component) else: part_num_str = '(top)' # print '{0} {1}'.format(part_num_str,part_type) # Display the header items for this part header_items = part.items() for item in part.items(): print '{0} : Header: {1} = {2}'.format(part_num_str,item[0],item[1]) params = part.get_params() for param in params: param_value = '= ' + param[1] if param[1] else '' print '{0} : Content-Type: {1} {2}'.format(part_num_str,param[0],param_value) # If part is not multipart, it is a leaf part; process it. if not part.is_multipart(): part_payload = part.get_payload() transfer_encoding = part.get('Content-Transfer-Encoding') # As it is, this code will dump each leaf part into a file named with its number. # To get the real data, it is necessary to decode the part_payload value # before writing it to the file. # This is where the decoding SHOULD happen part_payload = process_part(part_payload, transfer_encoding) with open('data-'+part_num_str,'wb') as payload_file: payload_file.write(part_payload) # print '{0} : Payload:\n--------\n{1}\n--------'.format(part_num_str,part_payload) # If part is multipart, recurse to children. else: children = [] for child in part.get_payload(): children.append(child) # print "children=",children child_num = 1 for child2 in children[0:]: # print "child2=",child2.get_content_type() child_part_num = part_num[:] child_part_num.append(child_num) child_num += 1 process_child_parts(child2,child_part_num) return # Decode the part_payload value # part_payload -- the raw part text # Return value # Decoded part, as a string def process_part(part_payload,transfer_encoding): # Default is to do nothing decoded_payload = part_payload # Modify this method to do the proper decoding. return decoded_payload main()