How do I get a mimetools.Message object from a mailbox.UnixMailbox object?

arcege at shore.net arcege at shore.net
Wed Jan 10 12:09:15 EST 2001


Paul Moore <paul.moore at uk.origin-it.com> wrote:
: On Mon, 8 Jan 2001 02:34:31 +0100 , "Steve Holden"
: <sholden at holdenweb.com> wrote:

:>The mimecntl module was invented to overcome the impedance mismatch between
:>mailbox and rfc822, and does so quite well, so you may wish to consider
:>using that instead.  I've used it fairly extensively and only had one
:>problem with it (which I'm debgging between times, but haven't looked at
:>lately).

: Thanks for the pointer. However, the module doesn't seem to handle
: mbox format mailboxes, and the mailbox module doesn't offer a method
: of generating data in a form that can be passed to mimecntl (that
: would need mimecntl.MIME_document to have a constructor from a
: rfc822.message).

: I hand-parsed the Unix mbox format file in the end - it's not hard,
: after all...

A cleaner, long-term solution (instead of hand-editing the files or
using mimecntl) might be to make a subclass of UnixMailbox from
mailbox.py to replace the _Mailbox.next() method to use mimetools
instead:

import mailbox, mimetools
class MimeUnixMailBox(mailbox.UnixMailbox):
    def next(self):
      while 1:
          self.fp.seek(self.seekp)
          try:
              self._search_start()
          except EOFError:
              self.seekp = self.fp.tell()
              return None
          start = self.fp.tell()
          self._search_end()
          self.seekp = stop = self.fp.tell()
          if start <> stop:
              break
      return mimetools.Message(mailbox._Subfile(self.fp, start, stop))

Then use the class as you would the UnixMailbox class.  You could use
the mimecntl module with the UnixMailbox class in the same way, but it
would depend on what you would want to do with it.  If you wanted just
wanted to read the mailbox, the mimetools module is what you want to
use.  But if you want to read/write the messages, you will want to use
the mimecntl module since you will find that converting to mimetools to
MimeWriter is difficult, which is why I wrote the mimecntl module in
the first place.

Using the mimecntl module, you would have something like:

import mailbox, mimecntl

# first make a subclass of MIME_document, to accept "virtual" file
# objects, then a subclass to create and return instances of
# the MIME_document subclass
class NoneFileDoc(mimecntl.MIME_document):
    def check_is_file(self, obj):
        """Check to see if it is like a file, but does not have to
have a "fileno" method."""
        return (hasattr(obj, 'seek') and callable(getattr(obj, 'seek')))

class MimeUnixMailbox(mailbox.UnixMailbox):
    def next(self):
        """Get next mail message, returning a MIME document."""
        while 1:
            self.fp.seek(self.seekp)
            try:
                self._search_start()
            except EOFError:
                self.seekp = self.fp.tell()
                return None
            start = self.fp.tell()
            self._search_end()
            self.seekp = stop = self.fp.tell()
            if start <> stop:
                break
        return NoneFileDoc(mailbox._Subfile(self.fp, start, stop))

    # other methods to write the file out again

if __name__ == '__main__':
    import os, sys
    if len(sys.argv) > 1:
        mailbox_fname = sys.argv[1]
    else:
        mailbox_fname = os.environ['MAIL']
    mailbox_file = open(mailbox_fname, 'r')
  
    mbox = MimeUnixMailbox(mailbox_file)

    print 'First message is'
    print mbox.next() # a printable MIME_document instance

This might lead you in some other directions for where you want to go.
Actually, this sounds like something I'll add to the documentation of
mimecntl.  Thank you. :)

  -Arcege




More information about the Python-list mailing list