1#! /usr/bin/env python 2 3# View a single MIME multipart message. 4# Display each part as a box. 5 6import string 7from types import * 8from Tkinter import * 9from ScrolledText import ScrolledText 10 11class MimeViewer: 12 def __init__(self, parent, title, msg): 13 self.title = title 14 self.msg = msg 15 self.frame = Frame(parent, {'relief': 'raised', 'bd': 2}) 16 self.frame.packing = {'expand': 0, 'fill': 'both'} 17 self.button = Checkbutton(self.frame, 18 {'text': title, 19 'command': self.toggle}) 20 self.button.pack({'anchor': 'w'}) 21 headertext = msg.getheadertext( 22 lambda x: x != 'received' and x[:5] != 'x400-') 23 height = countlines(headertext, 4) 24 if height: 25 self.htext = ScrolledText(self.frame, 26 {'height': height, 27 'width': 80, 28 'wrap': 'none', 29 'relief': 'raised', 30 'bd': 2}) 31 self.htext.packing = {'expand': 1, 'fill': 'both', 32 'after': self.button} 33 self.htext.insert('end', headertext) 34 else: 35 self.htext = Frame(self.frame, 36 {'relief': 'raised', 'bd': 2}) 37 self.htext.packing = {'side': 'top', 38 'ipady': 2, 39 'fill': 'x', 40 'after': self.button} 41 body = msg.getbody() 42 if type(body) == StringType: 43 self.pad = None 44 height = countlines(body, 10) 45 if height: 46 self.btext = ScrolledText(self.frame, 47 {'height': height, 48 'width': 80, 49 'wrap': 'none', 50 'relief': 'raised', 51 'bd': 2}) 52 self.btext.packing = {'expand': 1, 53 'fill': 'both'} 54 self.btext.insert('end', body) 55 else: 56 self.btext = None 57 self.parts = None 58 else: 59 self.pad = Frame(self.frame, 60 {'relief': 'flat', 'bd': 2}) 61 self.pad.packing = {'side': 'left', 'ipadx': 10, 62 'fill': 'y', 'after': self.htext} 63 self.parts = [] 64 for i in range(len(body)): 65 p = MimeViewer(self.frame, 66 '%s.%d' % (title, i+1), 67 body[i]) 68 self.parts.append(p) 69 self.btext = None 70 self.collapsed = 1 71 def pack(self): 72 self.frame.pack(self.frame.packing) 73 def destroy(self): 74 self.frame.destroy() 75 def show(self): 76 if self.collapsed: 77 self.button.invoke() 78 def toggle(self): 79 if self.collapsed: 80 self.explode() 81 else: 82 self.collapse() 83 def collapse(self): 84 self.collapsed = 1 85 for comp in self.htext, self.btext, self.pad: 86 if comp: 87 comp.forget() 88 if self.parts: 89 for part in self.parts: 90 part.frame.forget() 91 self.frame.pack({'expand': 0}) 92 def explode(self): 93 self.collapsed = 0 94 for comp in self.htext, self.btext, self.pad: 95 if comp: comp.pack(comp.packing) 96 if self.parts: 97 for part in self.parts: 98 part.pack() 99 self.frame.pack({'expand': 1}) 100 101def countlines(str, limit): 102 i = 0 103 n = 0 104 while n < limit: 105 i = string.find(str, '\n', i) 106 if i < 0: break 107 n = n+1 108 i = i+1 109 return n 110 111def main(): 112 import sys 113 import getopt 114 import mhlib 115 opts, args = getopt.getopt(sys.argv[1:], '') 116 for o, a in opts: 117 pass 118 message = None 119 folder = 'inbox' 120 for arg in args: 121 if arg[:1] == '+': 122 folder = arg[1:] 123 else: 124 message = string.atoi(arg) 125 126 mh = mhlib.MH() 127 f = mh.openfolder(folder) 128 if not message: 129 message = f.getcurrent() 130 m = f.openmessage(message) 131 132 root = Tk() 133 tk = root.tk 134 135 top = MimeViewer(root, '+%s/%d' % (folder, message), m) 136 top.pack() 137 top.show() 138 139 root.minsize(1, 1) 140 141 tk.mainloop() 142 143if __name__ == '__main__': main() 144