"""Classes to handle Unix style, MMDF style, and MH style mailboxes."""
__all__
= ["UnixMailbox","MmdfMailbox","MHMailbox","Maildir","BabylMailbox",
def __init__(self
, fp
, factory
=rfc822
.Message
):
return iter(self
.next
, None)
self
.seekp
= self
.fp
.tell()
self
.seekp
= stop
= self
.fp
.tell()
return self
.factory(_Subfile(self
.fp
, start
, stop
))
def __init__(self
, fp
, start
, stop
):
def _read(self
, length
, read_function
):
if self
.pos
>= self
.stop
:
remaining
= self
.stop
- self
.pos
if length
is None or length
< 0 or length
> remaining
:
data
= read_function(length
)
self
.pos
= self
.fp
.tell()
def read(self
, length
= None):
return self
._read
(length
, self
.fp
.read
)
def readline(self
, length
= None):
return self
._read
(length
, self
.fp
.readline
)
def readlines(self
, sizehint
= -1):
sizehint
= sizehint
- len(line
)
return self
.pos
- self
.start
def seek(self
, pos
, whence
=0):
self
.pos
= self
.start
+ pos
self
.pos
= self
.pos
+ pos
self
.pos
= self
.stop
+ pos
# Recommended to use PortableUnixMailbox instead!
class UnixMailbox(_Mailbox
):
line
= self
.fp
.readline()
if line
[:5] == 'From ' and self
._isrealfromline
(line
):
self
.fp
.readline() # Throw away header line
line
= self
.fp
.readline()
if line
[:5] == 'From ' and self
._isrealfromline
(line
):
# An overridable mechanism to test for From-line-ness. You can either
# specify a different regular expression or define a whole new
# _isrealfromline() method. Note that this only gets called for lines
# starting with the 5 characters "From ".
#http://home.netscape.com/eng/mozilla/2.0/relnotes/demo/content-length.html
# the only portable, reliable way to find message delimiters in a BSD (i.e
# Unix mailbox) style folder is to search for "\n\nFrom .*\n", or at the
# beginning of the file, "^From .*\n". While _fromlinepattern below seems
# like a good idea, in practice, there are too many variations for more
# strict parsing of the line to be completely accurate.
# _strict_isrealfromline() is the old version which tries to do stricter
# parsing of the From_ line. _portable_isrealfromline() simply returns
# true, since it's never called if the line doesn't already start with
# This algorithm, and the way it interacts with _search_start() and
# _search_end() may not be completely correct, because it doesn't check
# that the two characters preceding "From " are \n\n or the beginning of
# the file. Fixing this would require a more extensive rewrite than is
# necessary. For convenience, we've added a PortableUnixMailbox class
# which uses the more lenient _fromlinepattern regular expression.
_fromlinepattern
= r
"From \s*[^\s]+\s+\w\w\w\s+\w\w\w\s+\d?\d\s+" \
r
"\d?\d:\d\d(:\d\d)?(\s+[^\s]+)?\s+\d\d\d\d\s*$"
def _strict_isrealfromline(self
, line
):
self
._regexp
= re
.compile(self
._fromlinepattern
)
return self
._regexp
.match(line
)
def _portable_isrealfromline(self
, line
):
_isrealfromline
= _strict_isrealfromline
class PortableUnixMailbox(UnixMailbox
):
_isrealfromline
= UnixMailbox
._portable
_isrealfromline
class MmdfMailbox(_Mailbox
):
line
= self
.fp
.readline()
if line
[:5] == '\001\001\001\001\n':
line
= self
.fp
.readline()
if line
== '\001\001\001\001\n':
def __init__(self
, dirname
, factory
=rfc822
.Message
):
pat
= re
.compile('^[1-9][0-9]*$')
# the three following lines could be combined into:
# list = map(long, filter(pat.match, os.listdir(self.dirname)))
list = os
.listdir(self
.dirname
)
list = filter(pat
.match
, list)
# This only works in Python 1.6 or later;
# before that str() added 'L':
self
.boxes
= map(str, list)
return iter(self
.next
, None)
fp
= open(os
.path
.join(self
.dirname
, fn
))
except (AttributeError, TypeError):
# Qmail directory mailbox
def __init__(self
, dirname
, factory
=rfc822
.Message
):
newdir
= os
.path
.join(self
.dirname
, 'new')
boxes
= [os
.path
.join(newdir
, f
)
for f
in os
.listdir(newdir
) if f
[0] != '.']
# Now check for current mail in this maildir
curdir
= os
.path
.join(self
.dirname
, 'cur')
boxes
+= [os
.path
.join(curdir
, f
)
for f
in os
.listdir(curdir
) if f
[0] != '.']
return iter(self
.next
, None)
class BabylMailbox(_Mailbox
):
line
= self
.fp
.readline()
if line
== '*** EOOH ***\n':
line
= self
.fp
.readline()
if line
== '\037\014\n' or line
== '\037':
for key
in 'MAILDIR', 'MAIL', 'LOGNAME', 'USER':
print "$MAIL, $LOGNAME nor $USER set -- who are you?"
mbox
= os
.environ
['HOME'] + '/Mail/' + mbox
[1:]
if os
.path
.isfile('/var/mail/' + mbox
):
mbox
= '/var/mail/' + mbox
mbox
= '/usr/mail/' + mbox
if os
.path
.isdir(os
.path
.join(mbox
, 'cur')):
mb
= PortableUnixMailbox(fp
)
print 'Message %d body:'%num
sys
.stdout
.write(msg
.fp
.read())
print 'Mailbox',mbox
,'has',len(msgs
),'messages:'
f
= msg
.getheader('from') or ""
s
= msg
.getheader('subject') or ""
d
= msg
.getheader('date') or ""
print '-%20.20s %20.20s %-30.30s'%(f
, d
[5:], s
)
if __name__
== '__main__':