SF.net SVN: tmda: [2084] trunk/tmda/TMDA/pythonlib/email

[email protected] Sat, 07 Oct 2006 19:51:09 -0700
Newsgroups gmane.mail.spam.tmda.cvs
Message-ID <[email protected]>
Revision: 2084
          http://svn.sourceforge.net/tmda/?rev=2084&view=rev
Author:   jasonrm
Date:     2006-10-07 19:50:58 -0700 (Sat, 07 Oct 2006)

Log Message:
-----------
upgrade to Python email package v4.0.1.

Modified Paths:
--------------
    trunk/tmda/TMDA/pythonlib/email/__init__.py
    trunk/tmda/TMDA/pythonlib/email/_parseaddr.py

Added Paths:
-----------
    trunk/tmda/TMDA/pythonlib/email/base64mime.py
    trunk/tmda/TMDA/pythonlib/email/charset.py
    trunk/tmda/TMDA/pythonlib/email/encoders.py
    trunk/tmda/TMDA/pythonlib/email/errors.py
    trunk/tmda/TMDA/pythonlib/email/feedparser.py
    trunk/tmda/TMDA/pythonlib/email/generator.py
    trunk/tmda/TMDA/pythonlib/email/header.py
    trunk/tmda/TMDA/pythonlib/email/iterators.py
    trunk/tmda/TMDA/pythonlib/email/message.py
    trunk/tmda/TMDA/pythonlib/email/parser.py
    trunk/tmda/TMDA/pythonlib/email/quoprimime.py
    trunk/tmda/TMDA/pythonlib/email/utils.py

Removed Paths:
-------------
    trunk/tmda/TMDA/pythonlib/email/Charset.py
    trunk/tmda/TMDA/pythonlib/email/Encoders.py
    trunk/tmda/TMDA/pythonlib/email/Errors.py
    trunk/tmda/TMDA/pythonlib/email/Generator.py
    trunk/tmda/TMDA/pythonlib/email/Header.py
    trunk/tmda/TMDA/pythonlib/email/Iterators.py
    trunk/tmda/TMDA/pythonlib/email/MIMEAudio.py
    trunk/tmda/TMDA/pythonlib/email/MIMEBase.py
    trunk/tmda/TMDA/pythonlib/email/MIMEImage.py
    trunk/tmda/TMDA/pythonlib/email/MIMEMessage.py
    trunk/tmda/TMDA/pythonlib/email/MIMEMultipart.py
    trunk/tmda/TMDA/pythonlib/email/MIMENonMultipart.py
    trunk/tmda/TMDA/pythonlib/email/MIMEText.py
    trunk/tmda/TMDA/pythonlib/email/Message.py
    trunk/tmda/TMDA/pythonlib/email/Parser.py
    trunk/tmda/TMDA/pythonlib/email/Utils.py
    trunk/tmda/TMDA/pythonlib/email/_compat21.py
    trunk/tmda/TMDA/pythonlib/email/_compat22.py
    trunk/tmda/TMDA/pythonlib/email/base64MIME.py
    trunk/tmda/TMDA/pythonlib/email/quopriMIME.py

Deleted: trunk/tmda/TMDA/pythonlib/email/Charset.py
===================================================================
--- trunk/tmda/TMDA/pythonlib/email/Charset.py	2006-10-08 02:42:29 UTC (rev 2083)
+++ trunk/tmda/TMDA/pythonlib/email/Charset.py	2006-10-08 02:50:58 UTC (rev 2084)
@@ -1,390 +0,0 @@
-# Copyright (C) 2001,2002 Python Software Foundation
-# Author: [email protected] (Ben Gertzfield), [email protected] (Barry Warsaw)
-
-# Python 2.3 doesn't come with any Asian codecs by default.  Two packages are
-# currently available and supported as of this writing (30-Dec-2003):
-#
-# CJKCodecs
-# http://cjkpython.i18n.org
-# This package contains Chinese, Japanese, and Korean codecs
-
-# JapaneseCodecs
-# http://www.asahi-net.or.jp/~rd6t-kjym/python
-# Some Japanese users prefer this codec package
-
-from types import UnicodeType
-from email.Encoders import encode_7or8bit
-import email.base64MIME
-import email.quopriMIME
-
-def _isunicode(s):
-    return isinstance(s, UnicodeType)
-
-# Python 2.2.1 and beyond has these symbols
-try:
-    True, False
-except NameError:
-    True = 1
-    False = 0
-
-
-
-# Flags for types of header encodings
-QP     = 1   # Quoted-Printable
-BASE64 = 2   # Base64
-SHORTEST = 3 # the shorter of QP and base64, but only for headers
-
-# In "=?charset?q?hello_world?=", the =?, ?q?, and ?= add up to 7
-MISC_LEN = 7
-
-DEFAULT_CHARSET = 'us-ascii'
-
-
-
-# Defaults
-CHARSETS = {
-    # input        header enc  body enc output conv
-    'iso-8859-1':  (QP,        QP,      None),
-    'iso-8859-2':  (QP,        QP,      None),
-    'iso-8859-3':  (QP,        QP,      None),
-    'iso-8859-4':  (QP,        QP,      None),
-    # iso-8859-5 is Cyrillic, and not especially used
-    # iso-8859-6 is Arabic, also not particularly used
-    # iso-8859-7 is Greek, QP will not make it readable
-    # iso-8859-8 is Hebrew, QP will not make it readable
-    'iso-8859-9':  (QP,        QP,      None),
-    'iso-8859-10': (QP,        QP,      None),
-    # iso-8859-11 is Thai, QP will not make it readable
-    'iso-8859-13': (QP,        QP,      None),
-    'iso-8859-14': (QP,        QP,      None),
-    'iso-8859-15': (QP,        QP,      None),
-    'windows-1252':(QP,        QP,      None),
-    'viscii':      (QP,        QP,      None),
-    'us-ascii':    (None,      None,    None),
-    'big5':        (BASE64,    BASE64,  None),
-    'gb2312':      (BASE64,    BASE64,  None),
-    'euc-jp':      (BASE64,    None,    'iso-2022-jp'),
-    'shift_jis':   (BASE64,    None,    'iso-2022-jp'),
-    'iso-2022-jp': (BASE64,    None,    None),
-    'koi8-r':      (BASE64,    BASE64,  None),
-    'utf-8':       (SHORTEST,  BASE64, 'utf-8'),
-    # We're making this one up to represent raw unencoded 8-bit
-    '8bit':        (None,      BASE64, 'utf-8'),
-    }
-
-# Aliases for other commonly-used names for character sets.  Map
-# them to the real ones used in email.
-ALIASES = {
-    'latin_1': 'iso-8859-1',
-    'latin-1': 'iso-8859-1',
-    'latin_2': 'iso-8859-2',
-    'latin-2': 'iso-8859-2',
-    'latin_3': 'iso-8859-3',
-    'latin-3': 'iso-8859-3',
-    'latin_4': 'iso-8859-4',
-    'latin-4': 'iso-8859-4',
-    'latin_5': 'iso-8859-9',
-    'latin-5': 'iso-8859-9',
-    'latin_6': 'iso-8859-10',
-    'latin-6': 'iso-8859-10',
-    'latin_7': 'iso-8859-13',
-    'latin-7': 'iso-8859-13',
-    'latin_8': 'iso-8859-14',
-    'latin-8': 'iso-8859-14',
-    'latin_9': 'iso-8859-15',
-    'latin-9': 'iso-8859-15',
-    'cp949':   'ks_c_5601-1987',
-    'euc_jp':  'euc-jp',
-    'euc_kr':  'euc-kr',
-    'ascii':   'us-ascii',
-    }
-
-
-# Map charsets to their Unicode codec strings.
-CODEC_MAP = {
-    'gb2312':      'eucgb2312_cn',
-    'big5':        'big5_tw',
-    # Hack: We don't want *any* conversion for stuff marked us-ascii, as all
-    # sorts of garbage might be sent to us in the guise of 7-bit us-ascii.
-    # Let that stuff pass through without conversion to/from Unicode.
-    'us-ascii':    None,
-    }
-
-
-
-# Convenience functions for extending the above mappings
-def add_charset(charset, header_enc=None, body_enc=None, output_charset=None):
-    """Add character set properties to the global registry.
-
-    charset is the input character set, and must be the canonical name of a
-    character set.
-
-    Optional header_enc and body_enc is either Charset.QP for
-    quoted-printable, Charset.BASE64 for base64 encoding, Charset.SHORTEST for
-    the shortest of qp or base64 encoding, or None for no encoding.  SHORTEST
-    is only valid for header_enc.  It describes how message headers and
-    message bodies in the input charset are to be encoded.  Default is no
-    encoding.
-
-    Optional output_charset is the character set that the output should be
-    in.  Conversions will proceed from input charset, to Unicode, to the
-    output charset when the method Charset.convert() is called.  The default
-    is to output in the same character set as the input.
-
-    Both input_charset and output_charset must have Unicode codec entries in
-    the module's charset-to-codec mapping; use add_codec(charset, codecname)
-    to add codecs the module does not know about.  See the codecs module's
-    documentation for more information.
-    """
-    if body_enc == SHORTEST:
-        raise ValueError, 'SHORTEST not allowed for body_enc'
-    CHARSETS[charset] = (header_enc, body_enc, output_charset)
-
-
-def add_alias(alias, canonical):
-    """Add a character set alias.
-
-    alias is the alias name, e.g. latin-1
-    canonical is the character set's canonical name, e.g. iso-8859-1
-    """
-    ALIASES[alias] = canonical
-
-
-def add_codec(charset, codecname):
-    """Add a codec that map characters in the given charset to/from Unicode.
-
-    charset is the canonical name of a character set.  codecname is the name
-    of a Python codec, as appropriate for the second argument to the unicode()
-    built-in, or to the encode() method of a Unicode string.
-    """
-    CODEC_MAP[charset] = codecname
-
-
-
-class Charset:
-    """Map character sets to their email properties.
-
-    This class provides information about the requirements imposed on email
-    for a specific character set.  It also provides convenience routines for
-    converting between character sets, given the availability of the
-    applicable codecs.  Given a character set, it will do its best to provide
-    information on how to use that character set in an email in an
-    RFC-compliant way.
-
-    Certain character sets must be encoded with quoted-printable or base64
-    when used in email headers or bodies.  Certain character sets must be
-    converted outright, and are not allowed in email.  Instances of this
-    module expose the following information about a character set:
-
-    input_charset: The initial character set specified.  Common aliases
-                   are converted to their `official' email names (e.g. latin_1
-                   is converted to iso-8859-1).  Defaults to 7-bit us-ascii.
-
-    header_encoding: If the character set must be encoded before it can be
-                     used in an email header, this attribute will be set to
-                     Charset.QP (for quoted-printable), Charset.BASE64 (for
-                     base64 encoding), or Charset.SHORTEST for the shortest of
-                     QP or BASE64 encoding.  Otherwise, it will be None.
-
-    body_encoding: Same as header_encoding, but describes the encoding for the
-                   mail message's body, which indeed may be different than the
-                   header encoding.  Charset.SHORTEST is not allowed for
-                   body_encoding.
-
-    output_charset: Some character sets must be converted before the can be
-                    used in email headers or bodies.  If the input_charset is
-                    one of them, this attribute will contain the name of the
-                    charset output will be converted to.  Otherwise, it will
-                    be None.
-
-    input_codec: The name of the Python codec used to convert the
-                 input_charset to Unicode.  If no conversion codec is
-                 necessary, this attribute will be None.
-
-    output_codec: The name of the Python codec used to convert Unicode
-                  to the output_charset.  If no conversion codec is necessary,
-                  this attribute will have the same value as the input_codec.
-    """
-    def __init__(self, input_charset=DEFAULT_CHARSET):
-        # RFC 2046, $4.1.2 says charsets are not case sensitive
-        input_charset = input_charset.lower()
-        # Set the input charset after filtering through the aliases
-        self.input_charset = ALIASES.get(input_charset, input_charset)
-        # We can try to guess which encoding and conversion to use by the
-        # charset_map dictionary.  Try that first, but let the user override
-        # it.
-        henc, benc, conv = CHARSETS.get(self.input_charset,
-                                        (SHORTEST, BASE64, None))
-        if not conv:
-            conv = self.input_charset
-        # Set the attributes, allowing the arguments to override the default.
-        self.header_encoding = henc
-        self.body_encoding = benc
-        self.output_charset = ALIASES.get(conv, conv)
-        # Now set the codecs.  If one isn't defined for input_charset,
-        # guess and try a Unicode codec with the same name as input_codec.
-        self.input_codec = CODEC_MAP.get(self.input_charset,
-                                         self.input_charset)
-        self.output_codec = CODEC_MAP.get(self.output_charset,
-                                            self.output_charset)
-
-    def __str__(self):
-        return self.input_charset.lower()
-
-    __repr__ = __str__
-
-    def __eq__(self, other):
-        return str(self) == str(other).lower()
-
-    def __ne__(self, other):
-        return not self.__eq__(other)
-
-    def get_body_encoding(self):
-        """Return the content-transfer-encoding used for body encoding.
-
-        This is either the string `quoted-printable' or `base64' depending on
-        the encoding used, or it is a function in which case you should call
-        the function with a single argument, the Message object being
-        encoded.  The function should then set the Content-Transfer-Encoding
-        header itself to whatever is appropriate.
-
-        Returns "quoted-printable" if self.body_encoding is QP.
-        Returns "base64" if self.body_encoding is BASE64.
-        Returns "7bit" otherwise.
-        """
-        assert self.body_encoding <> SHORTEST
-        if self.body_encoding == QP:
-            return 'quoted-printable'
-        elif self.body_encoding == BASE64:
-            return 'base64'
-        else:
-            return encode_7or8bit
-
-    def convert(self, s):
-        """Convert a string from the input_codec to the output_codec."""
-        if self.input_codec <> self.output_codec:
-            return unicode(s, self.input_codec).encode(self.output_codec)
-        else:
-            return s
-
-    def to_splittable(self, s):
-        """Convert a possibly multibyte string to a safely splittable format.
-
-        Uses the input_codec to try and convert the string to Unicode, so it
-        can be safely split on character boundaries (even for multibyte
-        characters).
-
-        Returns the string as-is if it isn't known how to convert it to
-        Unicode with the input_charset.
-
-        Characters that could not be converted to Unicode will be replaced
-        with the Unicode replacement character U+FFFD.
-        """
-        if _isunicode(s) or self.input_codec is None:
-            return s
-        try:
-            return unicode(s, self.input_codec, 'replace')
-        except LookupError:
-            # Input codec not installed on system, so return the original
-            # string unchanged.
-            return s
-
-    def from_splittable(self, ustr, to_output=True):
-        """Convert a splittable string back into an encoded string.
-
-        Uses the proper codec to try and convert the string from Unicode back
-        into an encoded format.  Return the string as-is if it is not Unicode,
-        or if it could not be converted from Unicode.
-
-        Characters that could not be converted from Unicode will be replaced
-        with an appropriate character (usually '?').
-
-        If to_output is True (the default), uses output_codec to convert to an
-        encoded format.  If to_output is False, uses input_codec.
-        """
-        if to_output:
-            codec = self.output_codec
-        else:
-            codec = self.input_codec
-        if not _isunicode(ustr) or codec is None:
-            return ustr
-        try:
-            return ustr.encode(codec, 'replace')
-        except LookupError:
-            # Output codec not installed
-            return ustr
-
-    def get_output_charset(self):
-        """Return the output character set.
-
-        This is self.output_charset if that is not None, otherwise it is
-        self.input_charset.
-        """
-        return self.output_charset or self.input_charset
-
-    def encoded_header_len(self, s):
-        """Return the length of the encoded header string."""
-        cset = self.get_output_charset()
-        # The len(s) of a 7bit encoding is len(s)
-        if self.header_encoding == BASE64:
-            return email.base64MIME.base64_len(s) + len(cset) + MISC_LEN
-        elif self.header_encoding == QP:
-            return email.quopriMIME.header_quopri_len(s) + len(cset) + MISC_LEN
-        elif self.header_encoding == SHORTEST:
-            lenb64 = email.base64MIME.base64_len(s)
-            lenqp = email.quopriMIME.header_quopri_len(s)
-            return min(lenb64, lenqp) + len(cset) + MISC_LEN
-        else:
-            return len(s)
-
-    def header_encode(self, s, convert=False):
-        """Header-encode a string, optionally converting it to output_charset.
-
-        If convert is True, the string will be converted from the input
-        charset to the output charset automatically.  This is not useful for
-        multibyte character sets, which have line length issues (multibyte
-        characters must be split on a character, not a byte boundary); use the
-        high-level Header class to deal with these issues.  convert defaults
-        to False.
-
-        The type of encoding (base64 or quoted-printable) will be based on
-        self.header_encoding.
-        """
-        cset = self.get_output_charset()
-        if convert:
-            s = self.convert(s)
-        # 7bit/8bit encodings return the string unchanged (modulo conversions)
-        if self.header_encoding == BASE64:
-            return email.base64MIME.header_encode(s, cset)
-        elif self.header_encoding == QP:
-            return email.quopriMIME.header_encode(s, cset, maxlinelen=None)
-        elif self.header_encoding == SHORTEST:
-            lenb64 = email.base64MIME.base64_len(s)
-            lenqp = email.quopriMIME.header_quopri_len(s)
-            if lenb64 < lenqp:
-                return email.base64MIME.header_encode(s, cset)
-            else:
-                return email.quopriMIME.header_encode(s, cset, maxlinelen=None)
-        else:
-            return s
-
-    def body_encode(self, s, convert=True):
-        """Body-encode a string and convert it to output_charset.
-
-        If convert is True (the default), the string will be converted from
-        the input charset to output charset automatically.  Unlike
-        header_encode(), there are no issues with byte boundaries and
-        multibyte charsets in email bodies, so this is usually pretty safe.
-
-        The type of encoding (base64 or quoted-printable) will be based on
-        self.body_encoding.
-        """
-        if convert:
-            s = self.convert(s)
-        # 7bit/8bit encodings return the string unchanged (module conversions)
-        if self.body_encoding is BASE64:
-            return email.base64MIME.body_encode(s)
-        elif self.body_encoding is QP:
-            return email.quopriMIME.body_encode(s)
-        else:
-            return s

