Kaydet (Commit) 18ff7954 authored tarafından Barry Warsaw's avatar Barry Warsaw

Backporting of email 2.4 from Python 2.3. Many newly added modules,

some updated modules, updated documentation, and updated tests.  Note
that Lib/test/regrtest.py added test_email_codecs to the expected
skips for all platforms.  Also note that test_email_codecs.py differs
slightly from its Python 2.3 counterpart due to the difference in
package location for TestSkipped.
üst 5b70f66b
This diff is collapsed.
......@@ -17,8 +17,8 @@ set the \mailheader{Content-Transfer-Encoding} header as appropriate.
Here are the encoding functions provided:
\begin{funcdesc}{encode_quopri}{msg}
Encodes the payload into \emph{Quoted-Printable} form and sets the
\code{Content-Transfer-Encoding:} header to
Encodes the payload into quoted-printable form and sets the
\mailheader{Content-Transfer-Encoding} header to
\code{quoted-printable}\footnote{Note that encoding with
\method{encode_quopri()} also encodes all tabs and space characters in
the data.}.
......@@ -27,11 +27,11 @@ printable data, but contains a few unprintable characters.
\end{funcdesc}
\begin{funcdesc}{encode_base64}{msg}
Encodes the payload into \emph{Base64} form and sets the
Encodes the payload into base64 form and sets the
\mailheader{Content-Transfer-Encoding} header to
\code{base64}. This is a good encoding to use when most of your payload
is unprintable data since it is a more compact form than
Quoted-Printable. The drawback of Base64 encoding is that it
quoted-printable. The drawback of base64 encoding is that it
renders the text non-human readable.
\end{funcdesc}
......
......@@ -21,7 +21,7 @@ a message, this class is derived from \exception{MessageParseError}.
It can be raised from the \method{Parser.parse()} or
\method{Parser.parsestr()} methods.
Situations where it can be raised include finding a \emph{Unix-From}
Situations where it can be raised include finding an envelope
header after the first \rfc{2822} header of the message, finding a
continuation line before the first \rfc{2822} header is found, or finding
a line in the headers which is neither a header or a continuation
......@@ -35,7 +35,8 @@ It can be raised from the \method{Parser.parse()} or
\method{Parser.parsestr()} methods.
Situations where it can be raised include not being able to find the
starting or terminating boundary in a \mimetype{multipart/*} message.
starting or terminating boundary in a \mimetype{multipart/*} message
when strict parsing is used.
\end{excclassdesc}
\begin{excclassdesc}{MultipartConversionError}{}
......@@ -45,4 +46,9 @@ message's \mailheader{Content-Type} main type is not either
\mimetype{multipart} or missing. \exception{MultipartConversionError}
multiply inherits from \exception{MessageError} and the built-in
\exception{TypeError}.
Since \method{Message.add_payload()} is deprecated, this exception is
rarely raised in practice. However the exception may also be raised
if the \method{attach()} method is called on an instance of a class
derived from \class{MIMENonMultipart} (e.g. \class{MIMEImage}).
\end{excclassdesc}
\declaremodule{standard}{email.Generator}
\modulesynopsis{Generate flat text email messages from a message object tree.}
\modulesynopsis{Generate flat text email messages from a message structure.}
One of the most common tasks is to generate the flat text of the email
message represented by a message object tree. You will need to do
message represented by a message object structure. You will need to do
this if you want to send your message via the \refmodule{smtplib}
module or the \refmodule{nntplib} module, or print the message on the
console. Taking a message object tree and producing a flat text
console. Taking a message object structure and producing a flat text
document is the job of the \class{Generator} class.
Again, as with the \refmodule{email.Parser} module, you aren't limited
......@@ -13,10 +13,9 @@ to the functionality of the bundled generator; you could write one
from scratch yourself. However the bundled generator knows how to
generate most email in a standards-compliant way, should handle MIME
and non-MIME email messages just fine, and is designed so that the
transformation from flat text, to an object tree via the
\class{Parser} class,
and back to flat text, is idempotent (the input is identical to the
output).
transformation from flat text, to a message structure via the
\class{Parser} class, and back to flat text, is idempotent (the input
is identical to the output).
Here are the public methods of the \class{Generator} class:
......@@ -25,16 +24,18 @@ Here are the public methods of the \class{Generator} class:
The constructor for the \class{Generator} class takes a file-like
object called \var{outfp} for an argument. \var{outfp} must support
the \method{write()} method and be usable as the output file in a
Python 2.0 extended print statement.
Python extended print statement.
Optional \var{mangle_from_} is a flag that, when true, puts a \samp{>}
character in front of any line in the body that starts exactly as
\samp{From } (i.e. \code{From} followed by a space at the front of the
line). This is the only guaranteed portable way to avoid having such
lines be mistaken for \emph{Unix-From} headers (see
Optional \var{mangle_from_} is a flag that, when \code{True}, puts a
\samp{>} character in front of any line in the body that starts exactly as
\samp{From }, i.e. \code{From} followed by a space at the beginning of the
line. This is the only guaranteed portable way to avoid having such
lines be mistaken for a Unix mailbox format envelope header separator (see
\ulink{WHY THE CONTENT-LENGTH FORMAT IS BAD}
{http://home.netscape.com/eng/mozilla/2.0/relnotes/demo/content-length.html}
for details).
for details). \var{mangle_from_} defaults to \code{True}, but you
might want to set this to \code{False} if you are not writing Unix
mailbox format files.
Optional \var{maxheaderlen} specifies the longest length for a
non-continued header. When a header line is longer than
......@@ -47,20 +48,28 @@ recommended (but not required) by \rfc{2822}.
The other public \class{Generator} methods are:
\begin{methoddesc}[Generator]{__call__}{msg\optional{, unixfrom}}
Print the textual representation of the message object tree rooted at
\begin{methoddesc}[Generator]{flatten}{msg\optional{, unixfrom}}
Print the textual representation of the message object structure rooted at
\var{msg} to the output file specified when the \class{Generator}
instance was created. Sub-objects are visited depth-first and the
instance was created. Subparts are visited depth-first and the
resulting text will be properly MIME encoded.
Optional \var{unixfrom} is a flag that forces the printing of the
\emph{Unix-From} (a.k.a. envelope header or \code{From_} header)
delimiter before the first \rfc{2822} header of the root message
object. If the root object has no \emph{Unix-From} header, a standard
one is crafted. By default, this is set to 0 to inhibit the printing
of the \emph{Unix-From} delimiter.
envelope header delimiter before the first \rfc{2822} header of the
root message object. If the root object has no envelope header, a
standard one is crafted. By default, this is set to \code{False} to
inhibit the printing of the envelope delimiter.
Note that for subparts, no envelope header is ever printed.
Note that for sub-objects, no \emph{Unix-From} header is ever printed.
\versionadded{2.2.2}
\end{methoddesc}
\begin{methoddesc}[Generator]{clone}{fp}
Return an independent clone of this \class{Generator} instance with
the exact same options.
\versionadded{2.2.2}
\end{methoddesc}
\begin{methoddesc}[Generator]{write}{s}
......@@ -74,3 +83,59 @@ As a convenience, see the methods \method{Message.as_string()} and
\code{str(aMessage)}, a.k.a. \method{Message.__str__()}, which
simplify the generation of a formatted string representation of a
message object. For more detail, see \refmodule{email.Message}.
The \module{email.Generator} module also provides a derived class,
called \class{DecodedGenerator} which is like the \class{Generator}
base class, except that non-\mimetype{text} parts are substituted with
a format string representing the part.
\begin{classdesc}{DecodedGenerator}{outfp\optional{, mangle_from_\optional{,
maxheaderlen\optional{, fmt}}}}
This class, derived from \class{Generator} walks through all the
subparts of a message. If the subpart is of main type
\mimetype{text}, then it prints the decoded payload of the subpart.
Optional \var{_mangle_from_} and \var{maxheaderlen} are as with the
\class{Generator} base class.
If the subpart is not of main type \mimetype{text}, optional \var{fmt}
is a format string that is used instead of the message payload.
\var{fmt} is expanded with the following keywords, \samp{\%(keyword)s}
format:
\begin{itemize}
\item \code{type} -- Full MIME type of the non-\mimetype{text} part
\item \code{maintype} -- Main MIME type of the non-\mimetype{text} part
\item \code{subtype} -- Sub-MIME type of the non-\mimetype{text} part
\item \code{filename} -- Filename of the non-\mimetype{text} part
\item \code{description} -- Description associated with the
non-\mimetype{text} part
\item \code{encoding} -- Content transfer encoding of the
non-\mimetype{text} part
\end{itemize}
The default value for \var{fmt} is \code{None}, meaning
\begin{verbatim}
[Non-text (%(type)s) part of message omitted, filename %(filename)s]
\end{verbatim}
\versionadded{2.2.2}
\end{classdesc}
\subsubsection{Deprecated methods}
The following methods are deprecated in \module{email} version 2.
They are documented here for completeness.
\begin{methoddesc}[Generator]{__call__}{msg\optional{, unixfrom}}
This method is identical to the \method{flatten()} method.
\deprecated{2.2.2}{Use the \method{flatten()} method instead.}
\end{methoddesc}
......@@ -29,3 +29,35 @@ Thus, by default \function{typed_subpart_iterator()} returns each
subpart that has a MIME type of \mimetype{text/*}.
\end{funcdesc}
The following function has been added as a useful debugging tool. It
should \emph{not} be considered part of the supported public interface
for the package.
\begin{funcdesc}{_structure}{msg\optional{, fp\optional{, level}}}
Prints an indented representation of the content types of the
message object structure. For example:
\begin{verbatim}
>>> msg = email.message_from_file(somefile)
>>> _structure(msg)
multipart/mixed
text/plain
text/plain
multipart/digest
message/rfc822
text/plain
message/rfc822
text/plain
message/rfc822
text/plain
message/rfc822
text/plain
message/rfc822
text/plain
text/plain
\end{verbatim}
Optional \var{fp} is a file-like object to print the output to. It
must be suitable for Python's extended print statement. \var{level}
is used internally.
\end{funcdesc}
This diff is collapsed.
\declaremodule{standard}{email.Parser}
\modulesynopsis{Parse flat text email messages to produce a message
object tree.}
object structure.}
Message object trees can be created in one of two ways: they can be
Message object structures can be created in one of two ways: they can be
created from whole cloth by instantiating \class{Message} objects and
stringing them together via \method{add_payload()} and
stringing them together via \method{attach()} and
\method{set_payload()} calls, or they can be created by parsing a flat text
representation of the email message.
The \module{email} package provides a standard parser that understands
most email document structures, including MIME documents. You can
pass the parser a string or a file object, and the parser will return
to you the root \class{Message} instance of the object tree. For
to you the root \class{Message} instance of the object structure. For
simple, non-MIME messages the payload of this root object will likely
be a string containing the text of the message. For MIME
messages, the root object will return true from its
messages, the root object will return \code{True} from its
\method{is_multipart()} method, and the subparts can be accessed via
the \method{get_payload()} and \method{walk()} methods.
......@@ -27,61 +27,95 @@ message object trees any way it finds necessary.
The primary parser class is \class{Parser} which parses both the
headers and the payload of the message. In the case of
\mimetype{multipart} messages, it will recursively parse the body of
the container message. The \module{email.Parser} module also provides
a second class, called \class{HeaderParser} which can be used if
you're only interested in the headers of the message.
\class{HeaderParser} can be much faster in this situations, since it
does not attempt to parse the message body, instead setting the
payload to the raw body as a string. \class{HeaderParser} has the
same API as the \class{Parser} class.
the container message. Two modes of parsing are supported,
\emph{strict} parsing, which will usually reject any non-RFC compliant
message, and \emph{lax} parsing, which attempts to adjust for common
MIME formatting problems.
The \module{email.Parser} module also provides a second class, called
\class{HeaderParser} which can be used if you're only interested in
the headers of the message. \class{HeaderParser} can be much faster in
these situations, since it does not attempt to parse the message body,
instead setting the payload to the raw body as a string.
\class{HeaderParser} has the same API as the \class{Parser} class.
\subsubsection{Parser class API}
\begin{classdesc}{Parser}{\optional{_class}}
The constructor for the \class{Parser} class takes a single optional
\begin{classdesc}{Parser}{\optional{_class\optional{, strict}}}
The constructor for the \class{Parser} class takes an optional
argument \var{_class}. This must be a callable factory (such as a
function or a class), and it is used whenever a sub-message object
needs to be created. It defaults to \class{Message} (see
\refmodule{email.Message}). The factory will be called without
arguments.
The optional \var{strict} flag specifies whether strict or lax parsing
should be performed. Normally, when things like MIME terminating
boundaries are missing, or when messages contain other formatting
problems, the \class{Parser} will raise a
\exception{MessageParseError}. However, when lax parsing is enabled,
the \class{Parser} will attempt to work around such broken formatting
to produce a usable message structure (this doesn't mean
\exception{MessageParseError}s are never raised; some ill-formatted
messages just can't be parsed). The \var{strict} flag defaults to
\code{False} since lax parsing usually provides the most convenient
behavior.
\versionchanged[The \var{strict} flag was added]{2.2.2}
\end{classdesc}
The other public \class{Parser} methods are:
\begin{methoddesc}[Parser]{parse}{fp}
\begin{methoddesc}[Parser]{parse}{fp\optional{, headersonly}}
Read all the data from the file-like object \var{fp}, parse the
resulting text, and return the root message object. \var{fp} must
support both the \method{readline()} and the \method{read()} methods
on file-like objects.
The text contained in \var{fp} must be formatted as a block of \rfc{2822}
style headers and header continuation lines, optionally preceeded by a
\emph{Unix-From} header. The header block is terminated either by the
style headers and header continuation lines, optionally preceded by a
envelope header. The header block is terminated either by the
end of the data or by a blank line. Following the header block is the
body of the message (which may contain MIME-encoded subparts).
Optional \var{headersonly} is as with the \method{parse()} method.
\versionchanged[The \var{headersonly} flag was added]{2.2.2}
\end{methoddesc}
\begin{methoddesc}[Parser]{parsestr}{text}
\begin{methoddesc}[Parser]{parsestr}{text\optional{, headersonly}}
Similar to the \method{parse()} method, except it takes a string
object instead of a file-like object. Calling this method on a string
is exactly equivalent to wrapping \var{text} in a \class{StringIO}
instance first and calling \method{parse()}.
Optional \var{headersonly} is a flag specifying whether to stop
parsing after reading the headers or not. The default is \code{False},
meaning it parses the entire contents of the file.
\versionchanged[The \var{headersonly} flag was added]{2.2.2}
\end{methoddesc}
Since creating a message object tree from a string or a file object is
such a common task, two functions are provided as a convenience. They
are available in the top-level \module{email} package namespace.
Since creating a message object structure from a string or a file
object is such a common task, two functions are provided as a
convenience. They are available in the top-level \module{email}
package namespace.
\begin{funcdesc}{message_from_string}{s\optional{, _class\optional{, strict}}}
Return a message object structure from a string. This is exactly
equivalent to \code{Parser().parsestr(s)}. Optional \var{_class} and
\var{strict} are interpreted as with the \class{Parser} class constructor.
\begin{funcdesc}{message_from_string}{s\optional{, _class}}
Return a message object tree from a string. This is exactly
equivalent to \code{Parser().parsestr(s)}. Optional \var{_class} is
interpreted as with the \class{Parser} class constructor.
\versionchanged[The \var{strict} flag was added]{2.2.2}
\end{funcdesc}
\begin{funcdesc}{message_from_file}{fp\optional{, _class}}
Return a message object tree from an open file object. This is exactly
equivalent to \code{Parser().parse(fp)}. Optional \var{_class} is
interpreted as with the \class{Parser} class constructor.
\begin{funcdesc}{message_from_file}{fp\optional{, _class\optional{, strict}}}
Return a message object structure tree from an open file object. This
is exactly equivalent to \code{Parser().parse(fp)}. Optional
\var{_class} and \var{strict} are interpreted as with the
\class{Parser} class constructor.
\versionchanged[The \var{strict} flag was added]{2.2.2}
\end{funcdesc}
Here's an example of how you might use this at an interactive Python
......@@ -99,15 +133,20 @@ Here are some notes on the parsing semantics:
\begin{itemize}
\item Most non-\mimetype{multipart} type messages are parsed as a single
message object with a string payload. These objects will return
0 for \method{is_multipart()}.
\item One exception is for \mimetype{message/delivery-status} type
messages. Because the body of such messages consist of
blocks of headers, \class{Parser} will create a non-multipart
object containing non-multipart subobjects for each header
block.
\item Another exception is for \mimetype{message/*} types (more
general than \mimetype{message/delivery-status}). These are
typically \mimetype{message/rfc822} messages, represented as a
non-multipart object containing a singleton payload which is
another non-multipart \class{Message} instance.
\code{False} for \method{is_multipart()}. Their
\method{get_payload()} method will return a string object.
\item All \mimetype{multipart} type messages will be parsed as a
container message object with a list of sub-message objects for
their payload. The outer container message will return
\code{True} for \method{is_multipart()} and their
\method{get_payload()} method will return the list of
\class{Message} subparts.
\item Most messages with a content type of \mimetype{message/*}
(e.g. \mimetype{message/deliver-status} and
\mimetype{message/rfc822}) will also be parsed as container
object containing a list payload of length 1. Their
\method{is_multipart()} method will return \code{True}. The
single element in the list payload will be a sub-message object.
\end{itemize}
......@@ -6,7 +6,7 @@ package.
\begin{funcdesc}{quote}{str}
Return a new string with backslashes in \var{str} replaced by two
backslashes and double quotes replaced by backslash-double quote.
backslashes, and double quotes replaced by backslash-double quote.
\end{funcdesc}
\begin{funcdesc}{unquote}{str}
......@@ -21,10 +21,10 @@ Parse address -- which should be the value of some address-containing
field such as \mailheader{To} or \mailheader{Cc} -- into its constituent
\emph{realname} and \emph{email address} parts. Returns a tuple of that
information, unless the parse fails, in which case a 2-tuple of
\code{(None, None)} is returned.
\code{('', '')} is returned.
\end{funcdesc}
\begin{funcdesc}{dump_address_pair}{pair}
\begin{funcdesc}{formataddr}{pair}
The inverse of \method{parseaddr()}, this takes a 2-tuple of the form
\code{(realname, email_address)} and returns the string value suitable
for a \mailheader{To} or \mailheader{Cc} header. If the first element of
......@@ -48,27 +48,6 @@ all_recipients = getaddresses(tos + ccs + resent_tos + resent_ccs)
\end{verbatim}
\end{funcdesc}
\begin{funcdesc}{decode}{s}
This method decodes a string according to the rules in \rfc{2047}. It
returns the decoded string as a Python unicode string.
\end{funcdesc}
\begin{funcdesc}{encode}{s\optional{, charset\optional{, encoding}}}
This method encodes a string according to the rules in \rfc{2047}. It
is not actually the inverse of \function{decode()} since it doesn't
handle multiple character sets or multiple string parts needing
encoding. In fact, the input string \var{s} must already be encoded
in the \var{charset} character set (Python can't reliably guess what
character set a string might be encoded in). The default
\var{charset} is \samp{iso-8859-1}.
\var{encoding} must be either the letter \character{q} for
Quoted-Printable or \character{b} for Base64 encoding. If
neither, a \exception{ValueError} is raised. Both the \var{charset} and
the \var{encoding} strings are case-insensitive, and coerced to lower
case in the returned string.
\end{funcdesc}
\begin{funcdesc}{parsedate}{date}
Attempts to parse a date according to the rules in \rfc{2822}.
however, some mailers don't follow that format as specified, so
......@@ -106,7 +85,7 @@ common use.
\end{funcdesc}
\begin{funcdesc}{formatdate}{\optional{timeval\optional{, localtime}}}
Returns a date string as per Internet standard \rfc{2822}, e.g.:
Returns a date string as per \rfc{2822}, e.g.:
\begin{verbatim}
Fri, 09 Nov 2001 01:08:47 -0000
......@@ -116,7 +95,48 @@ Optional \var{timeval} if given is a floating point time value as
accepted by \function{time.gmtime()} and \function{time.localtime()},
otherwise the current time is used.
Optional \var{localtime} is a flag that when true, interprets
Optional \var{localtime} is a flag that when \code{True}, interprets
\var{timeval}, and returns a date relative to the local timezone
instead of UTC, properly taking daylight savings time into account.
The default is \code{False} meaning UTC is used.
\end{funcdesc}
\begin{funcdesc}{make_msgid}{\optional{idstring}}
Returns a string suitable for an \rfc{2822}-compliant
\mailheader{Message-ID} header. Optional \var{idstring} if given, is
a string used to strengthen the uniqueness of the message id.
\end{funcdesc}
\begin{funcdesc}{decode_rfc2231}{s}
Decode the string \var{s} according to \rfc{2231}.
\end{funcdesc}
\begin{funcdesc}{encode_rfc2231}{s\optional{, charset\optional{, language}}}
Encode the string \var{s} according to \rfc{2231}. Optional
\var{charset} and \var{language}, if given is the character set name
and language name to use. If neither is given, \var{s} is returned
as-is. If \var{charset} is given but \var{language} is not, the
string is encoded using the empty string for \var{language}.
\end{funcdesc}
\begin{funcdesc}{decode_params}{params}
Decode parameters list according to \rfc{2231}. \var{params} is a
sequence of 2-tuples containing elements of the form
\code{(content-type, string-value)}.
\end{funcdesc}
The following functions have been deprecated:
\begin{funcdesc}{dump_address_pair}{pair}
\deprecated{2.2.2}{Use \function{formataddr()} instead.}
\end{funcdesc}
\begin{funcdesc}{decode}{s}
\deprecated{2.2.2}{Use \method{Header.decode_header()} instead.}
\end{funcdesc}
\begin{funcdesc}{encode}{s\optional{, charset\optional{, encoding}}}
\deprecated{2.2.2}{Use \method{Header.encode()} instead.}
\end{funcdesc}
# Copyright (C) 2001 Python Software Foundation
# Copyright (C) 2001,2002 Python Software Foundation
# Author: barry@zope.com (Barry Warsaw)
"""Module containing encoding functions for Image.Image and Text.Text.
"""
import base64
from quopri import encodestring as _encodestring
# Helpers
def _qencode(s):
return _encodestring(s, quotetabs=1)
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):
......@@ -30,7 +51,7 @@ def _bencode(s):
def encode_base64(msg):
"""Encode the message's payload in Base64.
Also, add an appropriate Content-Transfer-Encoding: header.
Also, add an appropriate Content-Transfer-Encoding header.
"""
orig = msg.get_payload()
encdata = _bencode(orig)
......@@ -40,9 +61,9 @@ def encode_base64(msg):
def encode_quopri(msg):
"""Encode the message's payload in Quoted-Printable.
"""Encode the message's payload in quoted-printable.
Also, add an appropriate Content-Transfer-Encoding: header.
Also, add an appropriate Content-Transfer-Encoding header.
"""
orig = msg.get_payload()
encdata = _qencode(orig)
......@@ -52,8 +73,12 @@ def encode_quopri(msg):
def encode_7or8bit(msg):
"""Set the Content-Transfer-Encoding: header to 7bit or 8bit."""
"""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:
......
# Copyright (C) 2001 Python Software Foundation
# Copyright (C) 2001,2002 Python Software Foundation
# Author: barry@zope.com (Barry Warsaw)
"""email package exception classes.
......@@ -7,7 +7,7 @@
class MessageError(Exception):
"""Base class for errors in this module."""
"""Base class for errors in the email package."""
class MessageParseError(MessageError):
......
This diff is collapsed.
# Copyright (C) 2001 Python Software Foundation
# Copyright (C) 2001,2002 Python Software Foundation
# Author: barry@zope.com (Barry Warsaw)
"""Various types of useful iterators and generators.
"""
from __future__ import generators
from cStringIO import StringIO
from types import StringType
import sys
def body_line_iterator(msg):
"""Iterate over the parts, returning string payloads line-by-line."""
for subpart in msg.walk():
payload = subpart.get_payload()
if type(payload) is StringType:
for line in StringIO(payload):
yield line
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 typed_subpart_iterator(msg, maintype='text', subtype=None):
"""Iterate over the subparts with a given MIME type.
Use `maintype' as the main MIME type to match against; this defaults to
"text". Optional `subtype' is the MIME subtype to match against; if
omitted, only the main type is matched.
"""
for subpart in msg.walk():
if subpart.get_main_type('text') == maintype:
if subtype is None or subpart.get_subtype('plain') == subtype:
yield subpart
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)
......@@ -6,9 +6,9 @@
import sndhdr
from cStringIO import StringIO
import MIMEBase
import Errors
import Encoders
from email import Errors
from email import Encoders
from email.MIMENonMultipart import MIMENonMultipart
......@@ -37,7 +37,7 @@ def _whatsnd(data):
class MIMEAudio(MIMEBase.MIMEBase):
class MIMEAudio(MIMENonMultipart):
"""Class for generating audio/* MIME documents."""
def __init__(self, _audiodata, _subtype=None,
......@@ -46,7 +46,7 @@ class MIMEAudio(MIMEBase.MIMEBase):
_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.
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.
......@@ -55,17 +55,17 @@ class MIMEAudio(MIMEBase.MIMEBase):
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
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:
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'
MIMEBase.MIMEBase.__init__(self, 'audio', _subtype, **_params)
MIMENonMultipart.__init__(self, 'audio', _subtype, **_params)
self.set_payload(_audiodata)
_encoder(self)
# Copyright (C) 2001 Python Software Foundation
# Copyright (C) 2001,2002 Python Software Foundation
# Author: barry@zope.com (Barry Warsaw)
"""Base class for MIME specializations.
"""
import Message
from email import Message
......
# Copyright (C) 2001 Python Software Foundation
# Copyright (C) 2001,2002 Python Software Foundation
# Author: barry@zope.com (Barry Warsaw)
"""Class representing image/* type MIME documents.
......@@ -6,14 +6,13 @@
import imghdr
# Intrapackage imports
import MIMEBase
import Errors
import Encoders
from email import Errors
from email import Encoders
from email.MIMENonMultipart import MIMENonMultipart
class MIMEImage(MIMEBase.MIMEBase):
class MIMEImage(MIMENonMultipart):
"""Class for generating image/* type MIME documents."""
def __init__(self, _imagedata, _subtype=None,
......@@ -22,7 +21,7 @@ class MIMEImage(MIMEBase.MIMEBase):
_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.
subtype will be automatically included in the Content-Type header.
Otherwise, you can specify the specific image subtype via the _subtype
parameter.
......@@ -30,17 +29,17 @@ class MIMEImage(MIMEBase.MIMEBase):
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
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:
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'
MIMEBase.MIMEBase.__init__(self, 'image', _subtype, **_params)
MIMENonMultipart.__init__(self, 'image', _subtype, **_params)
self.set_payload(_imagedata)
_encoder(self)
# Copyright (C) 2001 Python Software Foundation
# Copyright (C) 2001,2002 Python Software Foundation
# Author: barry@zope.com (Barry Warsaw)
"""Class representing message/* MIME documents.
"""
import Message
import MIMEBase
from email import Message
from email.MIMENonMultipart import MIMENonMultipart
class MIMEMessage(MIMEBase.MIMEBase):
class MIMEMessage(MIMENonMultipart):
"""Class representing message/* MIME documents."""
def __init__(self, _msg, _subtype='rfc822'):
......@@ -22,7 +22,11 @@ class MIMEMessage(MIMEBase.MIMEBase):
default is "rfc822" (this is defined by the MIME standard, even though
the term "rfc822" is technically outdated by RFC 2822).
"""
MIMEBase.MIMEBase.__init__(self, 'message', _subtype)
MIMENonMultipart.__init__(self, 'message', _subtype)
if not isinstance(_msg, Message.Message):
raise TypeError, 'Argument is not an instance of Message'
self.set_payload(_msg)
# 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')
# Copyright (C) 2001 Python Software Foundation
# Copyright (C) 2001,2002 Python Software Foundation
# Author: barry@zope.com (Barry Warsaw)
"""Class representing text/* type MIME documents.
"""
import MIMEBase
from Encoders import encode_7or8bit
import warnings
from email.MIMENonMultipart import MIMENonMultipart
from email.Encoders import encode_7or8bit
class MIMEText(MIMEBase.MIMEBase):
class MIMEText(MIMENonMultipart):
"""Class for generating text/* type MIME documents."""
def __init__(self, _text, _subtype='plain', _charset='us-ascii',
_encoder=encode_7or8bit):
_encoder=None):
"""Create a text/* type MIME document.
_text is the string for this message object. If the text does not end
......@@ -21,21 +22,27 @@ class MIMEText(MIMEBase.MIMEBase):
_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".
_encoder is a function which will perform the actual encoding for
transport of the text data. It takes one argument, which is this
Text 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 doesn't actually modify the payload,
but it does set Content-Transfer-Encoding: to either `7bit' or `8bit'
as appropriate.
_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.
"""
MIMEBase.MIMEBase.__init__(self, 'text', _subtype,
**{'charset': _charset})
if _text and _text[-1] <> '\n':
MIMENonMultipart.__init__(self, 'text', _subtype,
**{'charset': _charset})
if _text and not _text.endswith('\n'):
_text += '\n'
self.set_payload(_text)
_encoder(self)
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)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
# Copyright (C) 2001 Python Software Foundation
# Copyright (C) 2001,2002 Python Software Foundation
# Author: barry@zope.com (Barry Warsaw)
"""A package for parsing, handling, and generating email messages.
"""
__version__ = '1.0'
__all__ = ['Encoders',
'Errors',
'Generator',
'Iterators',
'MIMEAudio',
'MIMEBase',
'MIMEImage',
'MIMEMessage',
'MIMEText',
'Message',
'Parser',
'Utils',
'message_from_string',
'message_from_file',
]
__version__ = '2.4'
__all__ = [
'base64MIME',
'Charset',
'Encoders',
'Errors',
'Generator',
'Header',
'Iterators',
'Message',
'MIMEAudio',
'MIMEBase',
'MIMEImage',
'MIMEMessage',
'MIMEMultipart',
'MIMENonMultipart',
'MIMEText',
'Parser',
'quopriMIME',
'Utils',
'message_from_string',
'message_from_file',
]
try:
True, False
except NameError:
True = 1
False = 0
# Some convenience routines
from Parser import Parser as _Parser
from Message import Message as _Message
# Some convenience routines. Don't import Parser and Message as side-effects
# of importing email since those cascadingly import most of the rest of the
# email package.
def message_from_string(s, _class=None, strict=False):
"""Parse a string into a Message object model.
Optional _class and strict are passed to the Parser constructor.
"""
from email.Parser import Parser
if _class is None:
from email.Message import Message
_class = Message
return Parser(_class, strict=strict).parsestr(s)
def message_from_string(s, _class=_Message):
return _Parser(_class).parsestr(s)
def message_from_file(fp, _class=None, strict=False):
"""Read a file and parse its contents into a Message object model.
def message_from_file(fp, _class=_Message):
return _Parser(_class).parse(fp)
Optional _class and strict are passed to the Parser constructor.
"""
from email.Parser import Parser
if _class is None:
from email.Message import Message
_class = Message
return Parser(_class, strict=strict).parse(fp)
# Patch encodings.aliases to recognize 'ansi_x3.4_1968' which isn't a standard
# alias in Python 2.1.3, but is used by the email package test suite.
from encodings.aliases import aliases # The aliases dictionary
if not aliases.has_key('ansi_x3.4_1968'):
aliases['ansi_x3.4_1968'] = 'ascii'
del aliases # Not needed any more
......@@ -484,6 +484,7 @@ _expectations = {
test_curses
test_dbm
test_dl
test_email_codecs
test_fcntl
test_fork1
test_gdbm
......@@ -511,6 +512,7 @@ _expectations = {
test_cl
test_curses
test_dl
test_email_codecs
test_gl
test_imgfile
test_largefile
......@@ -534,6 +536,7 @@ _expectations = {
test_curses
test_dbm
test_dl
test_email_codecs
test_fcntl
test_fork1
test_gl
......@@ -567,6 +570,7 @@ _expectations = {
test_cd
test_cl
test_dl
test_email_codecs
test_gl
test_imgfile
test_largefile
......@@ -591,6 +595,7 @@ _expectations = {
test_cd
test_cl
test_dl
test_email_codecs
test_gl
test_imgfile
test_largefile
......@@ -616,6 +621,7 @@ _expectations = {
test_cd
test_cl
test_dl
test_email_codecs
test_fork1
test_gettext
test_gl
......@@ -652,6 +658,7 @@ _expectations = {
test_crypt
test_dbm
test_dl
test_email_codecs
test_fcntl
test_fork1
test_gdbm
......@@ -690,6 +697,7 @@ _expectations = {
test_cl
test_curses
test_dl
test_email_codecs
test_gdbm
test_gl
test_imgfile
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment