blob: 3d7d2fc7dce5956ffcd726411cdc25b373a12ef7 [file] [log] [blame]
Guido van Rossum62448671996-09-17 21:33:15 +00001#!/usr/local/bin/python
2
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
8import regex
Guido van Rossumc7b68821994-04-28 09:53:33 +00009
10class _Mailbox:
11 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:
39 def __init__(self, fp, start, stop):
40 self.fp = fp
41 self.start = start
42 self.stop = stop
43 self.pos = self.start
44
Guido van Rossum2922c6d1994-05-06 14:28:19 +000045 def read(self, length = None):
Guido van Rossumc7b68821994-04-28 09:53:33 +000046 if self.pos >= self.stop:
47 return ''
Guido van Rossum2922c6d1994-05-06 14:28:19 +000048 if length is None:
Guido van Rossumc7b68821994-04-28 09:53:33 +000049 length = self.stop - self.pos
Guido van Rossumc7b68821994-04-28 09:53:33 +000050 self.fp.seek(self.pos)
51 self.pos = self.pos + length
52 return self.fp.read(length)
53
Guido van Rossum2922c6d1994-05-06 14:28:19 +000054 def readline(self, length = None):
Guido van Rossumc7b68821994-04-28 09:53:33 +000055 if self.pos >= self.stop:
56 return ''
Guido van Rossum2922c6d1994-05-06 14:28:19 +000057 if length is None:
Guido van Rossumc7b68821994-04-28 09:53:33 +000058 length = self.stop - self.pos
Guido van Rossumc7b68821994-04-28 09:53:33 +000059 self.fp.seek(self.pos)
60 data = self.fp.readline(length)
61 if len(data) < length:
62 length = len(data)
63 self.pos = self.pos + length
64 return data
65
66 def tell(self):
67 return self.pos - self.start
68
Jack Jansen97157791995-10-23 13:59:53 +000069 def seek(self, pos, whence=0):
70 if whence == 0:
71 self.pos = self.start + pos
72 elif whence == 1:
73 self.pos = self.pos + pos
74 elif whence == 2:
75 self.pos = self.stop + pos
Guido van Rossumc7b68821994-04-28 09:53:33 +000076
77 def close(self):
78 pass
79
80class UnixMailbox(_Mailbox):
81 def _search_start(self):
82 while 1:
83 line = self.fp.readline()
84 if not line:
85 raise EOFError
86 if line[:5] == 'From ':
87 return
88
89 def _search_end(self):
90 while 1:
91 pos = self.fp.tell()
92 line = self.fp.readline()
93 if not line:
94 return
95 if line[:5] == 'From ':
96 self.fp.seek(pos)
97 return
98
99class MmdfMailbox(_Mailbox):
100 def _search_start(self):
101 while 1:
102 line = self.fp.readline()
103 if not line:
104 raise EOFError
105 if line[:5] == '\001\001\001\001\n':
106 return
107
108 def _search_end(self):
109 while 1:
110 pos = self.fp.tell()
111 line = self.fp.readline()
112 if not line:
113 return
114 if line == '\001\001\001\001\n':
115 self.fp.seek(pos)
116 return
117
Jack Jansen97157791995-10-23 13:59:53 +0000118class MHMailbox:
119 def __init__(self, dirname):
120 pat = regex.compile('^[0-9][0-9]*$')
121 self.dirname = dirname
122 files = os.listdir(self.dirname)
123 self.boxes = []
124 for f in files:
125 if pat.match(f) == len(f):
126 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 Rossum62448671996-09-17 21:33:15 +0000137def _test():
Guido van Rossumc7b68821994-04-28 09:53:33 +0000138 import time
139 import sys
140 import string
Guido van Rossum62448671996-09-17 21:33:15 +0000141 import os
Jack Jansen97157791995-10-23 13:59:53 +0000142
Guido van Rossum62448671996-09-17 21:33:15 +0000143 args = sys.argv[1:]
144 if not args:
145 if os.environ.has_key('MAIL'):
146 mbox = os.environ['MAIL']
147 elif os.environ.has_key('MAIL'):
148 mbox = os.environ['USER']
149 else:
150 print "Who are you?"
151 return
152 else:
153 mbox = args[0]
154 if mbox[:1] == '+':
155 mbox = os.environ['HOME'] + '/Mail/' + mbox[1:]
156 elif not '/' in mbox:
157 mbox = '/usr/mail/' + mbox
158 if os.path.isdir(mbox):
159 mb = MHMailbox(mbox)
160 else:
161 fp = open(mbox, 'r')
162 mb = UnixMailbox(fp)
Jack Jansen97157791995-10-23 13:59:53 +0000163
Guido van Rossumc7b68821994-04-28 09:53:33 +0000164 msgs = []
165 while 1:
166 msg = mb.next()
167 if not msg:
168 break
169 msgs.append(msg)
Guido van Rossum62448671996-09-17 21:33:15 +0000170 if len(args) > 1:
171 num = string.atoi(args[1])
Guido van Rossumc7b68821994-04-28 09:53:33 +0000172 print 'Message %d body:'%num
173 msg = msgs[num-1]
174 msg.rewindbody()
175 sys.stdout.write(msg.fp.read())
Guido van Rossum62448671996-09-17 21:33:15 +0000176 else:
177 print 'Mailbox',mbox,'has',len(msgs),'messages:'
178 for msg in msgs:
179 f = msg.getheader('from')
180 s = msg.getheader('subject')
181 d = (msg.getheader('date'))
182 print '%20.20s %18.18s %-30.30s'%(f, d[5:], s)
183
184
185if __name__ == '__main__':
186 _test()