blob: babed8f5d0e5be4b2e56e9f19bfb0935fe68b43a [file] [log] [blame]
Georg Brandlf55aa802010-11-26 08:59:40 +00001#! /usr/bin/env python3
Guido van Rossum18468821994-06-20 07:49:28 +00002
3# View a single MIME multipart message.
4# Display each part as a box.
5
Georg Brandlf55aa802010-11-26 08:59:40 +00006import os
7import sys
8import getopt
9import mailbox
Benjamin Petersond6d63f52009-01-04 18:53:28 +000010from tkinter import *
11from tkinter.scrolledtext import ScrolledText
Guido van Rossum18468821994-06-20 07:49:28 +000012
Georg Brandlf55aa802010-11-26 08:59:40 +000013MBOXPATH = os.environ['HOME'] + '/Mail'
14
15class Error(Exception):
16 pass
17
18def getcurrent(self):
19 """Return the current message. Raise Error when there is none."""
20 seqs = self.get_sequences()
21 try:
22 return max(seqs['cur'])
23 except (ValueError, KeyError):
24 raise Error("no cur message")
25
26
Guido van Rossum18468821994-06-20 07:49:28 +000027class MimeViewer:
Tim Peters182b5ac2004-07-18 06:16:08 +000028 def __init__(self, parent, title, msg):
29 self.title = title
30 self.msg = msg
31 self.frame = Frame(parent, {'relief': 'raised', 'bd': 2})
32 self.frame.packing = {'expand': 0, 'fill': 'both'}
33 self.button = Checkbutton(self.frame,
34 {'text': title,
35 'command': self.toggle})
36 self.button.pack({'anchor': 'w'})
Georg Brandlf55aa802010-11-26 08:59:40 +000037 headertext = []
38 for item in msg.items():
39 headertext.append("%s: %s" % item)
40 headertext = '\n'.join(headertext)
Tim Peters182b5ac2004-07-18 06:16:08 +000041 height = countlines(headertext, 4)
42 if height:
43 self.htext = ScrolledText(self.frame,
44 {'height': height,
45 'width': 80,
46 'wrap': 'none',
47 'relief': 'raised',
48 'bd': 2})
49 self.htext.packing = {'expand': 1, 'fill': 'both',
50 'after': self.button}
51 self.htext.insert('end', headertext)
52 else:
53 self.htext = Frame(self.frame,
54 {'relief': 'raised', 'bd': 2})
55 self.htext.packing = {'side': 'top',
56 'ipady': 2,
57 'fill': 'x',
58 'after': self.button}
Georg Brandlf55aa802010-11-26 08:59:40 +000059 body = msg.get_payload()
60 if type(body) == str:
Tim Peters182b5ac2004-07-18 06:16:08 +000061 self.pad = None
62 height = countlines(body, 10)
63 if height:
64 self.btext = ScrolledText(self.frame,
65 {'height': height,
66 'width': 80,
67 'wrap': 'none',
68 'relief': 'raised',
69 'bd': 2})
70 self.btext.packing = {'expand': 1,
71 'fill': 'both'}
72 self.btext.insert('end', body)
73 else:
74 self.btext = None
75 self.parts = None
76 else:
77 self.pad = Frame(self.frame,
78 {'relief': 'flat', 'bd': 2})
79 self.pad.packing = {'side': 'left', 'ipadx': 10,
80 'fill': 'y', 'after': self.htext}
81 self.parts = []
82 for i in range(len(body)):
83 p = MimeViewer(self.frame,
84 '%s.%d' % (title, i+1),
85 body[i])
86 self.parts.append(p)
87 self.btext = None
88 self.collapsed = 1
89 def pack(self):
90 self.frame.pack(self.frame.packing)
91 def destroy(self):
92 self.frame.destroy()
93 def show(self):
94 if self.collapsed:
95 self.button.invoke()
96 def toggle(self):
97 if self.collapsed:
98 self.explode()
99 else:
100 self.collapse()
101 def collapse(self):
102 self.collapsed = 1
103 for comp in self.htext, self.btext, self.pad:
104 if comp:
105 comp.forget()
106 if self.parts:
107 for part in self.parts:
108 part.frame.forget()
109 self.frame.pack({'expand': 0})
110 def explode(self):
111 self.collapsed = 0
112 for comp in self.htext, self.btext, self.pad:
113 if comp: comp.pack(comp.packing)
114 if self.parts:
115 for part in self.parts:
116 part.pack()
117 self.frame.pack({'expand': 1})
Guido van Rossum18468821994-06-20 07:49:28 +0000118
119def countlines(str, limit):
Tim Peters182b5ac2004-07-18 06:16:08 +0000120 i = 0
121 n = 0
122 while n < limit:
Georg Brandlf55aa802010-11-26 08:59:40 +0000123 i = str.find('\n', i)
Tim Peters182b5ac2004-07-18 06:16:08 +0000124 if i < 0: break
125 n = n+1
126 i = i+1
127 return n
Guido van Rossum18468821994-06-20 07:49:28 +0000128
129def main():
Tim Peters182b5ac2004-07-18 06:16:08 +0000130 opts, args = getopt.getopt(sys.argv[1:], '')
131 for o, a in opts:
132 pass
133 message = None
134 folder = 'inbox'
135 for arg in args:
136 if arg[:1] == '+':
137 folder = arg[1:]
138 else:
Georg Brandlf55aa802010-11-26 08:59:40 +0000139 message = int(arg)
Guido van Rossum18468821994-06-20 07:49:28 +0000140
Georg Brandlf55aa802010-11-26 08:59:40 +0000141 mh = mailbox.MH(MBOXPATH)
142 f = mh.get_folder(folder)
143 if message is None:
144 message = getcurrent(f)
145 m = mailbox.MHMessage(f.get(message))
Guido van Rossum18468821994-06-20 07:49:28 +0000146
Tim Peters182b5ac2004-07-18 06:16:08 +0000147 root = Tk()
148 tk = root.tk
Guido van Rossum18468821994-06-20 07:49:28 +0000149
Tim Peters182b5ac2004-07-18 06:16:08 +0000150 top = MimeViewer(root, '+%s/%d' % (folder, message), m)
151 top.pack()
152 top.show()
Guido van Rossum18468821994-06-20 07:49:28 +0000153
Tim Peters182b5ac2004-07-18 06:16:08 +0000154 root.minsize(1, 1)
Guido van Rossum18468821994-06-20 07:49:28 +0000155
Tim Peters182b5ac2004-07-18 06:16:08 +0000156 tk.mainloop()
Guido van Rossum18468821994-06-20 07:49:28 +0000157
Georg Brandlf55aa802010-11-26 08:59:40 +0000158if __name__ == '__main__':
159 main()