blob: 37a4636cc30a79bdf69e37e951db8f490dcc2418 [file] [log] [blame]
Guido van Rossumf06ee5f1996-11-27 19:52:01 +00001#! /usr/bin/env python
Guido van Rossum62448671996-09-17 21:33:15 +00002
3"""Classes to handle Unix style, MMDF style, and MH style mailboxes."""
4
5
Guido van Rossumc7b68821994-04-28 09:53:33 +00006import rfc822
Jack Jansen97157791995-10-23 13:59:53 +00007import os
Guido van Rossumc7b68821994-04-28 09:53:33 +00008
9class _Mailbox:
10 def __init__(self, fp):
11 self.fp = fp
12 self.seekp = 0
13
Guido van Rossum44a4d591996-01-25 18:40:41 +000014 def seek(self, pos, whence=0):
15 if whence==1: # Relative to current position
16 self.pos = self.pos + pos
17 if whence==2: # Relative to file's end
18 self.pos = self.stop + pos
19 else: # Default - absolute position
20 self.pos = self.start + pos
Guido van Rossumc7b68821994-04-28 09:53:33 +000021
22 def next(self):
23 while 1:
24 self.fp.seek(self.seekp)
25 try:
26 self._search_start()
27 except EOFError:
28 self.seekp = self.fp.tell()
29 return None
30 start = self.fp.tell()
31 self._search_end()
32 self.seekp = stop = self.fp.tell()
33 if start <> stop:
34 break
35 return rfc822.Message(_Subfile(self.fp, start, stop))
36
37class _Subfile:
38 def __init__(self, fp, start, stop):
39 self.fp = fp
40 self.start = start
41 self.stop = stop
42 self.pos = self.start
43
Guido van Rossum2922c6d1994-05-06 14:28:19 +000044 def read(self, length = None):
Guido van Rossumc7b68821994-04-28 09:53:33 +000045 if self.pos >= self.stop:
46 return ''
Guido van Rossum2922c6d1994-05-06 14:28:19 +000047 if length is None:
Guido van Rossumc7b68821994-04-28 09:53:33 +000048 length = self.stop - self.pos
Guido van Rossumc7b68821994-04-28 09:53:33 +000049 self.fp.seek(self.pos)
50 self.pos = self.pos + length
51 return self.fp.read(length)
52
Guido van Rossum2922c6d1994-05-06 14:28:19 +000053 def readline(self, length = None):
Guido van Rossumc7b68821994-04-28 09:53:33 +000054 if self.pos >= self.stop:
55 return ''
Guido van Rossum2922c6d1994-05-06 14:28:19 +000056 if length is None:
Guido van Rossumc7b68821994-04-28 09:53:33 +000057 length = self.stop - self.pos
Guido van Rossumc7b68821994-04-28 09:53:33 +000058 self.fp.seek(self.pos)
59 data = self.fp.readline(length)
60 if len(data) < length:
61 length = len(data)
62 self.pos = self.pos + length
63 return data
64
65 def tell(self):
66 return self.pos - self.start
67
Jack Jansen97157791995-10-23 13:59:53 +000068 def seek(self, pos, whence=0):
69 if whence == 0:
70 self.pos = self.start + pos
71 elif whence == 1:
72 self.pos = self.pos + pos
73 elif whence == 2:
74 self.pos = self.stop + pos
Guido van Rossumc7b68821994-04-28 09:53:33 +000075
76 def close(self):
77 pass
78
79class UnixMailbox(_Mailbox):
80 def _search_start(self):
81 while 1:
82 line = self.fp.readline()
83 if not line:
84 raise EOFError
85 if line[:5] == 'From ':
86 return
87
88 def _search_end(self):
89 while 1:
90 pos = self.fp.tell()
91 line = self.fp.readline()
92 if not line:
93 return
94 if line[:5] == 'From ':
95 self.fp.seek(pos)
96 return
97
98class MmdfMailbox(_Mailbox):
99 def _search_start(self):
100 while 1:
101 line = self.fp.readline()
102 if not line:
103 raise EOFError
104 if line[:5] == '\001\001\001\001\n':
105 return
106
107 def _search_end(self):
108 while 1:
109 pos = self.fp.tell()
110 line = self.fp.readline()
111 if not line:
112 return
113 if line == '\001\001\001\001\n':
114 self.fp.seek(pos)
115 return
116
Jack Jansen97157791995-10-23 13:59:53 +0000117class MHMailbox:
118 def __init__(self, dirname):
Guido van Rossum9694fca1997-10-22 21:00:49 +0000119 import re
120 pat = re.compile('^[0-9][0-9]*$')
Jack Jansen97157791995-10-23 13:59:53 +0000121 self.dirname = dirname
122 files = os.listdir(self.dirname)
123 self.boxes = []
124 for f in files:
Guido van Rossum9694fca1997-10-22 21:00:49 +0000125 if pat.match(f):
Jack Jansen97157791995-10-23 13:59:53 +0000126 self.boxes.append(f)
127
128 def next(self):
129 if not self.boxes:
130 return None
131 fn = self.boxes[0]
132 del self.boxes[0]
133 fp = open(os.path.join(self.dirname, fn))
134 return rfc822.Message(fp)
135
136
Guido van Rossumfdf58fe1997-05-15 14:33:09 +0000137class BabylMailbox(_Mailbox):
138 def _search_start(self):
139 while 1:
140 line = self.fp.readline()
141 if not line:
142 raise EOFError
143 if line == '*** EOOH ***\n':
144 return
145
146 def _search_end(self):
147 while 1:
148 pos = self.fp.tell()
149 line = self.fp.readline()
150 if not line:
151 return
152 if line == '\037\014\n':
153 self.fp.seek(pos)
154 return
155
156
Guido van Rossum62448671996-09-17 21:33:15 +0000157def _test():
Guido van Rossumc7b68821994-04-28 09:53:33 +0000158 import time
159 import sys
160 import string
Guido van Rossum62448671996-09-17 21:33:15 +0000161 import os
Jack Jansen97157791995-10-23 13:59:53 +0000162
Guido van Rossum62448671996-09-17 21:33:15 +0000163 args = sys.argv[1:]
164 if not args:
Guido van Rossum6dd87831997-05-08 23:11:52 +0000165 for key in 'MAIL', 'LOGNAME', 'USER':
166 if os.environ.has_key(key):
167 mbox = os.environ[key]
168 break
Guido van Rossum62448671996-09-17 21:33:15 +0000169 else:
Guido van Rossum6dd87831997-05-08 23:11:52 +0000170 print "$MAIL, $LOGNAME nor $USER set -- who are you?"
Guido van Rossum62448671996-09-17 21:33:15 +0000171 return
172 else:
173 mbox = args[0]
174 if mbox[:1] == '+':
175 mbox = os.environ['HOME'] + '/Mail/' + mbox[1:]
176 elif not '/' in mbox:
177 mbox = '/usr/mail/' + mbox
178 if os.path.isdir(mbox):
179 mb = MHMailbox(mbox)
180 else:
181 fp = open(mbox, 'r')
182 mb = UnixMailbox(fp)
Jack Jansen97157791995-10-23 13:59:53 +0000183
Guido van Rossumc7b68821994-04-28 09:53:33 +0000184 msgs = []
185 while 1:
186 msg = mb.next()
187 if not msg:
188 break
189 msgs.append(msg)
Guido van Rossum9694fca1997-10-22 21:00:49 +0000190 msg.fp = None
Guido van Rossum62448671996-09-17 21:33:15 +0000191 if len(args) > 1:
192 num = string.atoi(args[1])
Guido van Rossumc7b68821994-04-28 09:53:33 +0000193 print 'Message %d body:'%num
194 msg = msgs[num-1]
195 msg.rewindbody()
196 sys.stdout.write(msg.fp.read())
Guido van Rossum62448671996-09-17 21:33:15 +0000197 else:
198 print 'Mailbox',mbox,'has',len(msgs),'messages:'
199 for msg in msgs:
200 f = msg.getheader('from')
201 s = msg.getheader('subject')
202 d = (msg.getheader('date'))
203 print '%20.20s %18.18s %-30.30s'%(f, d[5:], s)
204
205
206if __name__ == '__main__':
207 _test()