Still same bug even with email ver. 1.2

David Rushby woodsplitter at rocketmail.com
Mon Mar 18 16:05:43 EST 2002


"Michael Hudson" <mwh at python.net> wrote in message
news:u4rjdred0.fsf at python.net...
> woodsplitter at rocketmail.com (David Rushby) writes:
>
> > And here's SourceForge bug #491612 (closed now), which was filed
to
> > report this very bug:
> >
http://sourceforge.net/tracker/index.php?func=detail&aid=491612&group_
id=25568&atid=384678
> >
> > Unfortunately, contrary to Oleg's assertion in c.l.py and Barry's
in
> > his message added to the SF bug report, the CVS version of has
*not*
> > been fixed.
>
> Are you sure?  It's certainly possible, but I think revision 1.6 of
> Lib/email/Parser.py, which became revision 1.5.10.1 on the
> release22-maint branch, was certainly aimed at fixing this bug.
> ...
> First it would be good if you could supply some evidence that the
bug
> isn't, in fact, fixed.

I checked the release22-maint branch of Python out of SF CVS at approx
15:00 GMT on March 18.  I took the next to last example in email.tex
(the program that mails the contents of a directory) and ran it for
three cases:
A) the target directory contains no files
B) the target directory contains exactly one file
C) the target directory contains more than one file

Here is the stderr ouput for case A:
----------------------------------------------------------------------
-----
Traceback (most recent call last):
  File "dirmail.py", line 134, in ?
    main()
  File "dirmail.py", line 129, in main
    s.sendmail(sender, recips, outer.as_string(0))
  File "c:\dev\python\core\lib\email\Message.py", line 59, in
as_string
    g(self, unixfrom=unixfrom)
  File "c:\dev\python\core\lib\email\Generator.py", line 83, in
__call__
    self._write(msg)
  File "c:\dev\python\core\lib\email\Generator.py", line 104, in
_write
    self._dispatch(msg)
  File "c:\dev\python\core\lib\email\Generator.py", line 134, in
_dispatch
    meth(msg)
  File "c:\dev\python\core\lib\email\Generator.py", line 240, in
_handle_multipart
    for part in msg.get_payload():
TypeError: iteration over non-sequence
----------------------------------------------------------------------
-----

Here is the stderr ouput for case B:
----------------------------------------------------------------------
-----
Traceback (most recent call last):
  File "dirmail.py", line 134, in ?
    main()
  File "dirmail.py", line 129, in main
    s.sendmail(sender, recips, outer.as_string(0))
  File "c:\dev\python\core\lib\email\Message.py", line 59, in
as_string
    g(self, unixfrom=unixfrom)
  File "c:\dev\python\core\lib\email\Generator.py", line 83, in
__call__
    self._write(msg)
  File "c:\dev\python\core\lib\email\Generator.py", line 104, in
_write
    self._dispatch(msg)
  File "c:\dev\python\core\lib\email\Generator.py", line 134, in
_dispatch
    meth(msg)
  File "c:\dev\python\core\lib\email\Generator.py", line 240, in
_handle_multipart
    for part in msg.get_payload():
  File "c:\dev\python\core\lib\email\Message.py", line 151, in
__getitem__
    return self.get(name)
  File "c:\dev\python\core\lib\email\Message.py", line 214, in get
    name = name.lower()
AttributeError: 'int' object has no attribute 'lower'
----------------------------------------------------------------------
-----

There is no output to stderr for case C, because it works fine.

I hope this adequately demonstrates that SourceForge bug #491612
(which was filed against the mimelib for of the email package, but is
still relevant to the stdlib fork) has not been fixed, even in the
release22-maint CVS branch.

BTW, my operating system is Windows NT 4.0 SP6a.

The example program is shown below.  I made one trivial change to make
the temp file name cross-platform; I flagged that change with
"DSR:platform independent version:begin" and "DSR:platform independent
version:end".
----------------------------------------------------------------------
-----
#!/usr/bin/env python

"""Send the contents of a directory as a MIME message.

Usage: dirmail [options] from to [to ...]*

Options:
    -h / --help
        Print this message and exit.

    -d directory
    --directory=directory
        Mail the contents of the specified directory, otherwise use
the
        current directory.  Only the regular files in the directory
are sent,
        and we don't recurse to subdirectories.

`from' is the email address of the sender of the message.

`to' is the email address of the recipient of the message, and
multiple
recipients may be given.

The email is sent by forwarding to your local SMTP server, which then
does the
normal delivery process.  Your local machine must be running an SMTP
server.
"""

import sys
import os
import getopt
import smtplib
# For guessing MIME type based on file name extension
import mimetypes

from email import Encoders
from email.Message import Message
from email.MIMEAudio import MIMEAudio
from email.MIMEBase import MIMEBase
from email.MIMEImage import MIMEImage
from email.MIMEText import MIMEText

COMMASPACE = ', '


def usage(code, msg=''):
    print >> sys.stderr, __doc__
    if msg:
        print >> sys.stderr, msg
    sys.exit(code)


def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help',
'directory='])
    except getopt.error, msg:
        usage(1, msg)

    dir = os.curdir
    for opt, arg in opts:
        if opt in ('-h', '--help'):
            usage(0)
        elif opt in ('-d', '--directory'):
            dir = arg

    if len(args) < 2:
        usage(1)

    sender = args[0]
    recips = args[1:]

    # Create the enclosing (outer) message
    outer = MIMEBase('multipart', 'mixed')
    outer['Subject'] = 'Contents of directory %s' %
os.path.abspath(dir)
    outer['To'] = sender
    outer['From'] = COMMASPACE.join(recips)
    outer.preamble = 'You will not see this in a MIME-aware mail
reader.\n'
    # To guarantee the message ends with a newline
    outer.epilogue = ''

    for filename in os.listdir(dir):
        path = os.path.join(dir, filename)
        if not os.path.isfile(path):
            continue
        # Guess the Content-Type: based on the file's extension.
Encoding
        # will be ignored, although we should check for simple things
like
        # gzip'd or compressed files
        ctype, encoding = mimetypes.guess_type(path)
        if ctype is None or encoding is not None:
            # No guess could be made, or the file is encoded
(compressed), so
            # use a generic bag-of-bits type.
            ctype = 'application/octet-stream'
        maintype, subtype = ctype.split('/', 1)
        if maintype == 'text':
            fp = open(path)
            # Note: we should handle calculating the charset
            msg = MIMEText(fp.read(), _subtype=subtype)
            fp.close()
        elif maintype == 'image':
            fp = open(path, 'rb')
            msg = MIMEImage(fp.read(), _subtype=subtype)
            fp.close()
        elif maintype == 'audio':
            fp = open(path, 'rb')
            msg = MIMEAudio(fp.read(), _subtype=subtype)
            fp.close()
        else:
            fp = open(path, 'rb')
            msg = MIMEBase(maintype, subtype)
            msg.add_payload(fp.read())
            fp.close()
            # Encode the payload using Base64
            Encoders.encode_base64(msg)
        # Set the filename parameter
        msg.add_header('Content-Disposition', 'attachment',
filename=filename)
        outer.attach(msg)

    # DSR:platform independent version:begin
    # Was:
    #fp = open('/tmp/debug.pck', 'w')

    # Changed to:
    import tempfile
    fp = open(tempfile.mktemp(), 'w')
    # DSR:platform independent version:end
    import cPickle
    cPickle.dump(outer, fp)
    fp.close()
    # Now send the message
    s = smtplib.SMTP()
    s.connect()
    s.sendmail(sender, recips, outer.as_string(0))
    s.close()


if __name__ == '__main__':
    main()






More information about the Python-list mailing list