blob: d1315d0b894388dc598ff36a484abcd7f92a32d2 [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:
Guido van Rossum8ca84201998-03-26 20:56:10 +000010
Guido van Rossumc7b68821994-04-28 09:53:33 +000011 def __init__(self, fp):
12 self.fp = fp
13 self.seekp = 0
14
Guido van Rossum44a4d591996-01-25 18:40:41 +000015 def seek(self, pos, whence=0):
16 if whence==1: # Relative to current position
17 self.pos = self.pos + pos
18 if whence==2: # Relative to file's end
19 self.pos = self.stop + pos
20 else: # Default - absolute position
21 self.pos = self.start + pos
Guido van Rossumc7b68821994-04-28 09:53:33 +000022
23 def next(self):
24 while 1:
25 self.fp.seek(self.seekp)
26 try:
27 self._search_start()
28 except EOFError:
29 self.seekp = self.fp.tell()
30 return None
31 start = self.fp.tell()
32 self._search_end()
33 self.seekp = stop = self.fp.tell()
34 if start <> stop:
35 break
36 return rfc822.Message(_Subfile(self.fp, start, stop))
37
38class _Subfile:
Guido van Rossum8ca84201998-03-26 20:56:10 +000039
Guido van Rossumc7b68821994-04-28 09:53:33 +000040 def __init__(self, fp, start, stop):
41 self.fp = fp
42 self.start = start
43 self.stop = stop
44 self.pos = self.start
45
Guido van Rossum2922c6d1994-05-06 14:28:19 +000046 def read(self, length = None):
Guido van Rossumc7b68821994-04-28 09:53:33 +000047 if self.pos >= self.stop:
48 return ''
Guido van Rossum2922c6d1994-05-06 14:28:19 +000049 if length is None:
Guido van Rossumc7b68821994-04-28 09:53:33 +000050 length = self.stop - self.pos
Guido van Rossumc7b68821994-04-28 09:53:33 +000051 self.fp.seek(self.pos)
52 self.pos = self.pos + length
53 return self.fp.read(length)
54
Guido van Rossum2922c6d1994-05-06 14:28:19 +000055 def readline(self, length = None):
Guido van Rossumc7b68821994-04-28 09:53:33 +000056 if self.pos >= self.stop:
57 return ''
Guido van Rossum2922c6d1994-05-06 14:28:19 +000058 if length is None:
Guido van Rossumc7b68821994-04-28 09:53:33 +000059 length = self.stop - self.pos
Guido van Rossumc7b68821994-04-28 09:53:33 +000060 self.fp.seek(self.pos)
61 data = self.fp.readline(length)
62 if len(data) < length:
63 length = len(data)
64 self.pos = self.pos + length
65 return data
66
67 def tell(self):
68 return self.pos - self.start
69
Jack Jansen97157791995-10-23 13:59:53 +000070 def seek(self, pos, whence=0):
Guido van Rossum8ca84201998-03-26 20:56:10 +000071 if whence == 0:
72 self.pos = self.start + pos
Jack Jansen97157791995-10-23 13:59:53 +000073 elif whence == 1:
Guido van Rossum8ca84201998-03-26 20:56:10 +000074 self.pos = self.pos + pos
Jack Jansen97157791995-10-23 13:59:53 +000075 elif whence == 2:
Guido van Rossum8ca84201998-03-26 20:56:10 +000076 self.pos = self.stop + pos
Guido van Rossumc7b68821994-04-28 09:53:33 +000077
78 def close(self):
79 pass
80
81class UnixMailbox(_Mailbox):
Guido van Rossum8ca84201998-03-26 20:56:10 +000082
Guido van Rossumc7b68821994-04-28 09:53:33 +000083 def _search_start(self):
84 while 1:
85 line = self.fp.readline()
86 if not line:
87 raise EOFError
88 if line[:5] == 'From ':
89 return
90
91 def _search_end(self):
92 while 1:
93 pos = self.fp.tell()
94 line = self.fp.readline()
95 if not line:
96 return
97 if line[:5] == 'From ':
98 self.fp.seek(pos)
99 return
100
101class MmdfMailbox(_Mailbox):
Guido van Rossum8ca84201998-03-26 20:56:10 +0000102
Guido van Rossumc7b68821994-04-28 09:53:33 +0000103 def _search_start(self):
104 while 1:
105 line = self.fp.readline()
106 if not line:
107 raise EOFError
108 if line[:5] == '\001\001\001\001\n':
109 return
110
111 def _search_end(self):
112 while 1:
113 pos = self.fp.tell()
114 line = self.fp.readline()
115 if not line:
116 return
117 if line == '\001\001\001\001\n':
118 self.fp.seek(pos)
119 return
120
Jack Jansen97157791995-10-23 13:59:53 +0000121class MHMailbox:
Jack Jansen97157791995-10-23 13:59:53 +0000122
Guido van Rossum8ca84201998-03-26 20:56:10 +0000123 def __init__(self, dirname):
124 import re
125 pat = re.compile('^[0-9][0-9]*$')
126 self.dirname = dirname
127 files = os.listdir(self.dirname)
128 self.boxes = []
129 for f in files:
130 if pat.match(f):
131 self.boxes.append(f)
132
133 def next(self):
134 if not self.boxes:
135 return None
136 fn = self.boxes[0]
137 del self.boxes[0]
138 fp = open(os.path.join(self.dirname, fn))
139 return rfc822.Message(fp)
Jack Jansen97157791995-10-23 13:59:53 +0000140
141
Guido van Rossumfdf58fe1997-05-15 14:33:09 +0000142class BabylMailbox(_Mailbox):
Guido van Rossumfdf58fe1997-05-15 14:33:09 +0000143
Guido van Rossum8ca84201998-03-26 20:56:10 +0000144 def _search_start(self):
145 while 1:
146 line = self.fp.readline()
147 if not line:
148 raise EOFError
149 if line == '*** EOOH ***\n':
150 return
151
152 def _search_end(self):
153 while 1:
154 pos = self.fp.tell()
155 line = self.fp.readline()
156 if not line:
157 return
158 if line == '\037\014\n':
159 self.fp.seek(pos)
160 return
Guido van Rossumfdf58fe1997-05-15 14:33:09 +0000161
162
Guido van Rossum62448671996-09-17 21:33:15 +0000163def _test():
Guido van Rossumc7b68821994-04-28 09:53:33 +0000164 import time
165 import sys
166 import string
Guido van Rossum62448671996-09-17 21:33:15 +0000167 import os
Jack Jansen97157791995-10-23 13:59:53 +0000168
Guido van Rossum62448671996-09-17 21:33:15 +0000169 args = sys.argv[1:]
170 if not args:
Guido van Rossum6dd87831997-05-08 23:11:52 +0000171 for key in 'MAIL', 'LOGNAME', 'USER':
172 if os.environ.has_key(key):
173 mbox = os.environ[key]
174 break
Guido van Rossum62448671996-09-17 21:33:15 +0000175 else:
Guido van Rossum6dd87831997-05-08 23:11:52 +0000176 print "$MAIL, $LOGNAME nor $USER set -- who are you?"
Guido van Rossum62448671996-09-17 21:33:15 +0000177 return
178 else:
179 mbox = args[0]
180 if mbox[:1] == '+':
181 mbox = os.environ['HOME'] + '/Mail/' + mbox[1:]
182 elif not '/' in mbox:
183 mbox = '/usr/mail/' + mbox
184 if os.path.isdir(mbox):
185 mb = MHMailbox(mbox)
186 else:
187 fp = open(mbox, 'r')
188 mb = UnixMailbox(fp)
Jack Jansen97157791995-10-23 13:59:53 +0000189
Guido van Rossumc7b68821994-04-28 09:53:33 +0000190 msgs = []
191 while 1:
192 msg = mb.next()
193 if not msg:
194 break
195 msgs.append(msg)
Guido van Rossum9694fca1997-10-22 21:00:49 +0000196 msg.fp = None
Guido van Rossum62448671996-09-17 21:33:15 +0000197 if len(args) > 1:
198 num = string.atoi(args[1])
Guido van Rossumc7b68821994-04-28 09:53:33 +0000199 print 'Message %d body:'%num
200 msg = msgs[num-1]
201 msg.rewindbody()
202 sys.stdout.write(msg.fp.read())
Guido van Rossum62448671996-09-17 21:33:15 +0000203 else:
204 print 'Mailbox',mbox,'has',len(msgs),'messages:'
205 for msg in msgs:
206 f = msg.getheader('from')
207 s = msg.getheader('subject')
208 d = (msg.getheader('date'))
209 print '%20.20s %18.18s %-30.30s'%(f, d[5:], s)
210
211
212if __name__ == '__main__':
213 _test()