Deleted: trunk/tmda/TMDA/pythonlib/email/Encoders.py
===================================================================
--- trunk/tmda/TMDA/pythonlib/email/Encoders.py	2006-10-08 02:42:29 UTC (rev 2083)
+++ trunk/tmda/TMDA/pythonlib/email/Encoders.py	2006-10-08 02:50:58 UTC (rev 2084)
@@ -1,94 +0,0 @@
-# Copyright (C) 2001,2002 Python Software Foundation
-# Author: [email protected] (Barry Warsaw)
-
-"""Module containing encoding functions for Image.Image and Text.Text.
-"""
-
-import base64
-
-
-
-# Helpers
-try:
-    from quopri import encodestring as _encodestring
-
-    def _qencode(s):
-        enc = _encodestring(s, quotetabs=1)
-        # Must encode spaces, which quopri.encodestring() doesn't do
-        return enc.replace(' ', '=20')
-except ImportError:
-    # Python 2.1 doesn't have quopri.encodestring()
-    from cStringIO import StringIO
-    import quopri as _quopri
-
-    def _qencode(s):
-        if not s:
-            return s
-        hasnewline = (s[-1] == '\n')
-        infp = StringIO(s)
-        outfp = StringIO()
-        _quopri.encode(infp, outfp, quotetabs=1)
-        # Python 2.x's encode() doesn't encode spaces even when quotetabs==1
-        value = outfp.getvalue().replace(' ', '=20')
-        if not hasnewline and value[-1] == '\n':
-            return value[:-1]
-        return value
-
-
-def _bencode(s):
-    # We can't quite use base64.encodestring() since it tacks on a "courtesy
-    # newline".  Blech!
-    if not s:
-        return s
-    hasnewline = (s[-1] == '\n')
-    value = base64.encodestring(s)
-    if not hasnewline and value[-1] == '\n':
-        return value[:-1]
-    return value
-
-
-
-def encode_base64(msg):
-    """Encode the message's payload in Base64.
-
-    Also, add an appropriate Content-Transfer-Encoding header.
-    """
-    orig = msg.get_payload()
-    encdata = _bencode(orig)
-    msg.set_payload(encdata)
-    msg['Content-Transfer-Encoding'] = 'base64'
-
-
-
-def encode_quopri(msg):
-    """Encode the message's payload in quoted-printable.
-
-    Also, add an appropriate Content-Transfer-Encoding header.
-    """
-    orig = msg.get_payload()
-    encdata = _qencode(orig)
-    msg.set_payload(encdata)
-    msg['Content-Transfer-Encoding'] = 'quoted-printable'
-
-
-
-def encode_7or8bit(msg):
-    """Set the Content-Transfer-Encoding header to 7bit or 8bit."""
-    orig = msg.get_payload()
-    if orig is None:
-        # There's no payload.  For backwards compatibility we use 7bit
-        msg['Content-Transfer-Encoding'] = '7bit'
-        return
-    # We play a trick to make this go fast.  If encoding to ASCII succeeds, we
-    # know the data must be 7bit, otherwise treat it as 8bit.
-    try:
-        orig.encode('ascii')
-    except UnicodeError:
-        msg['Content-Transfer-Encoding'] = '8bit'
-    else:
-        msg['Content-Transfer-Encoding'] = '7bit'
-
-
-
-def encode_noop(msg):
-    """Do nothing."""

Deleted: trunk/tmda/TMDA/pythonlib/email/Errors.py
===================================================================
--- trunk/tmda/TMDA/pythonlib/email/Errors.py	2006-10-08 02:42:29 UTC (rev 2083)
+++ trunk/tmda/TMDA/pythonlib/email/Errors.py	2006-10-08 02:50:58 UTC (rev 2084)
@@ -1,26 +0,0 @@
-# Copyright (C) 2001,2002 Python Software Foundation
-# Author: [email protected] (Barry Warsaw)
-
-"""email package exception classes.
-"""
-
-
-
-class MessageError(Exception):
-    """Base class for errors in the email package."""
-
-
-class MessageParseError(MessageError):
-    """Base class for message parsing errors."""
-
-
-class HeaderParseError(MessageParseError):
-    """Error while parsing headers."""
-
-
-class BoundaryError(MessageParseError):
-    """Couldn't find terminating boundary."""
-
-
-class MultipartConversionError(MessageError, TypeError):
-    """Conversion to a multipart is prohibited."""

Deleted: trunk/tmda/TMDA/pythonlib/email/Generator.py
===================================================================
--- trunk/tmda/TMDA/pythonlib/email/Generator.py	2006-10-08 02:42:29 UTC (rev 2083)
+++ trunk/tmda/TMDA/pythonlib/email/Generator.py	2006-10-08 02:50:58 UTC (rev 2084)
@@ -1,398 +0,0 @@
-# Copyright (C) 2001,2002 Python Software Foundation
-# Author: [email protected] (Barry Warsaw)
-
-"""Classes to generate plain text from a message object tree.
-"""
-
-import re
-import sys
-import time
-import locale
-import random
-
-from types import ListType, StringType
-from cStringIO import StringIO
-
-from email.Header import Header
-from email.Parser import NLCRE
-
-try:
-    from email._compat22 import _isstring
-except SyntaxError:
-    from email._compat21 import _isstring
-
-try:
-    True, False
-except NameError:
-    True = 1
-    False = 0
-
-EMPTYSTRING = ''
-SEMISPACE = '; '
-BAR = '|'
-UNDERSCORE = '_'
-NL = '\n'
-NLTAB = '\n\t'
-SEMINLTAB = ';\n\t'
-SPACE8 = ' ' * 8
-
-fcre = re.compile(r'^From ', re.MULTILINE)
-
-def _is8bitstring(s):
-    if isinstance(s, StringType):
-        try:
-            unicode(s, 'us-ascii')
-        except UnicodeError:
-            return True
-    return False
-
-
-
-class Generator:
-    """Generates output from a Message object tree.
-
-    This basic generator writes the message to the given file object as plain
-    text.
-    """
-    #
-    # Public interface
-    #
-
-    def __init__(self, outfp, mangle_from_=True, maxheaderlen=78):
-        """Create the generator for message flattening.
-
-        outfp is the output file-like object for writing the message to.  It
-        must have a write() method.
-
-        Optional mangle_from_ is a flag that, when True (the default), escapes
-        From_ lines in the body of the message by putting a `>' in front of
-        them.
-
-        Optional maxheaderlen specifies the longest length for a non-continued
-        header.  When a header line is longer (in characters, with tabs
-        expanded to 8 spaces), than maxheaderlen, the header will be broken on
-        semicolons and continued as per RFC 2822.  If no semicolon is found,
-        then the header is left alone.  Set to zero to disable wrapping
-        headers.  Default is 78, as recommended (but not required by RFC
-        2822.
-        """
-        self._fp = outfp
-        self._mangle_from_ = mangle_from_
-        self.__maxheaderlen = maxheaderlen
-
-    def write(self, s):
-        # Just delegate to the file object
-        self._fp.write(s)
-
-    def flatten(self, msg, unixfrom=False):
-        """Print the message object tree rooted at msg to the output file
-        specified when the Generator instance was created.
-
-        unixfrom is a flag that forces the printing of a Unix From_ delimiter
-        before the first object in the message tree.  If the original message
-        has no From_ delimiter, a `standard' one is crafted.  By default, this
-        is False to inhibit the printing of any From_ delimiter.
-
-        Note that for subobjects, no From_ line is printed.
-        """
-        if unixfrom:
-            ufrom = msg.get_unixfrom()
-            if not ufrom:
-                ufrom = 'From nobody ' + time.ctime(time.time())
-            print >> self._fp, ufrom
-        self._write(msg)
-
-    # For backwards compatibility, but this is slower
-    __call__ = flatten
-
-    def clone(self, fp):
-        """Clone this generator with the exact same options."""
-        return self.__class__(fp, self._mangle_from_, self.__maxheaderlen)
-
-    #
-    # Protected interface - undocumented ;/
-    #
-
-    def _write(self, msg):
-        # We can't write the headers yet because of the following scenario:
-        # say a multipart message includes the boundary string somewhere in
-        # its body.  We'd have to calculate the new boundary /before/ we write
-        # the headers so that we can write the correct Content-Type:
-        # parameter.
-        #
-        # The way we do this, so as to make the _handle_*() methods simpler,
-        # is to cache any subpart writes into a StringIO.  The we write the
-        # headers and the StringIO contents.  That way, subpart handlers can
-        # Do The Right Thing, and can still modify the Content-Type: header if
-        # necessary.
-        oldfp = self._fp
-        try:
-            self._fp = sfp = StringIO()
-            self._dispatch(msg)
-        finally:
-            self._fp = oldfp
-        # Write the headers.  First we see if the message object wants to
-        # handle that itself.  If not, we'll do it generically.
-        meth = getattr(msg, '_write_headers', None)
-        if meth is None:
-            self._write_headers(msg)
-        else:
-            meth(self)
-        self._fp.write(sfp.getvalue())
-
-    def _dispatch(self, msg):
-        # Get the Content-Type: for the message, then try to dispatch to
-        # self._handle_<maintype>_<subtype>().  If there's no handler for the
-        # full MIME type, then dispatch to self._handle_<maintype>().  If
-        # that's missing too, then dispatch to self._writeBody().
-        main = msg.get_content_maintype()
-        sub = msg.get_content_subtype()
-        specific = UNDERSCORE.join((main, sub)).replace('-', '_')
-        meth = getattr(self, '_handle_' + specific, None)
-        if meth is None:
-            generic = main.replace('-', '_')
-            meth = getattr(self, '_handle_' + generic, None)
-            if meth is None:
-                meth = self._writeBody
-        meth(msg)
-
-    #
-    # Default handlers
-    #
-
-    def _write_headers(self, msg):
-        for h, v in msg.items():
-            print >> self._fp, '%s:' % h,
-            if self.__maxheaderlen == 0:
-                # Explicit no-wrapping
-                print >> self._fp, v
-            elif isinstance(v, Header):
-                # Header instances know what to do
-                print >> self._fp, v.encode()
-            elif _is8bitstring(v):
-                # If we have raw 8bit data in a byte string, we have no idea
-                # what the encoding is.  There is no safe way to split this
-                # string.  If it's ascii-subset, then we could do a normal
-                # ascii split, but if it's multibyte then we could break the
-                # string.  There's no way to know so the least harm seems to
-                # be to not split the string and risk it being too long.
-                print >> self._fp, v
-            else:
-                # Header's got lots of smarts, so use it.
-                print >> self._fp, Header(
-                    v, maxlinelen=self.__maxheaderlen,
-                    header_name=h, continuation_ws='\t').encode()
-        # A blank line always separates headers from body
-        print >> self._fp
-
-    #
-    # Handlers for writing types and subtypes
-    #
-
-    def _handle_text(self, msg):
-        payload = msg.get_payload()
-        if payload is None:
-            return
-        cset = msg.get_charset()
-        if cset is not None:
-            payload = cset.body_encode(payload)
-        if not _isstring(payload):
-            raise TypeError, 'string payload expected: %s' % type(payload)
-        if self._mangle_from_:
-            payload = fcre.sub('>From ', payload)
-        self._fp.write(payload)
-
-    # Default body handler
-    _writeBody = _handle_text
-
-    def _handle_multipart(self, msg):
-        # The trick here is to write out each part separately, merge them all
-        # together, and then make sure that the boundary we've chosen isn't
-        # present in the payload.
-        msgtexts = []
-        subparts = msg.get_payload()
-        if subparts is None:
-            # Nothing has ever been attached
-            boundary = msg.get_boundary(failobj=_make_boundary())
-            print >> self._fp, '--' + boundary
-            print >> self._fp, '\n'
-            print >> self._fp, '--' + boundary + '--'
-            return
-        elif _isstring(subparts):
-            # e.g. a non-strict parse of a message with no starting boundary.
-            self._fp.write(subparts)
-            return
-        elif not isinstance(subparts, ListType):
-            # Scalar payload
-            subparts = [subparts]
-        for part in subparts:
-            s = StringIO()
-            g = self.clone(s)
-            g.flatten(part, unixfrom=False)
-            msgtexts.append(s.getvalue())
-        # Now make sure the boundary we've selected doesn't appear in any of
-        # the message texts.
-        alltext = NL.join(msgtexts)
-        # BAW: What about boundaries that are wrapped in double-quotes?
-        boundary = msg.get_boundary(failobj=_make_boundary(alltext))
-        # If we had to calculate a new boundary because the body text
-        # contained that string, set the new boundary.  We don't do it
-        # unconditionally because, while set_boundary() preserves order, it
-        # doesn't preserve newlines/continuations in headers.  This is no big
-        # deal in practice, but turns out to be inconvenient for the unittest
-        # suite.
-        if msg.get_boundary() <> boundary:
-            msg.set_boundary(boundary)
-        # Write out any preamble
-        if msg.preamble is not None:
-            self._fp.write(msg.preamble)
-            # If preamble is the empty string, the length of the split will be
-            # 1, but the last element will be the empty string.  If it's
-            # anything else but does not end in a line separator, the length
-            # will be > 1 and not end in an empty string.  We need to
-            # guarantee a newline after the preamble, but don't add too many.
-            plines = NLCRE.split(msg.preamble)
-            if plines <> [''] and plines[-1] <> '':
-                self._fp.write('\n')
-        # First boundary is a bit different; it doesn't have a leading extra
-        # newline.
-        print >> self._fp, '--' + boundary
-        # Join and write the individual parts
-        joiner = '\n--' + boundary + '\n'
-        self._fp.write(joiner.join(msgtexts))
-        print >> self._fp, '\n--' + boundary + '--',
-        # Write out any epilogue
-        if msg.epilogue is not None:
-            if not msg.epilogue.startswith('\n'):
-                print >> self._fp
-            self._fp.write(msg.epilogue)
-
-    def _handle_message_delivery_status(self, msg):
-        # We can't just write the headers directly to self's file object
-        # because this will leave an extra newline between the last header
-        # block and the boundary.  Sigh.
-        blocks = []
-        for part in msg.get_payload():
-            s = StringIO()
-            g = self.clone(s)
-            g.flatten(part, unixfrom=False)
-            text = s.getvalue()
-            lines = text.split('\n')
-            # Strip off the unnecessary trailing empty line
-            if lines and lines[-1] == '':
-                blocks.append(NL.join(lines[:-1]))
-            else:
-                blocks.append(text)
-        # Now join all the blocks with an empty line.  This has the lovely
-        # effect of separating each block with an empty line, but not adding
-        # an extra one after the last one.
-        self._fp.write(NL.join(blocks))
-
-    def _handle_message(self, msg):
-        s = StringIO()
-        g = self.clone(s)
-        # The payload of a message/rfc822 part should be a multipart sequence
-        # of length 1.  The zeroth element of the list should be the Message
-        # object for the subpart.  Extract that object, stringify it, and
-        # write it out.
-        g.flatten(msg.get_payload(0), unixfrom=False)
-        self._fp.write(s.getvalue())
-
-
-
-class DecodedGenerator(Generator):
-    """Generator a text representation of a message.
-
-    Like the Generator base class, except that non-text parts are substituted
-    with a format string representing the part.
-    """
-    def __init__(self, outfp, mangle_from_=True, maxheaderlen=78, fmt=None):
-        """Like Generator.__init__() except that an additional optional
-        argument is allowed.
-
-        Walks through all subparts of a message.  If the subpart is of main
-        type `text', then it prints the decoded payload of the subpart.
-
-        Otherwise, fmt is a format string that is used instead of the message
-        payload.  fmt is expanded with the following keywords (in
-        %(keyword)s format):
-
-        type       : Full MIME type of the non-text part
-        maintype   : Main MIME type of the non-text part
-        subtype    : Sub-MIME type of the non-text part
-        filename   : Filename of the non-text part
-        description: Description associated with the non-text part
-        encoding   : Content transfer encoding of the non-text part
-
-        The default value for fmt is None, meaning
-
-        [Non-text (%(type)s) part of message omitted, filename %(filename)s]
-        """
-        Generator.__init__(self, outfp, mangle_from_, maxheaderlen)
-        if fmt is None:
-            fmt = ('[Non-text (%(type)s) part of message omitted, '
-                   'filename %(filename)s]')
-        self._fmt = fmt
-
-    def _dispatch(self, msg):
-        for part in msg.walk():
-            maintype = part.get_main_type('text')
-            if maintype == 'text':
-                print >> self, part.get_payload(decode=True)
-            elif maintype == 'multipart':
-                # Just skip this
-                pass
-            else:
-                print >> self, self._fmt % {
-                    'type'       : part.get_type('[no MIME type]'),
-                    'maintype'   : part.get_main_type('[no main MIME type]'),
-                    'subtype'    : part.get_subtype('[no sub-MIME type]'),
-                    'filename'   : part.get_filename('[no filename]'),
-                    'description': part.get('Content-Description',
-                                            '[no description]'),
-                    'encoding'   : part.get('Content-Transfer-Encoding',
-                                            '[no encoding]'),
-                    }
-
-
-
-class HeaderParsedGenerator(Generator):
-    """Generate text from a Message created by HeaderParser.
-
-    Header is generated as usual (by Generator).  The payload of a Message
-    created by HeaderParser is a raw string.  No encoding is necessary.  If it
-    came in valid, it goes out valid.  Conversely, if it came in bogus, it goes
-    out bogus.
-    """
-    def _dispatch(self, msg):
-        payload = msg.get_payload()
-        if payload is None:
-            return
-        if not _isstring(payload):
-            raise TypeError, 'string payload expected: %s' % type(payload)
-        if self._mangle_from_:
-            payload = fcre.sub('>From ', payload)
-        self._fp.write(payload)
-
-
-
-# Helper
-_width = len(repr(sys.maxint-1))
-_fmt = '%%0%dd' % _width
-
-def _make_boundary(text=None):
-    # Craft a random boundary.  If text is given, ensure that the chosen
-    # boundary doesn't appear in the text.
-    token = random.randrange(sys.maxint)
-    boundary = ('=' * 15) + (_fmt % token) + '=='
-    if text is None:
-        return boundary
-    b = boundary
-    counter = 0
-    while True:
-        cre = re.compile('^--' + re.escape(b) + '(--)?$', re.MULTILINE)
-        if not cre.search(text):
-            break
-        b = boundary + '.' + str(counter)
-        counter += 1
-    return b

Deleted: trunk/tmda/TMDA/pythonlib/email/Header.py
===================================================================
--- trunk/tmda/TMDA/pythonlib/email/Header.py	2006-10-08 02:42:29 UTC (rev 2083)
+++ trunk/tmda/TMDA/pythonlib/email/Header.py	2006-10-08 02:50:58 UTC (rev 2084)
@@ -1,515 +0,0 @@
-# Copyright (C) 2002 Python Software Foundation
-# Author: [email protected] (Ben Gertzfield), [email protected] (Barry Warsaw)
-
-"""Header encoding and decoding functionality."""
-
-import re
-import binascii
-from types import StringType, UnicodeType
-
-import email.quopriMIME
-import email.base64MIME
-from email.Errors import HeaderParseError
-from email.Charset import Charset
-
-try:
-    from email._compat22 import _floordiv
-except SyntaxError:
-    # Python 2.1 spells integer division differently
-    from email._compat21 import _floordiv
-
-try:
-    True, False
-except NameError:
-    True = 1
-    False = 0
-
-CRLFSPACE = '\r\n '
-CRLF = '\r\n'
-NL = '\n'
-SPACE = ' '
-USPACE = u' '
-SPACE8 = ' ' * 8
-EMPTYSTRING = ''
-UEMPTYSTRING = u''
-
-MAXLINELEN = 76
-
-ENCODE = 1
-DECODE = 2
-
-USASCII = Charset('us-ascii')
-UTF8 = Charset('utf-8')
-
-# Match encoded-word strings in the form =?charset?q?Hello_World?=
-ecre = re.compile(r'''
-  =\?                   # literal =?
-  (?P<charset>[^?]*?)   # non-greedy up to the next ? is the charset
-  \?                    # literal ?
-  (?P<encoding>[qb])    # either a "q" or a "b", case insensitive
-  \?                    # literal ?
-  (?P<encoded>.*?)      # non-greedy up to the next ?= is the encoded string
-  \?=                   # literal ?=
-  ''', re.VERBOSE | re.IGNORECASE)
-
-pcre = re.compile('([,;])')
-
-# Field name regexp, including trailing colon, but not separating whitespace,
-# according to RFC 2822.  Character range is from tilde to exclamation mark.
-# For use with .match()
-fcre = re.compile(r'[\041-\176]+:$')
-
-
-
-# Helpers
-_max_append = email.quopriMIME._max_append
-
-
-
-def decode_header(header):
-    """Decode a message header value without converting charset.
-
-    Returns a list of (decoded_string, charset) pairs containing each of the
-    decoded parts of the header.  Charset is None for non-encoded parts of the
-    header, otherwise a lower-case string containing the name of the character
-    set specified in the encoded string.
-
-    An email.Errors.HeaderParseError may be raised when certain decoding error
-    occurs (e.g. a base64 decoding exception).
-    """
-    # If no encoding, just return the header
-    header = str(header)
-    if not ecre.search(header):
-        return [(header, None)]
-    decoded = []
-    dec = ''
-    for line in header.splitlines():
-        # This line might not have an encoding in it
-        if not ecre.search(line):
-            decoded.append((line, None))
-            continue
-        parts = ecre.split(line)
-        while parts:
-            unenc = parts.pop(0).strip()
-            if unenc:
-                # Should we continue a long line?
-                if decoded and decoded[-1][1] is None:
-                    decoded[-1] = (decoded[-1][0] + SPACE + unenc, None)
-                else:
-                    decoded.append((unenc, None))
-            if parts:
-                charset, encoding = [s.lower() for s in parts[0:2]]
-                encoded = parts[2]
-                dec = None
-                if encoding == 'q':
-                    dec = email.quopriMIME.header_decode(encoded)
-                elif encoding == 'b':
-                    try:
-                        dec = email.base64MIME.decode(encoded)
-                    except binascii.Error:
-                        # Turn this into a higher level exception.  BAW: Right
-                        # now we throw the lower level exception away but
-                        # when/if we get exception chaining, we'll preserve it.
-                        raise HeaderParseError
-                if dec is None:
-                    dec = encoded
-
-                if decoded and decoded[-1][1] == charset:
-                    decoded[-1] = (decoded[-1][0] + dec, decoded[-1][1])
-                else:
-                    decoded.append((dec, charset))
-            del parts[0:3]
-    return decoded
-
-
-
-def make_header(decoded_seq, maxlinelen=None, header_name=None,
-                continuation_ws=' '):
-    """Create a Header from a sequence of pairs as returned by decode_header()
-
-    decode_header() takes a header value string and returns a sequence of
-    pairs of the format (decoded_string, charset) where charset is the string
-    name of the character set.
-
-    This function takes one of those sequence of pairs and returns a Header
-    instance.  Optional maxlinelen, header_name, and continuation_ws are as in
-    the Header constructor.
-    """
-    h = Header(maxlinelen=maxlinelen, header_name=header_name,
-               continuation_ws=continuation_ws)
-    for s, charset in decoded_seq:
-        # None means us-ascii but we can simply pass it on to h.append()
-        if charset is not None and not isinstance(charset, Charset):
-            charset = Charset(charset)
-        h.append(s, charset)
-    return h
-
-
-
-class Header:
-    def __init__(self, s=None, charset=None,
-                 maxlinelen=None, header_name=None,
-                 continuation_ws=' ', errors='strict'):
-        """Create a MIME-compliant header that can contain many character sets.
-
-        Optional s is the initial header value.  If None, the initial header
-        value is not set.  You can later append to the header with .append()
-        method calls.  s may be a byte string or a Unicode string, but see the
-        .append() documentation for semantics.
-
-        Optional charset serves two purposes: it has the same meaning as the
-        charset argument to the .append() method.  It also sets the default
-        character set for all subsequent .append() calls that omit the charset
-        argument.  If charset is not provided in the constructor, the us-ascii
-        charset is used both as s's initial charset and as the default for
-        subsequent .append() calls.
-
-        The maximum line length can be specified explicit via maxlinelen.  For
-        splitting the first line to a shorter value (to account for the field
-        header which isn't included in s, e.g. `Subject') pass in the name of
-        the field in header_name.  The default maxlinelen is 76.
-
-        continuation_ws must be RFC 2822 compliant folding whitespace (usually
-        either a space or a hard tab) which will be prepended to continuation
-        lines.
-
-        errors is passed through to the .append() call.
-        """
-        if charset is None:
-            charset = USASCII
-        if not isinstance(charset, Charset):
-            charset = Charset(charset)
-        self._charset = charset
-        self._continuation_ws = continuation_ws
-        cws_expanded_len = len(continuation_ws.replace('\t', SPACE8))
-        # BAW: I believe `chunks' and `maxlinelen' should be non-public.
-        self._chunks = []
-        if s is not None:
-            self.append(s, charset, errors)
-        if maxlinelen is None:
-            maxlinelen = MAXLINELEN
-        if header_name is None:
-            # We don't know anything about the field header so the first line
-            # is the same length as subsequent lines.
-            self._firstlinelen = maxlinelen
-        else:
-            # The first line should be shorter to take into account the field
-            # header.  Also subtract off 2 extra for the colon and space.
-            self._firstlinelen = maxlinelen - len(header_name) - 2
-        # Second and subsequent lines should subtract off the length in
-        # columns of the continuation whitespace prefix.
-        self._maxlinelen = maxlinelen - cws_expanded_len
-
-    def __str__(self):
-        """A synonym for self.encode()."""
-        return self.encode()
-
-    def __unicode__(self):
-        """Helper for the built-in unicode function."""
-        uchunks = []
-        lastcs = None
-        for s, charset in self._chunks:
-            # We must preserve spaces between encoded and non-encoded word
-            # boundaries, which means for us we need to add a space when we go
-            # from a charset to None/us-ascii, or from None/us-ascii to a
-            # charset.  Only do this for the second and subsequent chunks.
-            nextcs = charset
-            if uchunks:
-                if lastcs not in (None, 'us-ascii'):
-                    if nextcs in (None, 'us-ascii'):
-                        uchunks.append(USPACE)
-                        nextcs = None
-                elif nextcs not in (None, 'us-ascii'):
-                    uchunks.append(USPACE)
-            lastcs = nextcs
-            uchunks.append(unicode(s, str(charset)))
-        return UEMPTYSTRING.join(uchunks)
-
-    # Rich comparison operators for equality only.  BAW: does it make sense to
-    # have or explicitly disable <, <=, >, >= operators?
-    def __eq__(self, other):
-        # other may be a Header or a string.  Both are fine so coerce
-        # ourselves to a string, swap the args and do another comparison.
-        return other == self.encode()
-
-    def __ne__(self, other):
-        return not self == other
-
-    def append(self, s, charset=None, errors='strict'):
-        """Append a string to the MIME header.
-
-        Optional charset, if given, should be a Charset instance or the name
-        of a character set (which will be converted to a Charset instance).  A
-        value of None (the default) means that the charset given in the
-        constructor is used.
-
-        s may be a byte string or a Unicode string.  If it is a byte string
-        (i.e. isinstance(s, StringType) is true), then charset is the encoding
-        of that byte string, and a UnicodeError will be raised if the string
-        cannot be decoded with that charset.  If s is a Unicode string, then
-        charset is a hint specifying the character set of the characters in
-        the string.  In this case, when producing an RFC 2822 compliant header
-        using RFC 2047 rules, the Unicode string will be encoded using the
-        following charsets in order: us-ascii, the charset hint, utf-8.  The
-        first character set not to provoke a UnicodeError is used.
-
-        Optional `errors' is passed as the third argument to any unicode() or
-        ustr.encode() call.
-        """
-        if charset is None:
-            charset = self._charset
-        elif not isinstance(charset, Charset):
-            charset = Charset(charset)
-        # If the charset is our faux 8bit charset, leave the string unchanged
-        if charset <> '8bit':
-            # We need to test that the string can be converted to unicode and
-            # back to a byte string, given the input and output codecs of the
-            # charset.
-            if isinstance(s, StringType):
-                # Possibly raise UnicodeError if the byte string can't be
-                # converted to a unicode with the input codec of the charset.
-                incodec = charset.input_codec or 'us-ascii'
-                ustr = unicode(s, incodec, errors)
-                # Now make sure that the unicode could be converted back to a
-                # byte string with the output codec, which may be different
-                # than the iput coded.  Still, use the original byte string.
-                outcodec = charset.output_codec or 'us-ascii'
-                ustr.encode(outcodec, errors)
-            elif isinstance(s, UnicodeType):
-                # Now we have to be sure the unicode string can be converted
-                # to a byte string with a reasonable output codec.  We want to
-                # use the byte string in the chunk.
-                for charset in USASCII, charset, UTF8:
-                    try:
-                        outcodec = charset.output_codec or 'us-ascii'
-                        s = s.encode(outcodec, errors)
-                        break
-                    except UnicodeError:
-                        pass
-                else:
-                    assert False, 'utf-8 conversion failed'
-        self._chunks.append((s, charset))
-
-    def _split(self, s, charset, maxlinelen, splitchars):
-        # Split up a header safely for use with encode_chunks.
-        splittable = charset.to_splittable(s)
-        encoded = charset.from_splittable(splittable, True)
-        elen = charset.encoded_header_len(encoded)
-        # If the line's encoded length first, just return it
-        if elen <= maxlinelen:
-            return [(encoded, charset)]
-        # If we have undetermined raw 8bit characters sitting in a byte
-        # string, we really don't know what the right thing to do is.  We
-        # can't really split it because it might be multibyte data which we
-        # could break if we split it between pairs.  The least harm seems to
-        # be to not split the header at all, but that means they could go out
-        # longer than maxlinelen.
-        if charset == '8bit':
-            return [(s, charset)]
-        # BAW: I'm not sure what the right test here is.  What we're trying to
-        # do is be faithful to RFC 2822's recommendation that ($2.2.3):
-        #
-        # "Note: Though structured field bodies are defined in such a way that
-        #  folding can take place between many of the lexical tokens (and even
-        #  within some of the lexical tokens), folding SHOULD be limited to
-        #  placing the CRLF at higher-level syntactic breaks."
-        #
-        # For now, I can only imagine doing this when the charset is us-ascii,
-        # although it's possible that other charsets may also benefit from the
-        # higher-level syntactic breaks.
-        elif charset == 'us-ascii':
-            return self._split_ascii(s, charset, maxlinelen, splitchars)
-        # BAW: should we use encoded?
-        elif elen == len(s):
-            # We can split on _maxlinelen boundaries because we know that the
-            # encoding won't change the size of the string
-            splitpnt = maxlinelen
-            first = charset.from_splittable(splittable[:splitpnt], False)
-            last = charset.from_splittable(splittable[splitpnt:], False)
-        else:
-            # Binary search for split point
-            first, last = _binsplit(splittable, charset, maxlinelen)
-        # first is of the proper length so just wrap it in the appropriate
-        # chrome.  last must be recursively split.
-        fsplittable = charset.to_splittable(first)
-        fencoded = charset.from_splittable(fsplittable, True)
-        chunk = [(fencoded, charset)]
-        return chunk + self._split(last, charset, self._maxlinelen, splitchars)
-
-    def _split_ascii(self, s, charset, firstlen, splitchars):
-        chunks = _split_ascii(s, firstlen, self._maxlinelen,
-                              self._continuation_ws, splitchars)
-        return zip(chunks, [charset]*len(chunks))
-
-    def _encode_chunks(self, newchunks, maxlinelen):
-        # MIME-encode a header with many different charsets and/or encodings.
-        #
-        # Given a list of pairs (string, charset), return a MIME-encoded
-        # string suitable for use in a header field.  Each pair may have
-        # different charsets and/or encodings, and the resulting header will
-        # accurately reflect each setting.
-        #
-        # Each encoding can be email.Utils.QP (quoted-printable, for
-        # ASCII-like character sets like iso-8859-1), email.Utils.BASE64
-        # (Base64, for non-ASCII like character sets like KOI8-R and
-        # iso-2022-jp), or None (no encoding).
-        #
-        # Each pair will be represented on a separate line; the resulting
-        # string will be in the format:
-        #
-        # =?charset1?q?Mar=EDa_Gonz=E1lez_Alonso?=\n
-        #  =?charset2?b?SvxyZ2VuIEL2aW5n?="
-        chunks = []
-        for header, charset in newchunks:
-            if not header:
-                continue
-            if charset is None or charset.header_encoding is None:
-                s = header
-            else:
-                s = charset.header_encode(header)
-            # Don't add more folding whitespace than necessary
-            if chunks and chunks[-1].endswith(' '):
-                extra = ''
-            else:
-                extra = ' '
-            _max_append(chunks, s, maxlinelen, extra)
-        joiner = NL + self._continuation_ws
-        return joiner.join(chunks)
-
-    def encode(self, splitchars=';, '):
-        """Encode a message header into an RFC-compliant format.
-
-        There are many issues involved in converting a given string for use in
-        an email header.  Only certain character sets are readable in most
-        email clients, and as header strings can only contain a subset of
-        7-bit ASCII, care must be taken to properly convert and encode (with
-        Base64 or quoted-printable) header strings.  In addition, there is a
-        75-character length limit on any given encoded header field, so
-        line-wrapping must be performed, even with double-byte character sets.
-
-        This method will do its best to convert the string to the correct
-        character set used in email, and encode and line wrap it safely with
-        the appropriate scheme for that character set.
-
-        If the given charset is not known or an error occurs during
-        conversion, this function will return the header untouched.
-
-        Optional splitchars is a string containing characters to split long
-        ASCII lines on, in rough support of RFC 2822's `highest level
-        syntactic breaks'.  This doesn't affect RFC 2047 encoded lines.
-        """
-        newchunks = []
-        maxlinelen = self._firstlinelen
-        lastlen = 0
-        for s, charset in self._chunks:
-            # The first bit of the next chunk should be just long enough to
-            # fill the next line.  Don't forget the space separating the
-            # encoded words.
-            targetlen = maxlinelen - lastlen - 1
-            if targetlen < charset.encoded_header_len(''):
-                # Stick it on the next line
-                targetlen = maxlinelen
-            newchunks += self._split(s, charset, targetlen, splitchars)
-            lastchunk, lastcharset = newchunks[-1]
-            lastlen = lastcharset.encoded_header_len(lastchunk)
-        return self._encode_chunks(newchunks, maxlinelen)
-
-
-
-def _split_ascii(s, firstlen, restlen, continuation_ws, splitchars):
-    lines = []
-    maxlen = firstlen
-    for line in s.splitlines():
-        # Ignore any leading whitespace (i.e. continuation whitespace) already
-        # on the line, since we'll be adding our own.
-        line = line.lstrip()
-        if len(line) < maxlen:
-            lines.append(line)
-            maxlen = restlen
-            continue
-        # Attempt to split the line at the highest-level syntactic break
-        # possible.  Note that we don't have a lot of smarts about field
-        # syntax; we just try to break on semi-colons, then commas, then
-        # whitespace.
-        for ch in splitchars:
-            if line.find(ch) >= 0:
-                break
-        else:
-            # There's nothing useful to split the line on, not even spaces, so
-            # just append this line unchanged
-            lines.append(line)
-            maxlen = restlen
-            continue
-        # Now split the line on the character plus trailing whitespace
-        cre = re.compile(r'%s\s*' % ch)
-        if ch in ';,':
-            eol = ch
-        else:
-            eol = ''
-        joiner = eol + ' '
-        joinlen = len(joiner)
-        wslen = len(continuation_ws.replace('\t', SPACE8))
-        this = []
-        linelen = 0
-        for part in cre.split(line):
-            curlen = linelen + max(0, len(this)-1) * joinlen
-            partlen = len(part)
-            onfirstline = not lines
-            # We don't want to split after the field name, if we're on the
-            # first line and the field name is present in the header string.
-            if ch == ' ' and onfirstline and \
-                   len(this) == 1 and fcre.match(this[0]):
-                this.append(part)
-                linelen += partlen
-            elif curlen + partlen > maxlen:
-                if this:
-                    lines.append(joiner.join(this) + eol)
-                # If this part is longer than maxlen and we aren't already
-                # splitting on whitespace, try to recursively split this line
-                # on whitespace.
-                if partlen > maxlen and ch <> ' ':
-                    subl = _split_ascii(part, maxlen, restlen,
-                                        continuation_ws, ' ')
-                    lines.extend(subl[:-1])
-                    this = [subl[-1]]
-                else:
-                    this = [part]
-                linelen = wslen + len(this[-1])
-                maxlen = restlen
-            else:
-                this.append(part)
-                linelen += partlen
-        # Put any left over parts on a line by themselves
-        if this:
-            lines.append(joiner.join(this))
-    return lines
-
-
-
-def _binsplit(splittable, charset, maxlinelen):
-    i = 0
-    j = len(splittable)
-    while i < j:
-        # Invariants:
-        # 1. splittable[:k] fits for all k <= i (note that we *assume*,
-        #    at the start, that splittable[:0] fits).
-        # 2. splittable[:k] does not fit for any k > j (at the start,
-        #    this means we shouldn't look at any k > len(splittable)).
-        # 3. We don't know about splittable[:k] for k in i+1..j.
-        # 4. We want to set i to the largest k that fits, with i <= k <= j.
-        #
-        m = (i+j+1) >> 1  # ceiling((i+j)/2); i < m <= j
-        chunk = charset.from_splittable(splittable[:m], True)
-        chunklen = charset.encoded_header_len(chunk)
-        if chunklen <= maxlinelen:
-            # m is acceptable, so is a new lower bound.
-            i = m
-        else:
-            # m is not acceptable, so final i must be < m.
-            j = m - 1
-    # i == j.  Invariant #1 implies that splittable[:i] fits, and
-    # invariant #2 implies that splittable[:i+1] does not fit, so i
-    # is what we're looking for.
-    first = charset.from_splittable(splittable[:i], False)
-    last  = charset.from_splittable(splittable[i:], False)
-    return first, last

Deleted: trunk/tmda/TMDA/pythonlib/email/Iterators.py
===================================================================
--- trunk/tmda/TMDA/pythonlib/email/Iterators.py	2006-10-08 02:42:29 UTC (rev 2083)
+++ trunk/tmda/TMDA/pythonlib/email/Iterators.py	2006-10-08 02:50:58 UTC (rev 2084)
@@ -1,25 +0,0 @@
-# Copyright (C) 2001,2002 Python Software Foundation
-# Author: [email protected] (Barry Warsaw)
-
-"""Various types of useful iterators and generators.
-"""
-
-import sys
-
-try:
-    from email._compat22 import body_line_iterator, typed_subpart_iterator
-except SyntaxError:
-    # Python 2.1 doesn't have generators
-    from email._compat21 import body_line_iterator, typed_subpart_iterator
-
-
-
-def _structure(msg, fp=None, level=0):
-    """A handy debugging aid"""
-    if fp is None:
-        fp = sys.stdout
-    tab = ' ' * (level * 4)
-    print >> fp, tab + msg.get_content_type()
-    if msg.is_multipart():
-        for subpart in msg.get_payload():
-            _structure(subpart, fp, level+1)

Deleted: trunk/tmda/TMDA/pythonlib/email/MIMEAudio.py
===================================================================
--- trunk/tmda/TMDA/pythonlib/email/MIMEAudio.py	2006-10-08 02:42:29 UTC (rev 2083)
+++ trunk/tmda/TMDA/pythonlib/email/MIMEAudio.py	2006-10-08 02:50:58 UTC (rev 2084)
@@ -1,71 +0,0 @@
-# Author: Anthony Baxter
-
-"""Class representing audio/* type MIME documents.
-"""
-
-import sndhdr
-from cStringIO import StringIO
-
-from email import Errors
-from email import Encoders
-from email.MIMENonMultipart import MIMENonMultipart
-
-
-
-_sndhdr_MIMEmap = {'au'  : 'basic',
-                   'wav' :'x-wav',
-                   'aiff':'x-aiff',
-                   'aifc':'x-aiff',
-                   }
-
-# There are others in sndhdr that don't have MIME types. :(
-# Additional ones to be added to sndhdr? midi, mp3, realaudio, wma??
-def _whatsnd(data):
-    """Try to identify a sound file type.
-
-    sndhdr.what() has a pretty cruddy interface, unfortunately.  This is why
-    we re-do it here.  It would be easier to reverse engineer the Unix 'file'
-    command and use the standard 'magic' file, as shipped with a modern Unix.
-    """
-    hdr = data[:512]
-    fakefile = StringIO(hdr)
-    for testfn in sndhdr.tests:
-        res = testfn(hdr, fakefile)
-        if res is not None:
-            return _sndhdr_MIMEmap.get(res[0])
-    return None
-
-
-
-class MIMEAudio(MIMENonMultipart):
-    """Class for generating audio/* MIME documents."""
-
-    def __init__(self, _audiodata, _subtype=None,
-                 _encoder=Encoders.encode_base64, **_params):
-        """Create an audio/* type MIME document.
-
-        _audiodata is a string containing the raw audio data.  If this data
-        can be decoded by the standard Python `sndhdr' module, then the
-        subtype will be automatically included in the Content-Type header.
-        Otherwise, you can specify  the specific audio subtype via the
-        _subtype parameter.  If _subtype is not given, and no subtype can be
-        guessed, a TypeError is raised.
-
-        _encoder is a function which will perform the actual encoding for
-        transport of the image data.  It takes one argument, which is this
-        Image instance.  It should use get_payload() and set_payload() to
-        change the payload to the encoded form.  It should also add any
-        Content-Transfer-Encoding or other headers to the message as
-        necessary.  The default encoding is Base64.
-
-        Any additional keyword arguments are passed to the base class
-        constructor, which turns them into parameters on the Content-Type
-        header.
-        """
-        if _subtype is None:
-            _subtype = _whatsnd(_audiodata)
-        if _subtype is None:
-            raise TypeError, 'Could not find audio MIME subtype'
-        MIMENonMultipart.__init__(self, 'audio', _subtype, **_params)
-        self.set_payload(_audiodata)
-        _encoder(self)

Deleted: trunk/tmda/TMDA/pythonlib/email/MIMEBase.py
===================================================================
--- trunk/tmda/TMDA/pythonlib/email/MIMEBase.py	2006-10-08 02:42:29 UTC (rev 2083)
+++ trunk/tmda/TMDA/pythonlib/email/MIMEBase.py	2006-10-08 02:50:58 UTC (rev 2084)
@@ -1,24 +0,0 @@
-# Copyright (C) 2001,2002 Python Software Foundation
-# Author: [email protected] (Barry Warsaw)
-
-"""Base class for MIME specializations.
-"""
-
-from email import Message
-
-
-
-class MIMEBase(Message.Message):
-    """Base class for MIME specializations."""
-
-    def __init__(self, _maintype, _subtype, **_params):
-        """This constructor adds a Content-Type: and a MIME-Version: header.
-
-        The Content-Type: header is taken from the _maintype and _subtype
-        arguments.  Additional parameters for this header are taken from the
-        keyword arguments.
-        """
-        Message.Message.__init__(self)
-        ctype = '%s/%s' % (_maintype, _subtype)
-        self.add_header('Content-Type', ctype, **_params)
-        self['MIME-Version'] = '1.0'

Deleted: trunk/tmda/TMDA/pythonlib/email/MIMEImage.py
===================================================================
--- trunk/tmda/TMDA/pythonlib/email/MIMEImage.py	2006-10-08 02:42:29 UTC (rev 2083)
+++ trunk/tmda/TMDA/pythonlib/email/MIMEImage.py	2006-10-08 02:50:58 UTC (rev 2084)
@@ -1,45 +0,0 @@
-# Copyright (C) 2001,2002 Python Software Foundation
-# Author: [email protected] (Barry Warsaw)
-
-"""Class representing image/* type MIME documents.
-"""
-
-import imghdr
-
-from email import Errors
-from email import Encoders
-from email.MIMENonMultipart import MIMENonMultipart
-
-
-
-class MIMEImage(MIMENonMultipart):
-    """Class for generating image/* type MIME documents."""
-
-    def __init__(self, _imagedata, _subtype=None,
-                 _encoder=Encoders.encode_base64, **_params):
-        """Create an image/* type MIME document.
-
-        _imagedata is a string containing the raw image data.  If this data
-        can be decoded by the standard Python `imghdr' module, then the
-        subtype will be automatically included in the Content-Type header.
-        Otherwise, you can specify the specific image subtype via the _subtype
-        parameter.
-
-        _encoder is a function which will perform the actual encoding for
-        transport of the image data.  It takes one argument, which is this
-        Image instance.  It should use get_payload() and set_payload() to
-        change the payload to the encoded form.  It should also add any
-        Content-Transfer-Encoding or other headers to the message as
-        necessary.  The default encoding is Base64.
-
-        Any additional keyword arguments are passed to the base class
-        constructor, which turns them into parameters on the Content-Type
-        header.
-        """
-        if _subtype is None:
-            _subtype = imghdr.what(None, _imagedata)
-        if _subtype is None:
-            raise TypeError, 'Could not guess image MIME subtype'
-        MIMENonMultipart.__init__(self, 'image', _subtype, **_params)
-        self.set_payload(_imagedata)
-        _encoder(self)

Deleted: trunk/tmda/TMDA/pythonlib/email/MIMEMessage.py
===================================================================
--- trunk/tmda/TMDA/pythonlib/email/MIMEMessage.py	2006-10-08 02:42:29 UTC (rev 2083)
+++ trunk/tmda/TMDA/pythonlib/email/MIMEMessage.py	2006-10-08 02:50:58 UTC (rev 2084)
@@ -1,32 +0,0 @@
-# Copyright (C) 2001,2002 Python Software Foundation
-# Author: [email protected] (Barry Warsaw)
-
-"""Class representing message/* MIME documents.
-"""
-
-from email import Message
-from email.MIMENonMultipart import MIMENonMultipart
-
-
-
-class MIMEMessage(MIMENonMultipart):
-    """Class representing message/* MIME documents."""
-
-    def __init__(self, _msg, _subtype='rfc822'):
-        """Create a message/* type MIME document.
-
-        _msg is a message object and must be an instance of Message, or a
-        derived class of Message, otherwise a TypeError is raised.
-
-        Optional _subtype defines the subtype of the contained message.  The
-        default is "rfc822" (this is defined by the MIME standard, even though
-        the term "rfc822" is technically outdated by RFC 2822).
-        """
-        MIMENonMultipart.__init__(self, 'message', _subtype)
-        if not isinstance(_msg, Message.Message):
-            raise TypeError, 'Argument is not an instance of Message'
-        # It's convenient to use this base class method.  We need to do it
-        # this way or we'll get an exception
-        Message.Message.attach(self, _msg)
-        # And be sure our default type is set correctly
-        self.set_default_type('message/rfc822')

Deleted: trunk/tmda/TMDA/pythonlib/email/MIMEMultipart.py
===================================================================
--- trunk/tmda/TMDA/pythonlib/email/MIMEMultipart.py	2006-10-08 02:42:29 UTC (rev 2083)
+++ trunk/tmda/TMDA/pythonlib/email/MIMEMultipart.py	2006-10-08 02:50:58 UTC (rev 2084)
@@ -1,37 +0,0 @@
-# Copyright (C) 2002 Python Software Foundation
-# Author: [email protected] (Barry Warsaw)
-
-"""Base class for MIME multipart/* type messages.
-"""
-
-from email import MIMEBase
-
-
-
-class MIMEMultipart(MIMEBase.MIMEBase):
-    """Base class for MIME multipart/* type messages."""
-
-    def __init__(self, _subtype='mixed', boundary=None, *_subparts, **_params):
-        """Creates a multipart/* type message.
-
-        By default, creates a multipart/mixed message, with proper
-        Content-Type and MIME-Version headers.
-
-        _subtype is the subtype of the multipart content type, defaulting to
-        `mixed'.
-
-        boundary is the multipart boundary string.  By default it is
-        calculated as needed.
-
-        _subparts is a sequence of initial subparts for the payload.  It
-        must be possible to convert this sequence to a list.  You can always
-        attach new subparts to the message by using the attach() method.
-
-        Additional parameters for the Content-Type header are taken from the
-        keyword arguments (or passed into the _params argument).
-        """
-        MIMEBase.MIMEBase.__init__(self, 'multipart', _subtype, **_params)
-        if _subparts:
-            self.attach(*list(_subparts))
-        if boundary:
-            self.set_boundary(boundary)

Deleted: trunk/tmda/TMDA/pythonlib/email/MIMENonMultipart.py
===================================================================
--- trunk/tmda/TMDA/pythonlib/email/MIMENonMultipart.py	2006-10-08 02:42:29 UTC (rev 2083)
+++ trunk/tmda/TMDA/pythonlib/email/MIMENonMultipart.py	2006-10-08 02:50:58 UTC (rev 2084)
@@ -1,24 +0,0 @@
-# Copyright (C) 2002 Python Software Foundation
-# Author: [email protected] (Barry Warsaw)
-
-"""Base class for MIME type messages that are not multipart.
-"""
-
-from email import Errors
-from email import MIMEBase
-
-
-
-class MIMENonMultipart(MIMEBase.MIMEBase):
-    """Base class for MIME multipart/* type messages."""
-
-    __pychecker__ = 'unusednames=payload'
-
-    def attach(self, payload):
-        # The public API prohibits attaching multiple subparts to MIMEBase
-        # derived subtypes since none of them are, by definition, of content
-        # type multipart/*
-        raise Errors.MultipartConversionError(
-            'Cannot attach additional subparts to non-multipart/*')
-
-    del __pychecker__

Deleted: trunk/tmda/TMDA/pythonlib/email/MIMEText.py
===================================================================
--- trunk/tmda/TMDA/pythonlib/email/MIMEText.py	2006-10-08 02:42:29 UTC (rev 2083)
+++ trunk/tmda/TMDA/pythonlib/email/MIMEText.py	2006-10-08 02:50:58 UTC (rev 2084)
@@ -1,45 +0,0 @@
-# Copyright (C) 2001,2002 Python Software Foundation
-# Author: [email protected] (Barry Warsaw)
-
-"""Class representing text/* type MIME documents.
-"""
-
-import warnings
-from email.MIMENonMultipart import MIMENonMultipart
-from email.Encoders import encode_7or8bit
-
-
-
-class MIMEText(MIMENonMultipart):
-    """Class for generating text/* type MIME documents."""
-
-    def __init__(self, _text, _subtype='plain', _charset='us-ascii',
-                 _encoder=None):
-        """Create a text/* type MIME document.
-
-        _text is the string for this message object.
-
-        _subtype is the MIME sub content type, defaulting to "plain".
-
-        _charset is the character set parameter added to the Content-Type
-        header.  This defaults to "us-ascii".  Note that as a side-effect, the
-        Content-Transfer-Encoding header will also be set.
-
-        The use of the _encoder is deprecated.  The encoding of the payload,
-        and the setting of the character set parameter now happens implicitly
-        based on the _charset argument.  If _encoder is supplied, then a
-        DeprecationWarning is used, and the _encoder functionality may
-        override any header settings indicated by _charset.  This is probably
-        not what you want.
-        """
-        MIMENonMultipart.__init__(self, 'text', _subtype,
-                                  **{'charset': _charset})
-        self.set_payload(_text, _charset)
-        if _encoder is not None:
-            warnings.warn('_encoder argument is obsolete.',
-                          DeprecationWarning, 2)
-            # Because set_payload() with a _charset will set its own
-            # Content-Transfer-Encoding header, we need to delete the
-            # existing one or will end up with two of them. :(
-            del self['content-transfer-encoding']
-            _encoder(self)

Deleted: trunk/tmda/TMDA/pythonlib/email/Message.py
===================================================================
--- trunk/tmda/TMDA/pythonlib/email/Message.py	2006-10-08 02:42:29 UTC (rev 2083)
+++ trunk/tmda/TMDA/pythonlib/email/Message.py	2006-10-08 02:50:58 UTC (rev 2084)
@@ -1,837 +0,0 @@
-# Copyright (C) 2001,2002 Python Software Foundation
-# Author: [email protected] (Barry Warsaw)
-
-"""Basic message object for the email package object model.
-"""
-
-import re
-import uu
-import binascii
-import warnings
-from cStringIO import StringIO
-from types import ListType, TupleType, StringType
-
-# Intrapackage imports
-from email import Utils
-from email import Errors
-from email import Charset
-
-SEMISPACE = '; '
-
-try:
-    True, False
-except NameError:
-    True = 1
-    False = 0
-
-# Regular expression used to split header parameters.  BAW: this may be too
-# simple.  It isn't strictly RFC 2045 (section 5.1) compliant, but it catches
-# most headers found in the wild.  We may eventually need a full fledged
-# parser eventually.
-paramre = re.compile(r'\s*;\s*')
-# Regular expression that matches `special' characters in parameters, the
-# existance of which force quoting of the parameter value.
-tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
-
-
-
-# Helper functions
-def _formatparam(param, value=None, quote=True):
-    """Convenience function to format and return a key=value pair.
-
-    This will quote the value if needed or if quote is true.
-    """
-    if value is not None and len(value) > 0:
-        # TupleType is used for RFC 2231 encoded parameter values where items
-        # are (charset, language, value).  charset is a string, not a Charset
-        # instance.
-        if isinstance(value, TupleType):
-            # Encode as per RFC 2231
-            param += '*'
-            value = Utils.encode_rfc2231(value[2], value[0], value[1])
-        # BAW: Please check this.  I think that if quote is set it should
-        # force quoting even if not necessary.
-        if quote or tspecials.search(value):
-            return '%s="%s"' % (param, Utils.quote(value))
-        else:
-            return '%s=%s' % (param, value)
-    else:
-        return param
-
-def _parseparam(s):
-    plist = []
-    while s[:1] == ';':
-        s = s[1:]
-        end = s.find(';')
-        while end > 0 and s.count('"', 0, end) % 2:
-            end = s.find(';', end + 1)
-        if end < 0:
-            end = len(s)
-        f = s[:end]
-        if '=' in f:
-            i = f.index('=')
-            f = f[:i].strip().lower() + '=' + f[i+1:].strip()
-        plist.append(f.strip())
-        s = s[end:]
-    return plist
-
-
-def _unquotevalue(value):
-    if isinstance(value, TupleType):
-        return value[0], value[1], Utils.unquote(value[2])
-    else:
-        return Utils.unquote(value)
-
-
-
-class Message:
-    """Basic message object.
-
-    A message object is defined as something that has a bunch of RFC 2822
-    headers and a payload.  It may optionally have an envelope header
-    (a.k.a. Unix-From or From_ header).  If the message is a container (i.e. a
-    multipart or a message/rfc822), then the payload is a list of Message
-    objects, otherwise it is a string.
-
-    Message objects implement part of the `mapping' interface, which assumes
-    there is exactly one occurrance of the header per message.  Some headers
-    do in fact appear multiple times (e.g. Received) and for those headers,
-    you must use the explicit API to set or get all the headers.  Not all of
-    the mapping methods are implemented.
-    """
-    def __init__(self):
-        self._headers = []
-        self._unixfrom = None
-        self._payload = None
-        self._charset = None
-        # Defaults for multipart messages
-        self.preamble = self.epilogue = None
-        # Default content type
-        self._default_type = 'text/plain'
-
-    def __str__(self):
-        """Return the entire formatted message as a string.
-        This includes the headers, body, and envelope header.
-        """
-        return self.as_string(unixfrom=True)
-
-    def as_string(self, unixfrom=False):
-        """Return the entire formatted message as a string.
-        Optional `unixfrom' when True, means include the Unix From_ envelope
-        header.
-
-        This is a convenience method and may not generate the message exactly
-        as you intend.  For more flexibility, use the flatten() method of a
-        Generator instance.
-        """
-        from email.Generator import Generator
-        fp = StringIO()
-        g = Generator(fp)
-        g.flatten(self, unixfrom=unixfrom)
-        return fp.getvalue()
-
-    def is_multipart(self):
-        """Return True if the message consists of multiple parts."""
-        if isinstance(self._payload, ListType):
-            return True
-        return False
-
-    #
-    # Unix From_ line
-    #
-    def set_unixfrom(self, unixfrom):
-        self._unixfrom = unixfrom
-
-    def get_unixfrom(self):
-        return self._unixfrom
-
-    #
-    # Payload manipulation.
-    #
-    def add_payload(self, payload):
-        """Add the given payload to the current payload.
-
-        If the current payload is empty, then the current payload will be made
-        a scalar, set to the given value.
-
-        Note: This method is deprecated.  Use .attach() instead.
-        """
-        warnings.warn('add_payload() is deprecated, use attach() instead.',
-                      DeprecationWarning, 2)
-        if self._payload is None:
-            self._payload = payload
-        elif isinstance(self._payload, ListType):
-            self._payload.append(payload)
-        elif self.get_main_type() not in (None, 'multipart'):
-            raise Errors.MultipartConversionError(
-                'Message main content type must be "multipart" or missing')
-        else:
-            self._payload = [self._payload, payload]
-
-    def attach(self, payload):
-        """Add the given payload to the current payload.
-
-        The current payload will always be a list of objects after this method
-        is called.  If you want to set the payload to a scalar object, use
-        set_payload() instead.
-        """
-        if self._payload is None:
-            self._payload = [payload]
-        else:
-            self._payload.append(payload)
-
-    def get_payload(self, i=None, decode=False):
-        """Return a reference to the payload.
-
-        The payload will either be a list object or a string.  If you mutate
-        the list object, you modify the message's payload in place.  Optional
-        i returns that index into the payload.
-
-        Optional decode is a flag indicating whether the payload should be
-        decoded or not, according to the Content-Transfer-Encoding header
-        (default is False).
-
-        When True and the message is not a multipart, the payload will be
-        decoded if this header's value is `quoted-printable' or `base64'.  If
-        some other encoding is used, or the header is missing, or if the
-        payload has bogus data (i.e. bogus base64 or uuencoded data), the
-        payload is returned as-is.
-
-        If the message is a multipart and the decode flag is True, then None
-        is returned.
-        """
-        if i is None:
-            payload = self._payload
-        elif not isinstance(self._payload, ListType):
-            raise TypeError, 'Expected list, got %s' % type(self._payload)
-        else:
-            payload = self._payload[i]
-        if decode:
-            if self.is_multipart():
-                return None
-            cte = self.get('content-transfer-encoding', '').lower()
-            if cte == 'quoted-printable':
-                return Utils._qdecode(payload)
-            elif cte == 'base64':
-                try:
-                    return Utils._bdecode(payload)
-                except binascii.Error:
-                    # Incorrect padding
-                    return payload
-            elif cte in ('x-uuencode', 'uuencode', 'uue', 'x-uue'):
-                sfp = StringIO()
-                try:
-                    uu.decode(StringIO(payload+'\n'), sfp)
-                    payload = sfp.getvalue()
-                except uu.Error:
-                    # Some decoding problem
-                    return payload
-        # Everything else, including encodings with 8bit or 7bit are returned
-        # unchanged.
-        return payload
-
-    def set_payload(self, payload, charset=None):
-        """Set the payload to the given value.
-
-        Optional charset sets the message's default character set.  See
-        set_charset() for details.
-        """
-        self._payload = payload
-        if charset is not None:
-            self.set_charset(charset)
-
-    def set_charset(self, charset):
-        """Set the charset of the payload to a given character set.
-
-        charset can be a Charset instance, a string naming a character set, or
-        None.  If it is a string it will be converted to a Charset instance.
-        If charset is None, the charset parameter will be removed from the
-        Content-Type field.  Anything else will generate a TypeError.
-
-        The message will be assumed to be of type text/* encoded with
-        charset.input_charset.  It will be converted to charset.output_charset
-        and encoded properly, if needed, when generating the plain text
-        representation of the message.  MIME headers (MIME-Version,
-        Content-Type, Content-Transfer-Encoding) will be added as needed.
-
-        """
-        if charset is None:
-            self.del_param('charset')
-            self._charset = None
-            return
-        if isinstance(charset, StringType):
-            charset = Charset.Charset(charset)
-        if not isinstance(charset, Charset.Charset):
-            raise TypeError, charset
-        # BAW: should we accept strings that can serve as arguments to the
-        # Charset constructor?
-        self._charset = charset
-        if not self.has_key('MIME-Version'):
-            self.add_header('MIME-Version', '1.0')
-        if not self.has_key('Content-Type'):
-            self.add_header('Content-Type', 'text/plain',
-                            charset=charset.get_output_charset())
-        else:
-            self.set_param('charset', charset.get_output_charset())
-        if not self.has_key('Content-Transfer-Encoding'):
-            cte = charset.get_body_encoding()
-            if callable(cte):
-                cte(self)
-            else:
-                self.add_header('Content-Transfer-Encoding', cte)
-
-    def get_charset(self):
-        """Return the Charset instance associated with the message's payload.
-        """
-        return self._charset
-
-    #
-    # MAPPING INTERFACE (partial)
-    #
-    def __len__(self):
-        """Return the total number of headers, including duplicates."""
-        return len(self._headers)
-
-    def __getitem__(self, name):
-        """Get a header value.
-
-        Return None if the header is missing instead of raising an exception.
-
-        Note that if the header appeared multiple times, exactly which
-        occurrance gets returned is undefined.  Use getall() to get all
-        the values matching a header field name.
-        """
-        return self.get(name)
-
-    def __setitem__(self, name, val):
-        """Set the value of a header.
-
-        Note: this does not overwrite an existing header with the same field
-        name.  Use __delitem__() first to delete any existing headers.
-        """
-        self._headers.append((name, val))
-
-    def __delitem__(self, name):
-        """Delete all occurrences of a header, if present.
-
-        Does not raise an exception if the header is missing.
-        """
-        name = name.lower()
-        newheaders = []
-        for k, v in self._headers:
-            if k.lower() <> name:
-                newheaders.append((k, v))
-        self._headers = newheaders
-
-    def __contains__(self, name):
-        return name.lower() in [k.lower() for k, v in self._headers]
-
-    def has_key(self, name):
-        """Return true if the message contains the header."""
-        missing = []
-        return self.get(name, missing) is not missing
-
-    def keys(self):
-        """Return a list of all the message's header field names.
-
-        These will be sorted in the order they appeared in the original
-        message, or were added to the message, and may contain duplicates.
-        Any fields deleted and re-inserted are always appended to the header
-        list.
-        """
-        return [k for k, v in self._headers]
-
-    def values(self):
-        """Return a list of all the message's header values.
-
-        These will be sorted in the order they appeared in the original
-        message, or were added to the message, and may contain duplicates.
-        Any fields deleted and re-inserted are always appended to the header
-        list.
-        """
-        return [v for k, v in self._headers]
-
-    def items(self):
-        """Get all the message's header fields and values.
-
-        These will be sorted in the order they appeared in the original
-        message, or were added to the message, and may contain duplicates.
-        Any fields deleted and re-inserted are always appended to the header
-        list.
-        """
-        return self._headers[:]
-
-    def get(self, name, failobj=None):
-        """Get a header value.
-
-        Like __getitem__() but return failobj instead of None when the field
-        is missing.
-        """
-        name = name.lower()
-        for k, v in self._headers:
-            if k.lower() == name:
-                return v
-        return failobj
-
-    #
-    # Additional useful stuff
-    #
-
-    def get_all(self, name, failobj=None):
-        """Return a list of all the values for the named field.
-
-        These will be sorted in the order they appeared in the original
-        message, and may contain duplicates.  Any fields deleted and
-        re-inserted are always appended to the header list.
-
-        If no such fields exist, failobj is returned (defaults to None).
-        """
-        values = []
-        name = name.lower()
-        for k, v in self._headers:
-            if k.lower() == name:
-                values.append(v)
-        if not values:
-            return failobj
-        return values
-
-    def add_header(self, _name, _value, **_params):
-        """Extended header setting.
-
-        name is the header field to add.  keyword arguments can be used to set
-        additional parameters for the header field, with underscores converted
-        to dashes.  Normally the parameter will be added as key="value" unless
-        value is None, in which case only the key will be added.
-
-        Example:
-
-        msg.add_header('content-disposition', 'attachment', filename='bud.gif')
-        """
-        parts = []
-        for k, v in _params.items():
-            if v is None:
-                parts.append(k.replace('_', '-'))
-            else:
-                parts.append(_formatparam(k.replace('_', '-'), v))
-        if _value is not None:
-            parts.insert(0, _value)
-        self._headers.append((_name, SEMISPACE.join(parts)))
-
-    def replace_header(self, _name, _value):
-        """Replace a header.
-
-        Replace the first matching header found in the message, retaining
-        header order and case.  If no matching header was found, a KeyError is
-        raised.
-        """
-        _name = _name.lower()
-        for i, (k, v) in zip(range(len(self._headers)), self._headers):
-            if k.lower() == _name:
-                self._headers[i] = (k, _value)
-                break
-        else:
-            raise KeyError, _name
-
-    #
-    # These methods are silently deprecated in favor of get_content_type() and
-    # friends (see below).  They will be noisily deprecated in email 3.0.
-    #
-
-    def get_type(self, failobj=None):
-        """Returns the message's content type.
-
-        The returned string is coerced to lowercase and returned as a single
-        string of the form `maintype/subtype'.  If there was no Content-Type
-        header in the message, failobj is returned (defaults to None).
-        """
-        missing = []
-        value = self.get('content-type', missing)
-        if value is missing:
-            return failobj
-        return paramre.split(value)[0].lower().strip()
-
-    def get_main_type(self, failobj=None):
-        """Return the message's main content type if present."""
-        missing = []
-        ctype = self.get_type(missing)
-        if ctype is missing:
-            return failobj
-        if ctype.count('/') <> 1:
-            return failobj
-        return ctype.split('/')[0]
-
-    def get_subtype(self, failobj=None):
-        """Return the message's content subtype if present."""
-        missing = []
-        ctype = self.get_type(missing)
-        if ctype is missing:
-            return failobj
-        if ctype.count('/') <> 1:
-            return failobj
-        return ctype.split('/')[1]
-
-    #
-    # Use these three methods instead of the three above.
-    #
-
-    def get_content_type(self):
-        """Return the message's content type.
-
-        The returned string is coerced to lower case of the form
-        `maintype/subtype'.  If there was no Content-Type header in the
-        message, the default type as given by get_default_type() will be
-        returned.  Since according to RFC 2045, messages always have a default
-        type this will always return a value.
-
-        RFC 2045 defines a message's default type to be text/plain unless it
-        appears inside a multipart/digest container, in which case it would be
-        message/rfc822.
-        """
-        missing = []
-        value = self.get('content-type', missing)
-        if value is missing:
-            # This should have no parameters
-            return self.get_default_type()
-        ctype = paramre.split(value)[0].lower().strip()
-        # RFC 2045, section 5.2 says if its invalid, use text/plain
-        if ctype.count('/') <> 1:
-            return 'text/plain'
-        return ctype
-
-    def get_content_maintype(self):
-        """Return the message's main content type.
-
-        This is the `maintype' part of the string returned by
-        get_content_type().
-        """
-        ctype = self.get_content_type()
-        return ctype.split('/')[0]
-
-    def get_content_subtype(self):
-        """Returns the message's sub-content type.
-
-        This is the `subtype' part of the string returned by
-        get_content_type().
-        """
-        ctype = self.get_content_type()
-        return ctype.split('/')[1]
-
-    def get_default_type(self):
-        """Return the `default' content type.
-
-        Most messages have a default content type of text/plain, except for
-        messages that are subparts of multipart/digest containers.  Such
-        subparts have a default content type of message/rfc822.
-        """
-        return self._default_type
-
-    def set_default_type(self, ctype):
-        """Set the `default' content type.
-
-        ctype should be either "text/plain" or "message/rfc822", although this
-        is not enforced.  The default content type is not stored in the
-        Content-Type header.
-        """
-        self._default_type = ctype
-
-    def _get_params_preserve(self, failobj, header):
-        # Like get_params() but preserves the quoting of values.  BAW:
-        # should this be part of the public interface?
-        missing = []
-        value = self.get(header, missing)
-        if value is missing:
-            return failobj
-        params = []
-        for p in _parseparam(';' + value):
-            try:
-                name, val = p.split('=', 1)
-                name = name.strip()
-                val = val.strip()
-            except ValueError:
-                # Must have been a bare attribute
-                name = p.strip()
-                val = ''
-            params.append((name, val))
-        params = Utils.decode_params(params)
-        return params
-
-    def get_params(self, failobj=None, header='content-type', unquote=True):
-        """Return the message's Content-Type parameters, as a list.
-
-        The elements of the returned list are 2-tuples of key/value pairs, as
-        split on the `=' sign.  The left hand side of the `=' is the key,
-        while the right hand side is the value.  If there is no `=' sign in
-        the parameter the value is the empty string.  The value is as
-        described in the get_param() method.
-
-        Optional failobj is the object to return if there is no Content-Type
-        header.  Optional header is the header to search instead of
-        Content-Type.  If unquote is True, the value is unquoted.
-        """
-        missing = []
-        params = self._get_params_preserve(missing, header)
-        if params is missing:
-            return failobj
-        if unquote:
-            return [(k, _unquotevalue(v)) for k, v in params]
-        else:
-            return params
-
-    def get_param(self, param, failobj=None, header='content-type',
-                  unquote=True):
-        """Return the parameter value if found in the Content-Type header.
-
-        Optional failobj is the object to return if there is no Content-Type
-        header, or the Content-Type header has no such parameter.  Optional
-        header is the header to search instead of Content-Type.
-
-        Parameter keys are always compared case insensitively.  The return
-        value can either be a string, or a 3-tuple if the parameter was RFC
-        2231 encoded.  When it's a 3-tuple, the elements of the value are of
-        the form (CHARSET, LANGUAGE, VALUE).  Note that both CHARSET and
-        LANGUAGE can be None, in which case you should consider VALUE to be
-        encoded in the us-ascii charset.  You can usually ignore LANGUAGE.
-
-        Your application should be prepared to deal with 3-tuple return
-        values, and can convert the parameter to a Unicode string like so:
-
-            param = msg.get_param('foo')
-            if isinstance(param, tuple):
-                param = unicode(param[2], param[0] or 'us-ascii')
-
-        In any case, the parameter value (either the returned string, or the
-        VALUE item in the 3-tuple) is always unquoted, unless unquote is set
-        to False.
-        """
-        if not self.has_key(header):
-            return failobj
-        for k, v in self._get_params_preserve(failobj, header):
-            if k.lower() == param.lower():
-                if unquote:
-                    return _unquotevalue(v)
-                else:
-                    return v
-        return failobj
-
-    def set_param(self, param, value, header='Content-Type', requote=True,
-                  charset=None, language=''):
-        """Set a parameter in the Content-Type header.
-
-        If the parameter already exists in the header, its value will be
-        replaced with the new value.
-
-        If header is Content-Type and has not yet been defined for this
-        message, it will be set to "text/plain" and the new parameter and
-        value will be appended as per RFC 2045.
-
-        An alternate header can specified in the header argument, and all
-        parameters will be quoted as necessary unless requote is False.
-
-        If charset is specified, the parameter will be encoded according to RFC
-        2231.  Optional language specifies the RFC 2231 language, defaulting
-        to the empty string.  Both charset and language should be strings.
-        """
-        if not isinstance(value, TupleType) and charset:
-            value = (charset, language, value)
-
-        if not self.has_key(header) and header.lower() == 'content-type':
-            ctype = 'text/plain'
-        else:
-            ctype = self.get(header)
-        if not self.get_param(param, header=header):
-            if not ctype:
-                ctype = _formatparam(param, value, requote)
-            else:
-                ctype = SEMISPACE.join(
-                    [ctype, _formatparam(param, value, requote)])
-        else:
-            ctype = ''
-            for old_param, old_value in self.get_params(header=header,
-                                                        unquote=requote):
-                append_param = ''
-                if old_param.lower() == param.lower():
-                    append_param = _formatparam(param, value, requote)
-                else:
-                    append_param = _formatparam(old_param, old_value, requote)
-                if not ctype:
-                    ctype = append_param
-                else:
-                    ctype = SEMISPACE.join([ctype, append_param])
-        if ctype <> self.get(header):
-            del self[header]
-            self[header] = ctype
-
-    def del_param(self, param, header='content-type', requote=True):
-        """Remove the given parameter completely from the Content-Type header.
-
-        The header will be re-written in place without the parameter or its
-        value. All values will be quoted as necessary unless requote is
-        False.  Optional header specifies an alternative to the Content-Type
-        header.
-        """
-        if not self.has_key(header):
-            return
-        new_ctype = ''
-        for p, v in self.get_params(header, unquote=requote):
-            if p.lower() <> param.lower():
-                if not new_ctype:
-                    new_ctype = _formatparam(p, v, requote)
-                else:
-                    new_ctype = SEMISPACE.join([new_ctype,
-                                                _formatparam(p, v, requote)])
-        if new_ctype <> self.get(header):
-            del self[header]
-            self[header] = new_ctype
-
-    def set_type(self, type, header='Content-Type', requote=True):
-        """Set the main type and subtype for the Content-Type header.
-
-        type must be a string in the form "maintype/subtype", otherwise a
-        ValueError is raised.
-
-        This method replaces the Content-Type header, keeping all the
-        parameters in place.  If requote is False, this leaves the existing
-        header's quoting as is.  Otherwise, the parameters will be quoted (the
-        default).
-
-        An alternative header can be specified in the header argument.  When
-        the Content-Type header is set, we'll always also add a MIME-Version
-        header.
-        """
-        # BAW: should we be strict?
-        if not type.count('/') == 1:
-            raise ValueError
-        # Set the Content-Type, you get a MIME-Version
-        if header.lower() == 'content-type':
-            del self['mime-version']
-            self['MIME-Version'] = '1.0'
-        if not self.has_key(header):
-            self[header] = type
-            return
-        params = self.get_params(header, unquote=requote)
-        del self[header]
-        self[header] = type
-        # Skip the first param; it's the old type.
-        for p, v in params[1:]:
-            self.set_param(p, v, header, requote)
-
-    def get_filename(self, failobj=None):
-        """Return the filename associated with the payload if present.
-
-        The filename is extracted from the Content-Disposition header's
-        `filename' parameter, and it is unquoted.
-        """
-        missing = []
-        filename = self.get_param('filename', missing, 'content-disposition')
-        if filename is missing:
-            return failobj
-        if isinstance(filename, TupleType):
-            # It's an RFC 2231 encoded parameter
-            newvalue = _unquotevalue(filename)
-            return unicode(newvalue[2], newvalue[0] or 'us-ascii')
-        else:
-            newvalue = _unquotevalue(filename.strip())
-            return newvalue
-
-    def get_boundary(self, failobj=None):
-        """Return the boundary associated with the payload if present.
-
-        The boundary is extracted from the Content-Type header's `boundary'
-        parameter, and it is unquoted.
-        """
-        missing = []
-        boundary = self.get_param('boundary', missing)
-        if boundary is missing:
-            return failobj
-        if isinstance(boundary, TupleType):
-            # RFC 2231 encoded, so decode.  It better end up as ascii
-            charset = boundary[0] or 'us-ascii'
-            return unicode(boundary[2], charset).encode('us-ascii')
-        return _unquotevalue(boundary.strip())
-
-    def set_boundary(self, boundary):
-        """Set the boundary parameter in Content-Type to 'boundary'.
-
-        This is subtly different than deleting the Content-Type header and
-        adding a new one with a new boundary parameter via add_header().  The
-        main difference is that using the set_boundary() method preserves the
-        order of the Content-Type header in the original message.
-
-        HeaderParseError is raised if the message has no Content-Type header.
-        """
-        missing = []
-        params = self._get_params_preserve(missing, 'content-type')
-        if params is missing:
-            # There was no Content-Type header, and we don't know what type
-            # to set it to, so raise an exception.
-            raise Errors.HeaderParseError, 'No Content-Type header found'
-        newparams = []
-        foundp = False
-        for pk, pv in params:
-            if pk.lower() == 'boundary':
-                newparams.append(('boundary', '"%s"' % boundary))
-                foundp = True
-            else:
-                newparams.append((pk, pv))
-        if not foundp:
-            # The original Content-Type header had no boundary attribute.
-            # Tack one on the end.  BAW: should we raise an exception
-            # instead???
-            newparams.append(('boundary', '"%s"' % boundary))

@@ Diff output truncated at 100000 characters. @@

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.