mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Merge email package 4.0 from the sandbox, including documentation, test cases,
and NEWS updates.
This commit is contained in:
		
							parent
							
								
									9ae019bf5b
								
							
						
					
					
						commit
						40ef0067ad
					
				
					 44 changed files with 3821 additions and 468 deletions
				
			
		|  | @ -1,83 +1,69 @@ | |||
| #!/usr/bin/env python | ||||
| 
 | ||||
| """Send the contents of a directory as a MIME message. | ||||
| """Send the contents of a directory as a MIME message.""" | ||||
| 
 | ||||
| Usage: dirmail [options] from to [to ...]* | ||||
| 
 | ||||
| Options: | ||||
|     -h / --help | ||||
|         Print this message and exit. | ||||
| 
 | ||||
|     -d directory | ||||
|     --directory=directory | ||||
|         Mail the contents of the specified directory, otherwise use the | ||||
|         current directory.  Only the regular files in the directory are sent, | ||||
|         and we don't recurse to subdirectories. | ||||
| 
 | ||||
| `from' is the email address of the sender of the message. | ||||
| 
 | ||||
| `to' is the email address of the recipient of the message, and multiple | ||||
| recipients may be given. | ||||
| 
 | ||||
| The email is sent by forwarding to your local SMTP server, which then does the | ||||
| normal delivery process.  Your local machine must be running an SMTP server. | ||||
| """ | ||||
| 
 | ||||
| import sys | ||||
| import os | ||||
| import getopt | ||||
| import sys | ||||
| import smtplib | ||||
| # For guessing MIME type based on file name extension | ||||
| import mimetypes | ||||
| 
 | ||||
| from email import Encoders | ||||
| from email.Message import Message | ||||
| from email.MIMEAudio import MIMEAudio | ||||
| from email.MIMEBase import MIMEBase | ||||
| from email.MIMEMultipart import MIMEMultipart | ||||
| from email.MIMEImage import MIMEImage | ||||
| from email.MIMEText import MIMEText | ||||
| from optparse import OptionParser | ||||
| 
 | ||||
| from email import encoders | ||||
| from email.message import Message | ||||
| from email.mime.audio import MIMEAudio | ||||
| from email.mime.base import MIMEBase | ||||
| from email.mime.image import MIMEImage | ||||
| from email.mime.multipart import MIMEMultipart | ||||
| from email.mime.text import MIMEText | ||||
| 
 | ||||
| COMMASPACE = ', ' | ||||
| 
 | ||||
| 
 | ||||
| def usage(code, msg=''): | ||||
|     print >> sys.stderr, __doc__ | ||||
|     if msg: | ||||
|         print >> sys.stderr, msg | ||||
|     sys.exit(code) | ||||
| 
 | ||||
| 
 | ||||
| def main(): | ||||
|     try: | ||||
|         opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) | ||||
|     except getopt.error, msg: | ||||
|         usage(1, msg) | ||||
|     parser = OptionParser(usage="""\ | ||||
| Send the contents of a directory as a MIME message. | ||||
| 
 | ||||
|     dir = os.curdir | ||||
|     for opt, arg in opts: | ||||
|         if opt in ('-h', '--help'): | ||||
|             usage(0) | ||||
|         elif opt in ('-d', '--directory'): | ||||
|             dir = arg | ||||
| 
 | ||||
|     if len(args) < 2: | ||||
|         usage(1) | ||||
| 
 | ||||
|     sender = args[0] | ||||
|     recips = args[1:] | ||||
| Usage: %prog [options] | ||||
| 
 | ||||
| Unless the -o option is given, the email is sent by forwarding to your local | ||||
| SMTP server, which then does the normal delivery process.  Your local machine | ||||
| must be running an SMTP server. | ||||
| """) | ||||
|     parser.add_option('-d', '--directory', | ||||
|                       type='string', action='store', | ||||
|                       help="""Mail the contents of the specified directory, | ||||
|                       otherwise use the current directory.  Only the regular | ||||
|                       files in the directory are sent, and we don't recurse to | ||||
|                       subdirectories.""") | ||||
|     parser.add_option('-o', '--output', | ||||
|                       type='string', action='store', metavar='FILE', | ||||
|                       help="""Print the composed message to FILE instead of | ||||
|                       sending the message to the SMTP server.""") | ||||
|     parser.add_option('-s', '--sender', | ||||
|                       type='string', action='store', metavar='SENDER', | ||||
|                       help='The value of the From: header (required)') | ||||
|     parser.add_option('-r', '--recipient', | ||||
|                       type='string', action='append', metavar='RECIPIENT', | ||||
|                       default=[], dest='recipients', | ||||
|                       help='A To: header value (at least one required)') | ||||
|     opts, args = parser.parse_args() | ||||
|     if not opts.sender or not opts.recipients: | ||||
|         parser.print_help() | ||||
|         sys.exit(1) | ||||
|     directory = opts.directory | ||||
|     if not directory: | ||||
|         directory = '.' | ||||
|     # Create the enclosing (outer) message | ||||
|     outer = MIMEMultipart() | ||||
|     outer['Subject'] = 'Contents of directory %s' % os.path.abspath(dir) | ||||
|     outer['To'] = COMMASPACE.join(recips) | ||||
|     outer['From'] = sender | ||||
|     outer['Subject'] = 'Contents of directory %s' % os.path.abspath(directory) | ||||
|     outer['To'] = COMMASPACE.join(opts.recipients) | ||||
|     outer['From'] = opts.sender | ||||
|     outer.preamble = 'You will not see this in a MIME-aware mail reader.\n' | ||||
|     # To guarantee the message ends with a newline | ||||
|     outer.epilogue = '' | ||||
| 
 | ||||
|     for filename in os.listdir(dir): | ||||
|         path = os.path.join(dir, filename) | ||||
|     for filename in os.listdir(directory): | ||||
|         path = os.path.join(directory, filename) | ||||
|         if not os.path.isfile(path): | ||||
|             continue | ||||
|         # Guess the content type based on the file's extension.  Encoding | ||||
|  | @ -108,15 +94,20 @@ def main(): | |||
|             msg.set_payload(fp.read()) | ||||
|             fp.close() | ||||
|             # Encode the payload using Base64 | ||||
|             Encoders.encode_base64(msg) | ||||
|             encoders.encode_base64(msg) | ||||
|         # Set the filename parameter | ||||
|         msg.add_header('Content-Disposition', 'attachment', filename=filename) | ||||
|         outer.attach(msg) | ||||
| 
 | ||||
|     # Now send the message | ||||
|     # Now send or store the message | ||||
|     composed = outer.as_string() | ||||
|     if opts.output: | ||||
|         fp = open(opts.output, 'w') | ||||
|         fp.write(composed) | ||||
|         fp.close() | ||||
|     else: | ||||
|         s = smtplib.SMTP() | ||||
|         s.connect() | ||||
|     s.sendmail(sender, recips, outer.as_string()) | ||||
|         s.sendmail(opts.sender, opts.recipients, composed) | ||||
|         s.close() | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,8 +2,8 @@ | |||
| import smtplib | ||||
| 
 | ||||
| # Here are the email package modules we'll need | ||||
| from email.MIMEImage import MIMEImage | ||||
| from email.MIMEMultipart import MIMEMultipart | ||||
| from email.mime.image import MIMEImage | ||||
| from email.mime.multipart import MIMEMultipart | ||||
| 
 | ||||
| COMMASPACE = ', ' | ||||
| 
 | ||||
|  | @ -15,8 +15,6 @@ | |||
| msg['From'] = me | ||||
| msg['To'] = COMMASPACE.join(family) | ||||
| msg.preamble = 'Our family reunion' | ||||
| # Guarantees the message ends in a newline | ||||
| msg.epilogue = '' | ||||
| 
 | ||||
| # Assume we know that the image files are all in PNG format | ||||
| for file in pngfiles: | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| import smtplib | ||||
| 
 | ||||
| # Import the email modules we'll need | ||||
| from email.MIMEText import MIMEText | ||||
| from email.mime.text import MIMEText | ||||
| 
 | ||||
| # Open a plain text file for reading.  For this example, assume that | ||||
| # the text file contains only ASCII characters. | ||||
|  |  | |||
|  | @ -1,59 +1,44 @@ | |||
| #!/usr/bin/env python | ||||
| 
 | ||||
| """Unpack a MIME message into a directory of files. | ||||
| """Unpack a MIME message into a directory of files.""" | ||||
| 
 | ||||
| Usage: unpackmail [options] msgfile | ||||
| 
 | ||||
| Options: | ||||
|     -h / --help | ||||
|         Print this message and exit. | ||||
| 
 | ||||
|     -d directory | ||||
|     --directory=directory | ||||
|         Unpack the MIME message into the named directory, which will be | ||||
|         created if it doesn't already exist. | ||||
| 
 | ||||
| msgfile is the path to the file containing the MIME message. | ||||
| """ | ||||
| 
 | ||||
| import sys | ||||
| import os | ||||
| import getopt | ||||
| import sys | ||||
| import email | ||||
| import errno | ||||
| import mimetypes | ||||
| import email | ||||
| 
 | ||||
| 
 | ||||
| def usage(code, msg=''): | ||||
|     print >> sys.stderr, __doc__ | ||||
|     if msg: | ||||
|         print >> sys.stderr, msg | ||||
|     sys.exit(code) | ||||
| from optparse import OptionParser | ||||
| 
 | ||||
| 
 | ||||
| def main(): | ||||
|     try: | ||||
|         opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) | ||||
|     except getopt.error, msg: | ||||
|         usage(1, msg) | ||||
|     parser = OptionParser(usage="""\ | ||||
| Unpack a MIME message into a directory of files. | ||||
| 
 | ||||
|     dir = os.curdir | ||||
|     for opt, arg in opts: | ||||
|         if opt in ('-h', '--help'): | ||||
|             usage(0) | ||||
|         elif opt in ('-d', '--directory'): | ||||
|             dir = arg | ||||
| Usage: %prog [options] msgfile | ||||
| """) | ||||
|     parser.add_option('-d', '--directory', | ||||
|                       type='string', action='store', | ||||
|                       help="""Unpack the MIME message into the named | ||||
|                       directory, which will be created if it doesn't already | ||||
|                       exist.""") | ||||
|     opts, args = parser.parse_args() | ||||
|     if not opts.directory: | ||||
|         parser.print_help() | ||||
|         sys.exit(1) | ||||
| 
 | ||||
|     try: | ||||
|         msgfile = args[0] | ||||
|     except IndexError: | ||||
|         usage(1) | ||||
|         parser.print_help() | ||||
|         sys.exit(1) | ||||
| 
 | ||||
|     try: | ||||
|         os.mkdir(dir) | ||||
|         os.mkdir(opts.directory) | ||||
|     except OSError, e: | ||||
|         # Ignore directory exists error | ||||
|         if e.errno <> errno.EEXIST: raise | ||||
|         if e.errno <> errno.EEXIST: | ||||
|             raise | ||||
| 
 | ||||
|     fp = open(msgfile) | ||||
|     msg = email.message_from_file(fp) | ||||
|  | @ -74,8 +59,8 @@ def main(): | |||
|                 ext = '.bin' | ||||
|             filename = 'part-%03d%s' % (counter, ext) | ||||
|         counter += 1 | ||||
|         fp = open(os.path.join(dir, filename), 'wb') | ||||
|         fp.write(part.get_payload(decode=1)) | ||||
|         fp = open(os.path.join(opts.directory, filename), 'wb') | ||||
|         fp.write(part.get_payload(decode=True)) | ||||
|         fp.close() | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| % Copyright (C) 2001-2004 Python Software Foundation | ||||
| % Copyright (C) 2001-2006 Python Software Foundation | ||||
| % Author: barry@python.org (Barry Warsaw) | ||||
| 
 | ||||
| \section{\module{email} --- | ||||
|  | @ -18,10 +18,10 @@ subsumes most of the functionality in several older standard modules | |||
| such as \refmodule{rfc822}, \refmodule{mimetools}, | ||||
| \refmodule{multifile}, and other non-standard packages such as | ||||
| \module{mimecntl}.  It is specifically \emph{not} designed to do any | ||||
| sending of email messages to SMTP (\rfc{2821}) servers; that is the | ||||
| function of the \refmodule{smtplib} module.  The \module{email} | ||||
| package attempts to be as RFC-compliant as possible, supporting in | ||||
| addition to \rfc{2822}, such MIME-related RFCs as | ||||
| sending of email messages to SMTP (\rfc{2821}), NNTP, or other servers; those | ||||
| are functions of modules such as \refmodule{smtplib} and \refmodule{nntplib}. | ||||
| The \module{email} package attempts to be as RFC-compliant as possible, | ||||
| supporting in addition to \rfc{2822}, such MIME-related RFCs as | ||||
| \rfc{2045}, \rfc{2046}, \rfc{2047}, and \rfc{2231}. | ||||
| 
 | ||||
| The primary distinguishing feature of the \module{email} package is | ||||
|  | @ -41,7 +41,7 @@ The following sections describe the functionality of the | |||
| should be common in applications: an email message is read as flat | ||||
| text from a file or other source, the text is parsed to produce the | ||||
| object structure of the email message, this structure is manipulated, | ||||
| and finally rendered back into flat text. | ||||
| and finally, the object tree is rendered back into flat text. | ||||
| 
 | ||||
| It is perfectly feasible to create the object structure out of whole | ||||
| cloth --- i.e. completely from scratch.  From there, a similar | ||||
|  | @ -56,6 +56,7 @@ package, a section on differences and porting is provided. | |||
| 
 | ||||
| \begin{seealso} | ||||
|     \seemodule{smtplib}{SMTP protocol client} | ||||
|     \seemodule{nntplib}{NNTP protocol client} | ||||
| \end{seealso} | ||||
| 
 | ||||
| \subsection{Representing an email message} | ||||
|  | @ -88,22 +89,51 @@ package, a section on differences and porting is provided. | |||
| \subsection{Iterators} | ||||
| \input{emailiter} | ||||
| 
 | ||||
| \subsection{Package History} | ||||
| \subsection{Package History\label{email-pkg-history}} | ||||
| 
 | ||||
| Version 1 of the \module{email} package was bundled with Python | ||||
| releases up to Python 2.2.1.  Version 2 was developed for the Python | ||||
| 2.3 release, and backported to Python 2.2.2.  It was also available as | ||||
| a separate distutils-based package, and is compatible back to Python 2.1. | ||||
| This table describes the release history of the email package, corresponding | ||||
| to the version of Python that the package was released with.  For purposes of | ||||
| this document, when you see a note about change or added versions, these refer | ||||
| to the Python version the change was made it, \emph{not} the email package | ||||
| version.  This table also describes the Python compatibility of each version | ||||
| of the package. | ||||
| 
 | ||||
| \module{email} version 3.0 was released with Python 2.4 and as a separate | ||||
| distutils-based package.  It is compatible back to Python 2.3. | ||||
| \begin{tableiii}{l|l|l}{constant}{email version}{distributed with}{compatible with} | ||||
| \lineiii{1.x}{Python 2.2.0 to Python 2.2.1}{\emph{no longer supported}} | ||||
| \lineiii{2.5}{Python 2.2.2+ and Python 2.3}{Python 2.1 to 2.5} | ||||
| \lineiii{3.0}{Python 2.4}{Python 2.3 to 2.5} | ||||
| \lineiii{4.0}{Python 2.5}{Python 2.3 to 2.5} | ||||
| \end{tableiii} | ||||
| 
 | ||||
| Here are the differences between \module{email} version 3 and version 2: | ||||
| Here are the major differences between \module{email} verson 4 and version 3: | ||||
| 
 | ||||
| \begin{itemize} | ||||
| \item All modules have been renamed according to \pep{8} standards.  For | ||||
|       example, the version 3 module \module{email.Message} was renamed to | ||||
|       \module{email.message} in version 4. | ||||
| 
 | ||||
| \item A new subpackage \module{email.mime} was added and all the version 3 | ||||
|       \module{email.MIME*} modules were renamed and situated into the | ||||
|       \module{email.mime} subpackage.  For example, the version 3 module | ||||
|       \module{email.MIMEText} was renamed to \module{email.mime.text}. | ||||
| 
 | ||||
|       \emph{Note that the version 3 names will continue to work until Python | ||||
|       2.6}. | ||||
| 
 | ||||
| \item The \module{email.mime.application} module was added, which contains the | ||||
|       \class{MIMEApplication} class. | ||||
| 
 | ||||
| \item Methods that were deprecated in version 3 have been removed.  These | ||||
|       include \method{Generator.__call__()}, \method{Message.get_type()}, | ||||
|       \method{Message.get_main_type()}, \method{Message.get_subtype()}. | ||||
| \end{itemize} | ||||
| 
 | ||||
| Here are the major differences between \module{email} version 3 and version 2: | ||||
| 
 | ||||
| \begin{itemize} | ||||
| \item The \class{FeedParser} class was introduced, and the \class{Parser} | ||||
|       class was implemented in terms of the \class{FeedParser}.  All parsing | ||||
|       there for is non-strict, and parsing will make a best effort never to | ||||
|       therefore is non-strict, and parsing will make a best effort never to | ||||
|       raise an exception.  Problems found while parsing messages are stored in | ||||
|       the message's \var{defect} attribute. | ||||
| 
 | ||||
|  | @ -117,7 +147,7 @@ Here are the differences between \module{email} version 3 and version 2: | |||
|       \method{Generator.__call__()}, \method{Message.get_type()}, | ||||
|       \method{Message.get_main_type()}, \method{Message.get_subtype()}, and | ||||
|       the \var{strict} argument to the \class{Parser} class.  These are | ||||
|       expected to be removed in email 3.1. | ||||
|       expected to be removed in future versions. | ||||
| 
 | ||||
| \item Support for Pythons earlier than 2.3 has been removed. | ||||
| \end{itemize} | ||||
|  | @ -278,12 +308,12 @@ The \class{Message} class has the following differences: | |||
| \item The method \method{getpayloadastext()} was removed.  Similar | ||||
|       functionality | ||||
|       is supported by the \class{DecodedGenerator} class in the | ||||
|       \refmodule{email.Generator} module. | ||||
|       \refmodule{email.generator} module. | ||||
| 
 | ||||
| \item The method \method{getbodyastext()} was removed.  You can get | ||||
|       similar functionality by creating an iterator with | ||||
|       \function{typed_subpart_iterator()} in the | ||||
|       \refmodule{email.Iterators} module. | ||||
|       \refmodule{email.iterators} module. | ||||
| \end{itemize} | ||||
| 
 | ||||
| The \class{Parser} class has no differences in its public interface. | ||||
|  | @ -295,7 +325,7 @@ notification\footnote{Delivery Status Notifications (DSN) are defined | |||
| in \rfc{1894}.}. | ||||
| 
 | ||||
| The \class{Generator} class has no differences in its public | ||||
| interface.  There is a new class in the \refmodule{email.Generator} | ||||
| interface.  There is a new class in the \refmodule{email.generator} | ||||
| module though, called \class{DecodedGenerator} which provides most of | ||||
| the functionality previously available in the | ||||
| \method{Message.getpayloadastext()} method. | ||||
|  | @ -329,11 +359,11 @@ The following modules and classes have been changed: | |||
| 
 | ||||
| \module{mimelib} provided some utility functions in its | ||||
| \module{address} and \module{date} modules.  All of these functions | ||||
| have been moved to the \refmodule{email.Utils} module. | ||||
| have been moved to the \refmodule{email.utils} module. | ||||
| 
 | ||||
| The \code{MsgReader} class/module has been removed.  Its functionality | ||||
| is most closely supported in the \function{body_line_iterator()} | ||||
| function in the \refmodule{email.Iterators} module. | ||||
| function in the \refmodule{email.iterators} module. | ||||
| 
 | ||||
| \subsection{Examples} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| \declaremodule{standard}{email.Charset} | ||||
| \declaremodule{standard}{email.charset} | ||||
| \modulesynopsis{Character Sets} | ||||
| 
 | ||||
| This module provides a class \class{Charset} for representing | ||||
|  | @ -7,6 +7,8 @@ well as a character set registry and several convenience methods for | |||
| manipulating this registry.  Instances of \class{Charset} are used in | ||||
| several other modules within the \module{email} package. | ||||
| 
 | ||||
| Import this class from the \module{email.charset} module. | ||||
| 
 | ||||
| \versionadded{2.2.2} | ||||
| 
 | ||||
| \begin{classdesc}{Charset}{\optional{input_charset}} | ||||
|  | @ -153,7 +155,7 @@ 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 | ||||
| higher-level \class{Header} class to deal with these issues (see | ||||
| \refmodule{email.Header}).  \var{convert} defaults to \code{False}. | ||||
| \refmodule{email.header}).  \var{convert} defaults to \code{False}. | ||||
| 
 | ||||
| The type of encoding (base64 or quoted-printable) will be based on | ||||
| the \var{header_encoding} attribute. | ||||
|  | @ -188,7 +190,7 @@ This method allows you to compare two \class{Charset} instances for equality. | |||
| This method allows you to compare two \class{Charset} instances for inequality. | ||||
| \end{methoddesc} | ||||
| 
 | ||||
| The \module{email.Charset} module also provides the following | ||||
| The \module{email.charset} module also provides the following | ||||
| functions for adding new entries to the global character set, alias, | ||||
| and codec registries: | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| \declaremodule{standard}{email.Encoders} | ||||
| \declaremodule{standard}{email.encoders} | ||||
| \modulesynopsis{Encoders for email message payloads.} | ||||
| 
 | ||||
| When creating \class{Message} objects from scratch, you often need to | ||||
|  | @ -7,7 +7,7 @@ This is especially true for \mimetype{image/*} and \mimetype{text/*} | |||
| type messages containing binary data. | ||||
| 
 | ||||
| The \module{email} package provides some convenient encodings in its | ||||
| \module{Encoders} module.  These encoders are actually used by the | ||||
| \module{encoders} module.  These encoders are actually used by the | ||||
| \class{MIMEAudio} and \class{MIMEImage} class constructors to provide default | ||||
| encodings.  All encoder functions take exactly one argument, the message | ||||
| object to encode.  They usually extract the payload, encode it, and reset the | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| \declaremodule{standard}{email.Errors} | ||||
| \declaremodule{standard}{email.errors} | ||||
| \modulesynopsis{The exception classes used by the email package.} | ||||
| 
 | ||||
| The following exception classes are defined in the | ||||
| \module{email.Errors} module: | ||||
| \module{email.errors} module: | ||||
| 
 | ||||
| \begin{excclassdesc}{MessageError}{} | ||||
| This is the base class for all exceptions that the \module{email} | ||||
|  | @ -59,7 +59,7 @@ problem was found, so for example, if a message nested inside a | |||
| \mimetype{multipart/alternative} had a malformed header, that nested message | ||||
| object would have a defect, but the containing messages would not. | ||||
| 
 | ||||
| All defect classes are subclassed from \class{email.Errors.MessageDefect}, but | ||||
| All defect classes are subclassed from \class{email.errors.MessageDefect}, but | ||||
| this class is \emph{not} an exception! | ||||
| 
 | ||||
| \versionadded[All the defect classes were added]{2.4} | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| \declaremodule{standard}{email.Generator} | ||||
| \declaremodule{standard}{email.generator} | ||||
| \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 | ||||
|  | @ -8,7 +8,7 @@ module or the \refmodule{nntplib} module, or print the message on the | |||
| 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 | ||||
| Again, as with the \refmodule{email.parser} module, you aren't limited | ||||
| 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 | ||||
|  | @ -17,7 +17,8 @@ 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: | ||||
| Here are the public methods of the \class{Generator} class, imported from the | ||||
| \module{email.generator} module: | ||||
| 
 | ||||
| \begin{classdesc}{Generator}{outfp\optional{, mangle_from_\optional{, | ||||
|     maxheaderlen}}} | ||||
|  | @ -40,7 +41,7 @@ mailbox format files. | |||
| Optional \var{maxheaderlen} specifies the longest length for a | ||||
| non-continued header.  When a header line is longer than | ||||
| \var{maxheaderlen} (in characters, with tabs expanded to 8 spaces), | ||||
| the header will be split as defined in the \module{email.Header} | ||||
| the header will be split as defined in the \module{email.header.Header} | ||||
| class.  Set to zero to disable header wrapping.  The default is 78, as | ||||
| recommended (but not required) by \rfc{2822}. | ||||
| \end{classdesc} | ||||
|  | @ -81,9 +82,9 @@ be used in extended print statements. | |||
| 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}. | ||||
| message object.  For more detail, see \refmodule{email.message}. | ||||
| 
 | ||||
| The \module{email.Generator} module also provides a derived class, | ||||
| 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. | ||||
|  | @ -128,13 +129,5 @@ The default value for \var{fmt} is \code{None}, meaning | |||
| \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} | ||||
| \versionchanged[The previously deprecated method \method{__call__()} was | ||||
| removed]{2.5} | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| \declaremodule{standard}{email.Header} | ||||
| \declaremodule{standard}{email.header} | ||||
| \modulesynopsis{Representing non-ASCII headers} | ||||
| 
 | ||||
| \rfc{2822} is the base standard that describes the format of email | ||||
|  | @ -15,17 +15,18 @@ slew of RFCs have been written describing how to encode email | |||
| containing non-\ASCII{} characters into \rfc{2822}-compliant format. | ||||
| These RFCs include \rfc{2045}, \rfc{2046}, \rfc{2047}, and \rfc{2231}. | ||||
| The \module{email} package supports these standards in its | ||||
| \module{email.Header} and \module{email.Charset} modules. | ||||
| \module{email.header} and \module{email.charset} modules. | ||||
| 
 | ||||
| If you want to include non-\ASCII{} characters in your email headers, | ||||
| say in the \mailheader{Subject} or \mailheader{To} fields, you should | ||||
| use the \class{Header} class and assign the field in the | ||||
| \class{Message} object to an instance of \class{Header} instead of | ||||
| using a string for the header value.  For example: | ||||
| using a string for the header value.  Import the \class{Header} class from the | ||||
| \module{email.header} module.  For example: | ||||
| 
 | ||||
| \begin{verbatim} | ||||
| >>> from email.Message import Message | ||||
| >>> from email.Header import Header | ||||
| >>> from email.message import Message | ||||
| >>> from email.header import Header | ||||
| >>> msg = Message() | ||||
| >>> h = Header('p\xf6stal', 'iso-8859-1') | ||||
| >>> msg['Subject'] = h | ||||
|  | @ -87,7 +88,7 @@ Optional \var{errors} is passed straight through to the | |||
| Append the string \var{s} to the MIME header. | ||||
| 
 | ||||
| Optional \var{charset}, if given, should be a \class{Charset} instance | ||||
| (see \refmodule{email.Charset}) or the name of a character set, which | ||||
| (see \refmodule{email.charset}) or the name of a character set, which | ||||
| will be converted to a \class{Charset} instance.  A value of | ||||
| \code{None} (the default) means that the \var{charset} given in the | ||||
| constructor is used. | ||||
|  | @ -139,7 +140,7 @@ This method allows you to compare two \class{Header} instances for equality. | |||
| This method allows you to compare two \class{Header} instances for inequality. | ||||
| \end{methoddesc} | ||||
| 
 | ||||
| The \module{email.Header} module also provides the following | ||||
| The \module{email.header} module also provides the following | ||||
| convenient functions. | ||||
| 
 | ||||
| \begin{funcdesc}{decode_header}{header} | ||||
|  | @ -155,7 +156,7 @@ encoded string. | |||
| Here's an example: | ||||
| 
 | ||||
| \begin{verbatim} | ||||
| >>> from email.Header import decode_header | ||||
| >>> from email.header import decode_header | ||||
| >>> decode_header('=?iso-8859-1?q?p=F6stal?=') | ||||
| [('p\xf6stal', 'iso-8859-1')] | ||||
| \end{verbatim} | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| \declaremodule{standard}{email.Iterators} | ||||
| \declaremodule{standard}{email.iterators} | ||||
| \modulesynopsis{Iterate over a  message object tree.} | ||||
| 
 | ||||
| Iterating over a message object tree is fairly easy with the | ||||
| \method{Message.walk()} method.  The \module{email.Iterators} module | ||||
| \method{Message.walk()} method.  The \module{email.iterators} module | ||||
| provides some useful higher level iterations over message object | ||||
| trees. | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,10 +1,11 @@ | |||
| \declaremodule{standard}{email.Message} | ||||
| \declaremodule{standard}{email.message} | ||||
| \modulesynopsis{The base class representing email messages.} | ||||
| 
 | ||||
| The central class in the \module{email} package is the | ||||
| \class{Message} class; it is the base class for the \module{email} | ||||
| object model.  \class{Message} provides the core functionality for | ||||
| setting and querying header fields, and for accessing message bodies. | ||||
| \class{Message} class, imported from the \module{email.message} module.  It is | ||||
| the base class for the \module{email} object model.  \class{Message} provides | ||||
| the core functionality for setting and querying header fields, and for | ||||
| accessing message bodies. | ||||
| 
 | ||||
| Conceptually, a \class{Message} object consists of \emph{headers} and | ||||
| \emph{payloads}.  Headers are \rfc{2822} style field names and | ||||
|  | @ -45,7 +46,7 @@ begin with \code{From }.  For more flexibility, instantiate a | |||
| 
 | ||||
| \begin{verbatim} | ||||
| from cStringIO import StringIO | ||||
| from email.Generator import Generator | ||||
| from email.generator import Generator | ||||
| fp = StringIO() | ||||
| g = Generator(fp, mangle_from_=False, maxheaderlen=60) | ||||
| g.flatten(msg) | ||||
|  | @ -119,7 +120,7 @@ client's responsibility to ensure the payload invariants.  Optional | |||
| 
 | ||||
| \begin{methoddesc}[Message]{set_charset}{charset} | ||||
| Set the character set of the payload to \var{charset}, which can | ||||
| either be a \class{Charset} instance (see \refmodule{email.Charset}), a | ||||
| either be a \class{Charset} instance (see \refmodule{email.charset}), a | ||||
| string naming a character set, | ||||
| or \code{None}.  If it is a string, it will be converted to a | ||||
| \class{Charset} instance.  If \var{charset} is \code{None}, the | ||||
|  | @ -128,8 +129,8 @@ or \code{None}.  If it is a string, it will be converted to a | |||
| \exception{TypeError}. | ||||
| 
 | ||||
| The message will be assumed to be of type \mimetype{text/*} encoded with | ||||
| \code{charset.input_charset}.  It will be converted to | ||||
| \code{charset.output_charset} | ||||
| \var{charset.input_charset}.  It will be converted to | ||||
| \var{charset.output_charset} | ||||
| and encoded properly, if needed, when generating the plain text | ||||
| representation of the message.  MIME headers | ||||
| (\mailheader{MIME-Version}, \mailheader{Content-Type}, | ||||
|  | @ -513,6 +514,9 @@ message/rfc822 | |||
| \end{verbatim} | ||||
| \end{methoddesc} | ||||
| 
 | ||||
| \versionchanged[The previously deprecated methods \method{get_type()}, | ||||
| \method{get_main_type()}, and \method{get_subtype()} were removed]{2.5} | ||||
| 
 | ||||
| \class{Message} objects can also optionally contain two instance | ||||
| attributes, which can be used when generating the plain text of a MIME | ||||
| message. | ||||
|  | @ -532,7 +536,7 @@ to the message's \var{preamble} attribute.  When the \class{Generator} | |||
| is writing out the plain text representation of a MIME message, and it | ||||
| finds the message has a \var{preamble} attribute, it will write this | ||||
| text in the area between the headers and the first boundary.  See | ||||
| \refmodule{email.Parser} and \refmodule{email.Generator} for details. | ||||
| \refmodule{email.parser} and \refmodule{email.generator} for details. | ||||
| 
 | ||||
| Note that if the message object has no preamble, the | ||||
| \var{preamble} attribute will be \code{None}. | ||||
|  | @ -543,58 +547,15 @@ The \var{epilogue} attribute acts the same way as the \var{preamble} | |||
| attribute, except that it contains text that appears between the last | ||||
| boundary and the end of the message. | ||||
| 
 | ||||
| One note: when generating the flat text for a \mimetype{multipart} | ||||
| message that has no \var{epilogue} (using the standard | ||||
| \class{Generator} class), no newline is added after the closing | ||||
| boundary line.  If the message object has an \var{epilogue} and its | ||||
| value does not start with a newline, a newline is printed after the | ||||
| closing boundary.  This seems a little clumsy, but it makes the most | ||||
| practical sense.  The upshot is that if you want to ensure that a | ||||
| newline get printed after your closing \mimetype{multipart} boundary, | ||||
| set the \var{epilogue} to the empty string. | ||||
| \versionchanged[You do not need to set the epilogue to the empty string in | ||||
| order for the \class{Generator} to print a newline at the end of the | ||||
| file]{2.5} | ||||
| \end{datadesc} | ||||
| 
 | ||||
| \begin{datadesc}{defects} | ||||
| The \var{defects} attribute contains a list of all the problems found when | ||||
| parsing this message.  See \refmodule{email.Errors} for a detailed description | ||||
| parsing this message.  See \refmodule{email.errors} for a detailed description | ||||
| of the possible parsing defects. | ||||
| 
 | ||||
| \versionadded{2.4} | ||||
| \end{datadesc} | ||||
| 
 | ||||
| \subsubsection{Deprecated methods} | ||||
| 
 | ||||
| \versionchanged[The \method{add_payload()} method was removed; use the | ||||
| \method{attach()} method instead]{2.4} | ||||
| 
 | ||||
| The following methods are deprecated.  They are documented here for | ||||
| completeness. | ||||
| 
 | ||||
| \begin{methoddesc}[Message]{get_type}{\optional{failobj}} | ||||
| Return the message's content type, as a string of the form | ||||
| \mimetype{maintype/subtype} as taken from the | ||||
| \mailheader{Content-Type} header. | ||||
| The returned string is coerced to lowercase. | ||||
| 
 | ||||
| If there is no \mailheader{Content-Type} header in the message, | ||||
| \var{failobj} is returned (defaults to \code{None}). | ||||
| 
 | ||||
| \deprecated{2.2.2}{Use the \method{get_content_type()} method instead.} | ||||
| \end{methoddesc} | ||||
| 
 | ||||
| \begin{methoddesc}[Message]{get_main_type}{\optional{failobj}} | ||||
| Return the message's \emph{main} content type.  This essentially returns the | ||||
| \var{maintype} part of the string returned by \method{get_type()}, with the | ||||
| same semantics for \var{failobj}. | ||||
| 
 | ||||
| \deprecated{2.2.2}{Use the \method{get_content_maintype()} method instead.} | ||||
| \end{methoddesc} | ||||
| 
 | ||||
| \begin{methoddesc}[Message]{get_subtype}{\optional{failobj}} | ||||
| Return the message's sub-content type.  This essentially returns the | ||||
| \var{subtype} part of the string returned by \method{get_type()}, with the | ||||
| same semantics for \var{failobj}. | ||||
| 
 | ||||
| \deprecated{2.2.2}{Use the \method{get_content_subtype()} method instead.} | ||||
| \end{methoddesc} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,3 +1,11 @@ | |||
| \declaremodule{standard}{email.mime} | ||||
| \declaremodule{standard}{email.mime.base} | ||||
| \declaremodule{standard}{email.mime.nonmultipart} | ||||
| \declaremodule{standard}{email.mime.multipart} | ||||
| \declaremodule{standard}{email.mime.audio} | ||||
| \declaremodule{standard}{email.mime.image} | ||||
| \declaremodule{standard}{email.mime.message} | ||||
| \declaremodule{standard}{email.mime.text} | ||||
| Ordinarily, you get a message object structure by passing a file or | ||||
| some text to a parser, which parses the text and returns the root | ||||
| message object.  However you can also build a complete message | ||||
|  | @ -6,26 +14,16 @@ hand.  In fact, you can also take an existing structure and add new | |||
| \class{Message} objects, move them around, etc.  This makes a very | ||||
| convenient interface for slicing-and-dicing MIME messages. | ||||
| 
 | ||||
| You can create a new object structure by creating \class{Message} | ||||
| instances, adding attachments and all the appropriate headers manually. | ||||
| For MIME messages though, the \module{email} package provides some | ||||
| convenient subclasses to make things easier.  Each of these classes | ||||
| should be imported from a module with the same name as the class, from | ||||
| within the \module{email} package.  E.g.: | ||||
| 
 | ||||
| \begin{verbatim} | ||||
| import email.MIMEImage.MIMEImage | ||||
| \end{verbatim} | ||||
| 
 | ||||
| or | ||||
| 
 | ||||
| \begin{verbatim} | ||||
| from email.MIMEText import MIMEText | ||||
| \end{verbatim} | ||||
| You can create a new object structure by creating \class{Message} instances, | ||||
| adding attachments and all the appropriate headers manually.  For MIME | ||||
| messages though, the \module{email} package provides some convenient | ||||
| subclasses to make things easier. | ||||
| 
 | ||||
| Here are the classes: | ||||
| 
 | ||||
| \begin{classdesc}{MIMEBase}{_maintype, _subtype, **_params} | ||||
| Module: \module{email.mime.base} | ||||
| 
 | ||||
| This is the base class for all the MIME-specific subclasses of | ||||
| \class{Message}.  Ordinarily you won't create instances specifically | ||||
| of \class{MIMEBase}, although you could.  \class{MIMEBase} is provided | ||||
|  | @ -45,6 +43,8 @@ The \class{MIMEBase} class always adds a \mailheader{Content-Type} header | |||
| \end{classdesc} | ||||
| 
 | ||||
| \begin{classdesc}{MIMENonMultipart}{} | ||||
| Module: \module{email.mime.nonmultipart} | ||||
| 
 | ||||
| A subclass of \class{MIMEBase}, this is an intermediate base class for | ||||
| MIME messages that are not \mimetype{multipart}.  The primary purpose | ||||
| of this class is to prevent the use of the \method{attach()} method, | ||||
|  | @ -57,6 +57,7 @@ exception is raised. | |||
| 
 | ||||
| \begin{classdesc}{MIMEMultipart}{\optional{subtype\optional{, | ||||
|     boundary\optional{, _subparts\optional{, _params}}}}} | ||||
| Module: \module{email.mime.multipart} | ||||
| 
 | ||||
| A subclass of \class{MIMEBase}, this is an intermediate base class for | ||||
| MIME messages that are \mimetype{multipart}.  Optional \var{_subtype} | ||||
|  | @ -80,8 +81,31 @@ argument, which is a keyword dictionary. | |||
| \versionadded{2.2.2} | ||||
| \end{classdesc} | ||||
| 
 | ||||
| \begin{classdesc}{MIMEApplication}{_data\optional{, _subtype\optional{, | ||||
|     _encoder\optional{, **_params}}}} | ||||
| Module: \module{email.mime.application} | ||||
| 
 | ||||
| A subclass of \class{MIMENonMultipart}, the \class{MIMEApplication} class is | ||||
| used to represent MIME message objects of major type \mimetype{application}. | ||||
| \var{_data} is a string containing the raw byte data.  Optional \var{_subtype} | ||||
| specifies the MIME subtype and defaults to \mimetype{octet-stream}.   | ||||
| 
 | ||||
| Optional \var{_encoder} is a callable (i.e. function) which will | ||||
| perform the actual encoding of the data for transport.  This | ||||
| callable takes one argument, which is the \class{MIMEApplication} instance. | ||||
| It should use \method{get_payload()} and \method{set_payload()} to | ||||
| change the payload to encoded form.  It should also add any | ||||
| \mailheader{Content-Transfer-Encoding} or other headers to the message | ||||
| object as necessary.  The default encoding is base64.  See the | ||||
| \refmodule{email.encoders} module for a list of the built-in encoders. | ||||
| 
 | ||||
| \var{_params} are passed straight through to the base class constructor. | ||||
| \versionadded{2.5} | ||||
| \end{classdesc} | ||||
| 
 | ||||
| \begin{classdesc}{MIMEAudio}{_audiodata\optional{, _subtype\optional{, | ||||
|     _encoder\optional{, **_params}}}} | ||||
| Module: \module{email.mime.audio} | ||||
| 
 | ||||
| A subclass of \class{MIMENonMultipart}, the \class{MIMEAudio} class | ||||
| is used to create MIME message objects of major type \mimetype{audio}. | ||||
|  | @ -100,13 +124,14 @@ It should use \method{get_payload()} and \method{set_payload()} to | |||
| change the payload to encoded form.  It should also add any | ||||
| \mailheader{Content-Transfer-Encoding} or other headers to the message | ||||
| object as necessary.  The default encoding is base64.  See the | ||||
| \refmodule{email.Encoders} module for a list of the built-in encoders. | ||||
| \refmodule{email.encoders} module for a list of the built-in encoders. | ||||
| 
 | ||||
| \var{_params} are passed straight through to the base class constructor. | ||||
| \end{classdesc} | ||||
| 
 | ||||
| \begin{classdesc}{MIMEImage}{_imagedata\optional{, _subtype\optional{, | ||||
|     _encoder\optional{, **_params}}}} | ||||
| Module: \module{email.mime.image} | ||||
| 
 | ||||
| A subclass of \class{MIMENonMultipart}, the \class{MIMEImage} class is | ||||
| used to create MIME message objects of major type \mimetype{image}. | ||||
|  | @ -125,13 +150,15 @@ It should use \method{get_payload()} and \method{set_payload()} to | |||
| change the payload to encoded form.  It should also add any | ||||
| \mailheader{Content-Transfer-Encoding} or other headers to the message | ||||
| object as necessary.  The default encoding is base64.  See the | ||||
| \refmodule{email.Encoders} module for a list of the built-in encoders. | ||||
| \refmodule{email.encoders} module for a list of the built-in encoders. | ||||
| 
 | ||||
| \var{_params} are passed straight through to the \class{MIMEBase} | ||||
| constructor. | ||||
| \end{classdesc} | ||||
| 
 | ||||
| \begin{classdesc}{MIMEMessage}{_msg\optional{, _subtype}} | ||||
| Module: \module{email.mime.message} | ||||
| 
 | ||||
| A subclass of \class{MIMENonMultipart}, the \class{MIMEMessage} class | ||||
| is used to create MIME objects of main type \mimetype{message}. | ||||
| \var{_msg} is used as the payload, and must be an instance of class | ||||
|  | @ -143,6 +170,8 @@ to \mimetype{rfc822}. | |||
| \end{classdesc} | ||||
| 
 | ||||
| \begin{classdesc}{MIMEText}{_text\optional{, _subtype\optional{, _charset}}} | ||||
| Module: \module{email.mime.text} | ||||
| 
 | ||||
| A subclass of \class{MIMENonMultipart}, the \class{MIMEText} class is | ||||
| used to create MIME objects of major type \mimetype{text}. | ||||
| \var{_text} is the string for the payload.  \var{_subtype} is the | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| \declaremodule{standard}{email.Parser} | ||||
| \declaremodule{standard}{email.parser} | ||||
| \modulesynopsis{Parse flat text email messages to produce a message | ||||
| 	        object structure.} | ||||
| 
 | ||||
|  | @ -41,9 +41,10 @@ message object trees any way it finds necessary. | |||
| 
 | ||||
| \versionadded{2.4} | ||||
| 
 | ||||
| The \class{FeedParser} provides an API that is conducive to incremental | ||||
| parsing of email messages, such as would be necessary when reading the text of | ||||
| an email message from a source that can block (e.g. a socket).  The | ||||
| The \class{FeedParser}, imported from the \module{email.feedparser} module, | ||||
| provides an API that is conducive to incremental parsing of email messages, | ||||
| such as would be necessary when reading the text of an email message from a | ||||
| source that can block (e.g. a socket).  The | ||||
| \class{FeedParser} can of course be used to parse an email message fully | ||||
| contained in a string or a file, but the classic \class{Parser} API may be | ||||
| more convenient for such use cases.  The semantics and results of the two | ||||
|  | @ -56,14 +57,14 @@ accurate when parsing standards-compliant messages, and it does a very good | |||
| job of parsing non-compliant messages, providing information about how a | ||||
| message was deemed broken.  It will populate a message object's \var{defects} | ||||
| attribute with a list of any problems it found in a message.  See the | ||||
| \refmodule{email.Errors} module for the list of defects that it can find. | ||||
| \refmodule{email.errors} module for the list of defects that it can find. | ||||
| 
 | ||||
| Here is the API for the \class{FeedParser}: | ||||
| 
 | ||||
| \begin{classdesc}{FeedParser}{\optional{_factory}} | ||||
| Create a \class{FeedParser} instance.  Optional \var{_factory} is a | ||||
| no-argument callable that will be called whenever a new message object is | ||||
| needed.  It defaults to the \class{email.Message.Message} class. | ||||
| needed.  It defaults to the \class{email.message.Message} class. | ||||
| \end{classdesc} | ||||
| 
 | ||||
| \begin{methoddesc}[FeedParser]{feed}{data} | ||||
|  | @ -82,21 +83,22 @@ more data to a closed \class{FeedParser}. | |||
| 
 | ||||
| \subsubsection{Parser class API} | ||||
| 
 | ||||
| The \class{Parser} provides an API that can be used to parse a message when | ||||
| the complete contents of the message are available in a string or file.  The | ||||
| \module{email.Parser} module also provides a second class, called | ||||
| The \class{Parser} class, imported from the \module{email.parser} module, | ||||
| provides an API that can be used to parse a message when the complete contents | ||||
| of the message are available in a string or file.  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. | ||||
| 
 | ||||
| \begin{classdesc}{Parser}{\optional{_class\optional{, strict}}} | ||||
| \begin{classdesc}{Parser}{\optional{_class}} | ||||
| 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 | ||||
| \refmodule{email.message}).  The factory will be called without | ||||
| arguments. | ||||
| 
 | ||||
| The optional \var{strict} flag is ignored.  \deprecated{2.4}{Because the | ||||
|  | @ -201,6 +203,6 @@ Here are some notes on the parsing semantics: | |||
|       \method{is_multipart()} method may return \code{False}.  If such | ||||
|       messages were parsed with the \class{FeedParser}, they will have an | ||||
|       instance of the \class{MultipartInvariantViolationDefect} class in their | ||||
|       \var{defects} attribute list.  See \refmodule{email.Errors} for | ||||
|       \var{defects} attribute list.  See \refmodule{email.errors} for | ||||
|       details. | ||||
| \end{itemize} | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| \declaremodule{standard}{email.Utils} | ||||
| \declaremodule{standard}{email.utils} | ||||
| \modulesynopsis{Miscellaneous email package utilities.} | ||||
| 
 | ||||
| There are several useful utilities provided in the \module{email.Utils} | ||||
| There are several useful utilities provided in the \module{email.utils} | ||||
| module: | ||||
| 
 | ||||
| \begin{funcdesc}{quote}{str} | ||||
|  | @ -38,7 +38,7 @@ values as might be returned by \method{Message.get_all()}.  Here's a | |||
| simple example that gets all the recipients of a message: | ||||
| 
 | ||||
| \begin{verbatim} | ||||
| from email.Utils import getaddresses | ||||
| from email.utils import getaddresses | ||||
| 
 | ||||
| tos = msg.get_all('to', []) | ||||
| ccs = msg.get_all('cc', []) | ||||
|  |  | |||
|  | @ -12,9 +12,9 @@ | |||
| \authoraddress{\email{barry@python.org}} | ||||
| 
 | ||||
| \date{\today} | ||||
| \release{3.0}			% software release, not documentation | ||||
| \release{4.0}			% software release, not documentation | ||||
| \setreleaseinfo{}		% empty for final release | ||||
| \setshortversion{3.0}		% major.minor only for software | ||||
| \setshortversion{4.0}		% major.minor only for software | ||||
| 
 | ||||
| \begin{document} | ||||
| 
 | ||||
|  | @ -38,11 +38,11 @@ The \module{email} package provides classes and utilities to create, | |||
| parse, generate, and modify email messages, conforming to all the | ||||
| relevant email and MIME related RFCs. | ||||
| 
 | ||||
| This document describes version 3.0 of the \module{email} package, which is | ||||
| distributed with Python 2.4 and is available as a standalone distutils-based | ||||
| package for use with Python 2.3.  \module{email} 3.0 is not compatible with | ||||
| Python versions earlier than 2.3.  For more information about the | ||||
| \module{email} package, including download links and mailing lists, see | ||||
| This document describes version 4.0 of the \module{email} package, which is | ||||
| distributed with Python 2.5 and is available as a standalone distutils-based | ||||
| package for use with earlier Python versions.  \module{email} 4.0 is not | ||||
| compatible with Python versions earlier than 2.3.  For more information about | ||||
| the \module{email} package, including download links and mailing lists, see | ||||
| \ulink{Python's email SIG}{http://www.python.org/sigs/email-sig}. | ||||
| 
 | ||||
| The documentation that follows was written for the Python project, so | ||||
|  | @ -51,7 +51,8 @@ package documentation, there are a few notes to be aware of: | |||
| 
 | ||||
| \begin{itemize} | ||||
| \item Deprecation and ``version added'' notes are relative to the | ||||
|       Python version a feature was added or deprecated. | ||||
|       Python version a feature was added or deprecated.  See | ||||
|       the package history in section \ref{email-pkg-history} for details. | ||||
| 
 | ||||
| \item If you're reading this documentation as part of the | ||||
|       standalone \module{email} package, some of the internal links to | ||||
|  |  | |||
|  | @ -4,9 +4,10 @@ | |||
| 
 | ||||
| """A package for parsing, handling, and generating email messages.""" | ||||
| 
 | ||||
| __version__ = '3.0.1' | ||||
| __version__ = '4.0a2' | ||||
| 
 | ||||
| __all__ = [ | ||||
|     # Old names | ||||
|     'base64MIME', | ||||
|     'Charset', | ||||
|     'Encoders', | ||||
|  | @ -27,6 +28,19 @@ | |||
|     'Utils', | ||||
|     'message_from_string', | ||||
|     'message_from_file', | ||||
|     # new names | ||||
|     'base64mime', | ||||
|     'charset', | ||||
|     'encoders', | ||||
|     'errors', | ||||
|     'generator', | ||||
|     'header', | ||||
|     'iterators', | ||||
|     'message', | ||||
|     'mime', | ||||
|     'parser', | ||||
|     'quoprimime', | ||||
|     'utils', | ||||
|     ] | ||||
| 
 | ||||
| 
 | ||||
|  | @ -39,7 +53,7 @@ def message_from_string(s, *args, **kws): | |||
| 
 | ||||
|     Optional _class and strict are passed to the Parser constructor. | ||||
|     """ | ||||
|     from email.Parser import Parser | ||||
|     from email.parser import Parser | ||||
|     return Parser(*args, **kws).parsestr(s) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -48,5 +62,62 @@ def message_from_file(fp, *args, **kws): | |||
| 
 | ||||
|     Optional _class and strict are passed to the Parser constructor. | ||||
|     """ | ||||
|     from email.Parser import Parser | ||||
|     from email.parser import Parser | ||||
|     return Parser(*args, **kws).parse(fp) | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| # Lazy loading to provide name mapping from new-style names (PEP 8 compatible | ||||
| # email 4.0 module names), to old-style names (email 3.0 module names). | ||||
| import sys | ||||
| 
 | ||||
| class LazyImporter(object): | ||||
|   def __init__(self, module_name): | ||||
|       self.__name__ = 'email.' + module_name | ||||
| 
 | ||||
|   def __getattr__(self, name): | ||||
|       __import__(self.__name__) | ||||
|       mod = sys.modules[self.__name__] | ||||
|       self.__dict__.update(mod.__dict__) | ||||
|       return getattr(mod, name) | ||||
| 
 | ||||
| 
 | ||||
| _LOWERNAMES = [ | ||||
|     # email.<old name> -> email.<new name is lowercased old name> | ||||
|     'Charset', | ||||
|     'Encoders', | ||||
|     'Errors', | ||||
|     'FeedParser', | ||||
|     'Generator', | ||||
|     'Header', | ||||
|     'Iterators', | ||||
|     'Message', | ||||
|     'Parser', | ||||
|     'Utils', | ||||
|     'base64MIME', | ||||
|     'quopriMIME', | ||||
|     ] | ||||
| 
 | ||||
| _MIMENAMES = [ | ||||
|     # email.MIME<old name> -> email.mime.<new name is lowercased old name> | ||||
|     'Audio', | ||||
|     'Base', | ||||
|     'Image', | ||||
|     'Message', | ||||
|     'Multipart', | ||||
|     'NonMultipart', | ||||
|     'Text', | ||||
|     ] | ||||
| 
 | ||||
| for _name in _LOWERNAMES: | ||||
|     importer = LazyImporter(_name.lower()) | ||||
|     sys.modules['email.' + _name] = importer | ||||
|     setattr(sys.modules['email'], _name, importer) | ||||
| 
 | ||||
| 
 | ||||
| import email.mime | ||||
| for _name in _MIMENAMES: | ||||
|     importer = LazyImporter('mime.' + _name.lower()) | ||||
|     sys.modules['email.MIME' + _name] = importer | ||||
|     setattr(sys.modules['email'], 'MIME' + _name, importer) | ||||
|     setattr(sys.modules['email.mime'], _name, importer) | ||||
|  |  | |||
|  | @ -6,6 +6,13 @@ | |||
| Lifted directly from rfc822.py.  This should eventually be rewritten. | ||||
| """ | ||||
| 
 | ||||
| __all__ = [ | ||||
|     'mktime_tz', | ||||
|     'parsedate', | ||||
|     'parsedate_tz', | ||||
|     'quote', | ||||
|     ] | ||||
| 
 | ||||
| import time | ||||
| 
 | ||||
| SPACE = ' ' | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| # Copyright (C) 2002-2004 Python Software Foundation | ||||
| # Copyright (C) 2002-2006 Python Software Foundation | ||||
| # Author: Ben Gertzfield | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
|  | @ -24,9 +24,21 @@ | |||
| module. | ||||
| """ | ||||
| 
 | ||||
| __all__ = [ | ||||
|     'base64_len', | ||||
|     'body_decode', | ||||
|     'body_encode', | ||||
|     'decode', | ||||
|     'decodestring', | ||||
|     'encode', | ||||
|     'encodestring', | ||||
|     'header_encode', | ||||
|     ] | ||||
| 
 | ||||
| import re | ||||
| 
 | ||||
| from binascii import b2a_base64, a2b_base64 | ||||
| from email.Utils import fix_eols | ||||
| from email.utils import fix_eols | ||||
| 
 | ||||
| CRLF = '\r\n' | ||||
| NL = '\n' | ||||
|  | @ -2,9 +2,18 @@ | |||
| # Author: Ben Gertzfield, Barry Warsaw | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
| import email.base64MIME | ||||
| import email.quopriMIME | ||||
| from email.Encoders import encode_7or8bit | ||||
| __all__ = [ | ||||
|     'Charset', | ||||
|     'add_alias', | ||||
|     'add_charset', | ||||
|     'add_codec', | ||||
|     ] | ||||
| 
 | ||||
| import email.base64mime | ||||
| import email.quoprimime | ||||
| 
 | ||||
| from email import errors | ||||
| from email.encoders import encode_7or8bit | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
|  | @ -186,8 +195,17 @@ class Charset: | |||
|     """ | ||||
|     def __init__(self, input_charset=DEFAULT_CHARSET): | ||||
|         # RFC 2046, $4.1.2 says charsets are not case sensitive.  We coerce to | ||||
|         # unicode because its .lower() is locale insensitive. | ||||
|         input_charset = unicode(input_charset, 'ascii').lower() | ||||
|         # unicode because its .lower() is locale insensitive.  If the argument | ||||
|         # is already a unicode, we leave it at that, but ensure that the | ||||
|         # charset is ASCII, as the standard (RFC XXX) requires. | ||||
|         try: | ||||
|             if isinstance(input_charset, unicode): | ||||
|                 input_charset.encode('ascii') | ||||
|             else: | ||||
|                 input_charset = unicode(input_charset, 'ascii') | ||||
|         except UnicodeError: | ||||
|             raise errors.CharsetError(input_charset) | ||||
|         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 | ||||
|  | @ -307,12 +325,12 @@ def encoded_header_len(self, s): | |||
|         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 | ||||
|             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 | ||||
|             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) | ||||
|             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) | ||||
|  | @ -335,16 +353,16 @@ def header_encode(self, s, convert=False): | |||
|             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) | ||||
|             return email.base64mime.header_encode(s, cset) | ||||
|         elif self.header_encoding == QP: | ||||
|             return email.quopriMIME.header_encode(s, cset, maxlinelen=None) | ||||
|             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) | ||||
|             lenb64 = email.base64mime.base64_len(s) | ||||
|             lenqp = email.quoprimime.header_quopri_len(s) | ||||
|             if lenb64 < lenqp: | ||||
|                 return email.base64MIME.header_encode(s, cset) | ||||
|                 return email.base64mime.header_encode(s, cset) | ||||
|             else: | ||||
|                 return email.quopriMIME.header_encode(s, cset, maxlinelen=None) | ||||
|                 return email.quoprimime.header_encode(s, cset, maxlinelen=None) | ||||
|         else: | ||||
|             return s | ||||
| 
 | ||||
|  | @ -363,8 +381,8 @@ def body_encode(self, s, convert=True): | |||
|             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) | ||||
|             return email.base64mime.body_encode(s) | ||||
|         elif self.body_encoding is QP: | ||||
|             return email.quopriMIME.body_encode(s) | ||||
|             return email.quoprimime.body_encode(s) | ||||
|         else: | ||||
|             return s | ||||
|  | @ -1,12 +1,22 @@ | |||
| # Copyright (C) 2001-2004 Python Software Foundation | ||||
| # Copyright (C) 2001-2006 Python Software Foundation | ||||
| # Author: Barry Warsaw | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
| """Encodings and related functions.""" | ||||
| 
 | ||||
| __all__ = [ | ||||
|     'encode_7or8bit', | ||||
|     'encode_base64', | ||||
|     'encode_noop', | ||||
|     'encode_quopri', | ||||
|     ] | ||||
| 
 | ||||
| import base64 | ||||
| 
 | ||||
| from quopri import encodestring as _encodestring | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| def _qencode(s): | ||||
|     enc = _encodestring(s, quotetabs=True) | ||||
|     # Must encode spaces, which quopri.encodestring() doesn't do | ||||
|  | @ -1,4 +1,4 @@ | |||
| # Copyright (C) 2001-2004 Python Software Foundation | ||||
| # Copyright (C) 2001-2006 Python Software Foundation | ||||
| # Author: Barry Warsaw | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
|  | @ -26,6 +26,10 @@ class MultipartConversionError(MessageError, TypeError): | |||
|     """Conversion to a multipart is prohibited.""" | ||||
| 
 | ||||
| 
 | ||||
| class CharsetError(MessageError): | ||||
|     """An illegal charset was given.""" | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| # These are parsing defects which the parser was able to work around. | ||||
| class MessageDefect: | ||||
|  | @ -19,9 +19,12 @@ | |||
| object's .defects attribute. | ||||
| """ | ||||
| 
 | ||||
| __all__ = ['FeedParser'] | ||||
| 
 | ||||
| import re | ||||
| from email import Errors | ||||
| from email import Message | ||||
| 
 | ||||
| from email import errors | ||||
| from email import message | ||||
| 
 | ||||
| NLCRE = re.compile('\r\n|\r|\n') | ||||
| NLCRE_bol = re.compile('(\r\n|\r|\n)') | ||||
|  | @ -130,7 +133,7 @@ def next(self): | |||
| class FeedParser: | ||||
|     """A feed-style parser of email.""" | ||||
| 
 | ||||
|     def __init__(self, _factory=Message.Message): | ||||
|     def __init__(self, _factory=message.Message): | ||||
|         """_factory is called with no arguments to create a new message obj""" | ||||
|         self._factory = _factory | ||||
|         self._input = BufferedSubFile() | ||||
|  | @ -164,7 +167,7 @@ def close(self): | |||
|         # Look for final set of defects | ||||
|         if root.get_content_maintype() == 'multipart' \ | ||||
|                and not root.is_multipart(): | ||||
|             root.defects.append(Errors.MultipartInvariantViolationDefect()) | ||||
|             root.defects.append(errors.MultipartInvariantViolationDefect()) | ||||
|         return root | ||||
| 
 | ||||
|     def _new_message(self): | ||||
|  | @ -277,7 +280,7 @@ def _parsegen(self): | |||
|                 # defined a boundary.  That's a problem which we'll handle by | ||||
|                 # reading everything until the EOF and marking the message as | ||||
|                 # defective. | ||||
|                 self._cur.defects.append(Errors.NoBoundaryInMultipartDefect()) | ||||
|                 self._cur.defects.append(errors.NoBoundaryInMultipartDefect()) | ||||
|                 lines = [] | ||||
|                 for line in self._input: | ||||
|                     if line is NeedMoreData: | ||||
|  | @ -381,7 +384,7 @@ def _parsegen(self): | |||
|             # that as a defect and store the captured text as the payload. | ||||
|             # Everything from here to the EOF is epilogue. | ||||
|             if capturing_preamble: | ||||
|                 self._cur.defects.append(Errors.StartBoundaryNotFoundDefect()) | ||||
|                 self._cur.defects.append(errors.StartBoundaryNotFoundDefect()) | ||||
|                 self._cur.set_payload(EMPTYSTRING.join(preamble)) | ||||
|                 epilogue = [] | ||||
|                 for line in self._input: | ||||
|  | @ -432,7 +435,7 @@ def _parse_headers(self, lines): | |||
|                     # The first line of the headers was a continuation.  This | ||||
|                     # is illegal, so let's note the defect, store the illegal | ||||
|                     # line, and ignore it for purposes of headers. | ||||
|                     defect = Errors.FirstHeaderLineIsContinuationDefect(line) | ||||
|                     defect = errors.FirstHeaderLineIsContinuationDefect(line) | ||||
|                     self._cur.defects.append(defect) | ||||
|                     continue | ||||
|                 lastvalue.append(line) | ||||
|  | @ -460,13 +463,13 @@ def _parse_headers(self, lines): | |||
|                 else: | ||||
|                     # Weirdly placed unix-from line.  Note this as a defect | ||||
|                     # and ignore it. | ||||
|                     defect = Errors.MisplacedEnvelopeHeaderDefect(line) | ||||
|                     defect = errors.MisplacedEnvelopeHeaderDefect(line) | ||||
|                     self._cur.defects.append(defect) | ||||
|                     continue | ||||
|             # Split the line on the colon separating field name from value. | ||||
|             i = line.find(':') | ||||
|             if i < 0: | ||||
|                 defect = Errors.MalformedHeaderDefect(line) | ||||
|                 defect = errors.MalformedHeaderDefect(line) | ||||
|                 self._cur.defects.append(defect) | ||||
|                 continue | ||||
|             lastheader = line[:i] | ||||
|  | @ -4,14 +4,16 @@ | |||
| 
 | ||||
| """Classes to generate plain text from a message object tree.""" | ||||
| 
 | ||||
| __all__ = ['Generator', 'DecodedGenerator'] | ||||
| 
 | ||||
| import re | ||||
| import sys | ||||
| import time | ||||
| import random | ||||
| import warnings | ||||
| from cStringIO import StringIO | ||||
| 
 | ||||
| from email.Header import Header | ||||
| from cStringIO import StringIO | ||||
| from email.header import Header | ||||
| 
 | ||||
| UNDERSCORE = '_' | ||||
| NL = '\n' | ||||
|  | @ -81,12 +83,6 @@ def flatten(self, msg, unixfrom=False): | |||
|             print >> self._fp, ufrom | ||||
|         self._write(msg) | ||||
| 
 | ||||
|     # For backwards compatibility, but this is slower | ||||
|     def __call__(self, msg, unixfrom=False): | ||||
|         warnings.warn('__call__() deprecated; use flatten()', | ||||
|                       DeprecationWarning, 2) | ||||
|         self.flatten(msg, unixfrom) | ||||
| 
 | ||||
|     def clone(self, fp): | ||||
|         """Clone this generator with the exact same options.""" | ||||
|         return self.__class__(fp, self._mangle_from_, self._maxheaderlen) | ||||
|  | @ -1,16 +1,23 @@ | |||
| # Copyright (C) 2002-2004 Python Software Foundation | ||||
| # Copyright (C) 2002-2006 Python Software Foundation | ||||
| # Author: Ben Gertzfield, Barry Warsaw | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
| """Header encoding and decoding functionality.""" | ||||
| 
 | ||||
| __all__ = [ | ||||
|     'Header', | ||||
|     'decode_header', | ||||
|     'make_header', | ||||
|     ] | ||||
| 
 | ||||
| import re | ||||
| import binascii | ||||
| 
 | ||||
| import email.quopriMIME | ||||
| import email.base64MIME | ||||
| from email.Errors import HeaderParseError | ||||
| from email.Charset import Charset | ||||
| import email.quoprimime | ||||
| import email.base64mime | ||||
| 
 | ||||
| from email.errors import HeaderParseError | ||||
| from email.charset import Charset | ||||
| 
 | ||||
| NL = '\n' | ||||
| SPACE = ' ' | ||||
|  | @ -42,7 +49,7 @@ | |||
| 
 | ||||
|  | ||||
| # Helpers | ||||
| _max_append = email.quopriMIME._max_append | ||||
| _max_append = email.quoprimime._max_append | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
|  | @ -82,10 +89,10 @@ def decode_header(header): | |||
|                 encoded = parts[2] | ||||
|                 dec = None | ||||
|                 if encoding == 'q': | ||||
|                     dec = email.quopriMIME.header_decode(encoded) | ||||
|                     dec = email.quoprimime.header_decode(encoded) | ||||
|                 elif encoding == 'b': | ||||
|                     try: | ||||
|                         dec = email.base64MIME.decode(encoded) | ||||
|                         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 | ||||
|  | @ -1,9 +1,16 @@ | |||
| # Copyright (C) 2001-2004 Python Software Foundation | ||||
| # Copyright (C) 2001-2006 Python Software Foundation | ||||
| # Author: Barry Warsaw | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
| """Various types of useful iterators and generators.""" | ||||
| 
 | ||||
| __all__ = [ | ||||
|     'body_line_iterator', | ||||
|     'typed_subpart_iterator', | ||||
|     'walk', | ||||
|     # Do not include _structure() since it's part of the debugging API. | ||||
|     ] | ||||
| 
 | ||||
| import sys | ||||
| from cStringIO import StringIO | ||||
| 
 | ||||
|  | @ -25,7 +32,6 @@ def walk(self): | |||
| 
 | ||||
|  | ||||
| # These two functions are imported into the Iterators.py interface module. | ||||
| # The Python 2.2 version uses generators for efficiency. | ||||
| def body_line_iterator(msg, decode=False): | ||||
|     """Iterate over the parts, returning string payloads line-by-line. | ||||
| 
 | ||||
|  | @ -4,6 +4,8 @@ | |||
| 
 | ||||
| """Basic message object for the email package object model.""" | ||||
| 
 | ||||
| __all__ = ['Message'] | ||||
| 
 | ||||
| import re | ||||
| import uu | ||||
| import binascii | ||||
|  | @ -11,9 +13,9 @@ | |||
| from cStringIO import StringIO | ||||
| 
 | ||||
| # Intrapackage imports | ||||
| from email import Utils | ||||
| from email import Errors | ||||
| from email import Charset | ||||
| import email.charset | ||||
| from email import utils | ||||
| from email import errors | ||||
| 
 | ||||
| SEMISPACE = '; ' | ||||
| 
 | ||||
|  | @ -41,11 +43,11 @@ def _formatparam(param, value=None, quote=True): | |||
|         if isinstance(value, tuple): | ||||
|             # Encode as per RFC 2231 | ||||
|             param += '*' | ||||
|             value = Utils.encode_rfc2231(value[2], value[0], value[1]) | ||||
|             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)) | ||||
|             return '%s="%s"' % (param, utils.quote(value)) | ||||
|         else: | ||||
|             return '%s=%s' % (param, value) | ||||
|     else: | ||||
|  | @ -70,14 +72,14 @@ def _parseparam(s): | |||
| 
 | ||||
| 
 | ||||
| def _unquotevalue(value): | ||||
|     # This is different than Utils.collapse_rfc2231_value() because it doesn't | ||||
|     # This is different than utils.collapse_rfc2231_value() because it doesn't | ||||
|     # try to convert the value to a unicode.  Message.get_param() and | ||||
|     # Message.get_params() are both currently defined to return the tuple in | ||||
|     # the face of RFC 2231 parameters. | ||||
|     if isinstance(value, tuple): | ||||
|         return value[0], value[1], Utils.unquote(value[2]) | ||||
|         return value[0], value[1], utils.unquote(value[2]) | ||||
|     else: | ||||
|         return Utils.unquote(value) | ||||
|         return utils.unquote(value) | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
|  | @ -188,17 +190,17 @@ def get_payload(self, i=None, decode=False): | |||
|                 return None | ||||
|             cte = self.get('content-transfer-encoding', '').lower() | ||||
|             if cte == 'quoted-printable': | ||||
|                 return Utils._qdecode(payload) | ||||
|                 return utils._qdecode(payload) | ||||
|             elif cte == 'base64': | ||||
|                 try: | ||||
|                     return Utils._bdecode(payload) | ||||
|                     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) | ||||
|                     uu.decode(StringIO(payload+'\n'), sfp, quiet=True) | ||||
|                     payload = sfp.getvalue() | ||||
|                 except uu.Error: | ||||
|                     # Some decoding problem | ||||
|  | @ -237,8 +239,8 @@ def set_charset(self, charset): | |||
|             self._charset = None | ||||
|             return | ||||
|         if isinstance(charset, str): | ||||
|             charset = Charset.Charset(charset) | ||||
|         if not isinstance(charset, Charset.Charset): | ||||
|             charset = email.charset.Charset(charset) | ||||
|         if not isinstance(charset, email.charset.Charset): | ||||
|             raise TypeError(charset) | ||||
|         # BAW: should we accept strings that can serve as arguments to the | ||||
|         # Charset constructor? | ||||
|  | @ -412,49 +414,6 @@ def replace_header(self, _name, _value): | |||
|         else: | ||||
|             raise KeyError(_name) | ||||
| 
 | ||||
|     # | ||||
|     # Deprecated methods.  These will be removed in email 3.1. | ||||
|     # | ||||
| 
 | ||||
|     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). | ||||
|         """ | ||||
|         warnings.warn('get_type() deprecated; use get_content_type()', | ||||
|                       DeprecationWarning, 2) | ||||
|         missing = object() | ||||
|         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.""" | ||||
|         warnings.warn('get_main_type() deprecated; use get_content_maintype()', | ||||
|                       DeprecationWarning, 2) | ||||
|         missing = object() | ||||
|         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.""" | ||||
|         warnings.warn('get_subtype() deprecated; use get_content_subtype()', | ||||
|                       DeprecationWarning, 2) | ||||
|         missing = object() | ||||
|         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. | ||||
|     # | ||||
|  | @ -537,7 +496,7 @@ def _get_params_preserve(self, failobj, header): | |||
|                 name = p.strip() | ||||
|                 val = '' | ||||
|             params.append((name, val)) | ||||
|         params = Utils.decode_params(params) | ||||
|         params = utils.decode_params(params) | ||||
|         return params | ||||
| 
 | ||||
|     def get_params(self, failobj=None, header='content-type', unquote=True): | ||||
|  | @ -714,7 +673,7 @@ def get_filename(self, failobj=None): | |||
|             filename = self.get_param('name', missing, 'content-disposition') | ||||
|         if filename is missing: | ||||
|             return failobj | ||||
|         return Utils.collapse_rfc2231_value(filename).strip() | ||||
|         return utils.collapse_rfc2231_value(filename).strip() | ||||
| 
 | ||||
|     def get_boundary(self, failobj=None): | ||||
|         """Return the boundary associated with the payload if present. | ||||
|  | @ -727,7 +686,7 @@ def get_boundary(self, failobj=None): | |||
|         if boundary is missing: | ||||
|             return failobj | ||||
|         # RFC 2046 says that boundaries may begin but not end in w/s | ||||
|         return Utils.collapse_rfc2231_value(boundary).rstrip() | ||||
|         return utils.collapse_rfc2231_value(boundary).rstrip() | ||||
| 
 | ||||
|     def set_boundary(self, boundary): | ||||
|         """Set the boundary parameter in Content-Type to 'boundary'. | ||||
|  | @ -744,7 +703,7 @@ def set_boundary(self, boundary): | |||
|         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' | ||||
|             raise errors.HeaderParseError('No Content-Type header found') | ||||
|         newparams = [] | ||||
|         foundp = False | ||||
|         for pk, pv in params: | ||||
							
								
								
									
										0
									
								
								Lib/email/mime/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								Lib/email/mime/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										36
									
								
								Lib/email/mime/application.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								Lib/email/mime/application.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| # Copyright (C) 2001-2006 Python Software Foundation | ||||
| # Author: Keith Dart | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
| """Class representing application/* type MIME documents.""" | ||||
| 
 | ||||
| __all__ = ["MIMEApplication"] | ||||
| 
 | ||||
| from email import encoders | ||||
| from email.mime.nonmultipart import MIMENonMultipart | ||||
| 
 | ||||
| 
 | ||||
| class MIMEApplication(MIMENonMultipart): | ||||
|     """Class for generating application/* MIME documents.""" | ||||
| 
 | ||||
|     def __init__(self, _data, _subtype='octet-stream', | ||||
|                  _encoder=encoders.encode_base64, **_params): | ||||
|         """Create an application/* type MIME document. | ||||
| 
 | ||||
|         _data is a string containing the raw applicatoin data. | ||||
| 
 | ||||
|         _subtype is the MIME content type subtype, defaulting to | ||||
|         'octet-stream'. | ||||
| 
 | ||||
|         _encoder is a function which will perform the actual encoding for | ||||
|         transport of the application data, defaulting to base64 encoding. | ||||
| 
 | ||||
|         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: | ||||
|             raise TypeError('Invalid application MIME subtype') | ||||
|         MIMENonMultipart.__init__(self, 'application', _subtype, **_params) | ||||
|         self.set_payload(_data) | ||||
|         _encoder(self) | ||||
|  | @ -1,15 +1,16 @@ | |||
| # Copyright (C) 2001-2004 Python Software Foundation | ||||
| # Copyright (C) 2001-2006 Python Software Foundation | ||||
| # Author: Anthony Baxter | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
| """Class representing audio/* type MIME documents.""" | ||||
| 
 | ||||
| import sndhdr | ||||
| from cStringIO import StringIO | ||||
| __all__ = ['MIMEAudio'] | ||||
| 
 | ||||
| from email import Errors | ||||
| from email import Encoders | ||||
| from email.MIMENonMultipart import MIMENonMultipart | ||||
| import sndhdr | ||||
| 
 | ||||
| from cStringIO import StringIO | ||||
| from email import encoders | ||||
| from email.mime.nonmultipart import MIMENonMultipart | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
|  | @ -42,7 +43,7 @@ class MIMEAudio(MIMENonMultipart): | |||
|     """Class for generating audio/* MIME documents.""" | ||||
| 
 | ||||
|     def __init__(self, _audiodata, _subtype=None, | ||||
|                  _encoder=Encoders.encode_base64, **_params): | ||||
|                  _encoder=encoders.encode_base64, **_params): | ||||
|         """Create an audio/* type MIME document. | ||||
| 
 | ||||
|         _audiodata is a string containing the raw audio data.  If this data | ||||
|  | @ -1,14 +1,16 @@ | |||
| # Copyright (C) 2001-2004 Python Software Foundation | ||||
| # Copyright (C) 2001-2006 Python Software Foundation | ||||
| # Author: Barry Warsaw | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
| """Base class for MIME specializations.""" | ||||
| 
 | ||||
| from email import Message | ||||
| __all__ = ['MIMEBase'] | ||||
| 
 | ||||
| from email import message | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| class MIMEBase(Message.Message): | ||||
| class MIMEBase(message.Message): | ||||
|     """Base class for MIME specializations.""" | ||||
| 
 | ||||
|     def __init__(self, _maintype, _subtype, **_params): | ||||
|  | @ -18,7 +20,7 @@ def __init__(self, _maintype, _subtype, **_params): | |||
|         arguments.  Additional parameters for this header are taken from the | ||||
|         keyword arguments. | ||||
|         """ | ||||
|         Message.Message.__init__(self) | ||||
|         message.Message.__init__(self) | ||||
|         ctype = '%s/%s' % (_maintype, _subtype) | ||||
|         self.add_header('Content-Type', ctype, **_params) | ||||
|         self['MIME-Version'] = '1.0' | ||||
|  | @ -1,14 +1,15 @@ | |||
| # Copyright (C) 2001-2004 Python Software Foundation | ||||
| # Copyright (C) 2001-2006 Python Software Foundation | ||||
| # Author: Barry Warsaw | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
| """Class representing image/* type MIME documents.""" | ||||
| 
 | ||||
| __all__ = ['MIMEImage'] | ||||
| 
 | ||||
| import imghdr | ||||
| 
 | ||||
| from email import Errors | ||||
| from email import Encoders | ||||
| from email.MIMENonMultipart import MIMENonMultipart | ||||
| from email import encoders | ||||
| from email.mime.nonmultipart import MIMENonMultipart | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
|  | @ -16,7 +17,7 @@ class MIMEImage(MIMENonMultipart): | |||
|     """Class for generating image/* type MIME documents.""" | ||||
| 
 | ||||
|     def __init__(self, _imagedata, _subtype=None, | ||||
|                  _encoder=Encoders.encode_base64, **_params): | ||||
|                  _encoder=encoders.encode_base64, **_params): | ||||
|         """Create an image/* type MIME document. | ||||
| 
 | ||||
|         _imagedata is a string containing the raw image data.  If this data | ||||
|  | @ -1,11 +1,13 @@ | |||
| # Copyright (C) 2001-2004 Python Software Foundation | ||||
| # Copyright (C) 2001-2006 Python Software Foundation | ||||
| # Author: Barry Warsaw | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
| """Class representing message/* MIME documents.""" | ||||
| 
 | ||||
| from email import Message | ||||
| from email.MIMENonMultipart import MIMENonMultipart | ||||
| __all__ = ['MIMEMessage'] | ||||
| 
 | ||||
| from email import message | ||||
| from email.mime.nonmultipart import MIMENonMultipart | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
|  | @ -23,10 +25,10 @@ def __init__(self, _msg, _subtype='rfc822'): | |||
|         the term "rfc822" is technically outdated by RFC 2822). | ||||
|         """ | ||||
|         MIMENonMultipart.__init__(self, 'message', _subtype) | ||||
|         if not isinstance(_msg, Message.Message): | ||||
|         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) | ||||
|         message.Message.attach(self, _msg) | ||||
|         # And be sure our default type is set correctly | ||||
|         self.set_default_type('message/rfc822') | ||||
|  | @ -1,14 +1,16 @@ | |||
| # Copyright (C) 2002-2004 Python Software Foundation | ||||
| # Copyright (C) 2002-2006 Python Software Foundation | ||||
| # Author: Barry Warsaw | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
| """Base class for MIME multipart/* type messages.""" | ||||
| 
 | ||||
| from email import MIMEBase | ||||
| __all__ = ['MIMEMultipart'] | ||||
| 
 | ||||
| from email.mime.base import MIMEBase | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| class MIMEMultipart(MIMEBase.MIMEBase): | ||||
| class MIMEMultipart(MIMEBase): | ||||
|     """Base class for MIME multipart/* type messages.""" | ||||
| 
 | ||||
|     def __init__(self, _subtype='mixed', boundary=None, _subparts=None, | ||||
|  | @ -31,7 +33,7 @@ def __init__(self, _subtype='mixed', boundary=None, _subparts=None, | |||
|         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) | ||||
|         MIMEBase.__init__(self, 'multipart', _subtype, **_params) | ||||
|         if _subparts: | ||||
|             for p in _subparts: | ||||
|                 self.attach(p) | ||||
|  | @ -1,15 +1,17 @@ | |||
| # Copyright (C) 2002-2004 Python Software Foundation | ||||
| # Copyright (C) 2002-2006 Python Software Foundation | ||||
| # Author: Barry Warsaw | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
| """Base class for MIME type messages that are not multipart.""" | ||||
| 
 | ||||
| from email import Errors | ||||
| from email import MIMEBase | ||||
| __all__ = ['MIMENonMultipart'] | ||||
| 
 | ||||
| from email import errors | ||||
| from email.mime.base import MIMEBase | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| class MIMENonMultipart(MIMEBase.MIMEBase): | ||||
| class MIMENonMultipart(MIMEBase): | ||||
|     """Base class for MIME multipart/* type messages.""" | ||||
| 
 | ||||
|     __pychecker__ = 'unusednames=payload' | ||||
|  | @ -18,7 +20,7 @@ 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( | ||||
|         raise errors.MultipartConversionError( | ||||
|             'Cannot attach additional subparts to non-multipart/*') | ||||
| 
 | ||||
|     del __pychecker__ | ||||
|  | @ -1,11 +1,13 @@ | |||
| # Copyright (C) 2001-2004 Python Software Foundation | ||||
| # Copyright (C) 2001-2006 Python Software Foundation | ||||
| # Author: Barry Warsaw | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
| """Class representing text/* type MIME documents.""" | ||||
| 
 | ||||
| from email.MIMENonMultipart import MIMENonMultipart | ||||
| from email.Encoders import encode_7or8bit | ||||
| __all__ = ['MIMEText'] | ||||
| 
 | ||||
| from email.encoders import encode_7or8bit | ||||
| from email.mime.nonmultipart import MIMENonMultipart | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
|  | @ -1,13 +1,16 @@ | |||
| # Copyright (C) 2001-2004 Python Software Foundation | ||||
| # Copyright (C) 2001-2006 Python Software Foundation | ||||
| # Author: Barry Warsaw, Thomas Wouters, Anthony Baxter | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
| """A parser of RFC 2822 and MIME email messages.""" | ||||
| 
 | ||||
| __all__ = ['Parser', 'HeaderParser'] | ||||
| 
 | ||||
| import warnings | ||||
| from cStringIO import StringIO | ||||
| from email.FeedParser import FeedParser | ||||
| from email.Message import Message | ||||
| 
 | ||||
| from email.feedparser import FeedParser | ||||
| from email.message import Message | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
|  | @ -1,4 +1,4 @@ | |||
| # Copyright (C) 2001-2004 Python Software Foundation | ||||
| # Copyright (C) 2001-2006 Python Software Foundation | ||||
| # Author: Ben Gertzfield | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
|  | @ -26,9 +26,27 @@ | |||
| wrapping issues, use the email.Header module. | ||||
| """ | ||||
| 
 | ||||
| __all__ = [ | ||||
|     'body_decode', | ||||
|     'body_encode', | ||||
|     'body_quopri_check', | ||||
|     'body_quopri_len', | ||||
|     'decode', | ||||
|     'decodestring', | ||||
|     'encode', | ||||
|     'encodestring', | ||||
|     'header_decode', | ||||
|     'header_encode', | ||||
|     'header_quopri_check', | ||||
|     'header_quopri_len', | ||||
|     'quote', | ||||
|     'unquote', | ||||
|     ] | ||||
| 
 | ||||
| import re | ||||
| 
 | ||||
| from string import hexdigits | ||||
| from email.Utils import fix_eols | ||||
| from email.utils import fix_eols | ||||
| 
 | ||||
| CRLF = '\r\n' | ||||
| NL = '\n' | ||||
|  | @ -39,9 +39,6 @@ | |||
| EMPTYSTRING = '' | ||||
| SPACE = ' ' | ||||
| 
 | ||||
| # We don't care about DeprecationWarnings | ||||
| warnings.filterwarnings('ignore', '', DeprecationWarning, __name__) | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| def openfile(filename, mode='r'): | ||||
|  | @ -87,7 +84,7 @@ def test_getset_charset(self): | |||
|         charset = Charset('iso-8859-1') | ||||
|         msg.set_charset(charset) | ||||
|         eq(msg['mime-version'], '1.0') | ||||
|         eq(msg.get_type(), 'text/plain') | ||||
|         eq(msg.get_content_type(), 'text/plain') | ||||
|         eq(msg['content-type'], 'text/plain; charset="iso-8859-1"') | ||||
|         eq(msg.get_param('charset'), 'iso-8859-1') | ||||
|         eq(msg['content-transfer-encoding'], 'quoted-printable') | ||||
|  | @ -211,6 +208,19 @@ def test_get_decoded_uu_payload(self): | |||
|         msg.set_payload('foo') | ||||
|         eq(msg.get_payload(decode=True), 'foo') | ||||
| 
 | ||||
|     def test_decode_bogus_uu_payload_quietly(self): | ||||
|         msg = Message() | ||||
|         msg.set_payload('begin 664 foo.txt\n%<W1F=0000H \n \nend\n') | ||||
|         msg['Content-Transfer-Encoding'] = 'x-uuencode' | ||||
|         old_stderr = sys.stderr | ||||
|         try: | ||||
|             sys.stderr = sfp = StringIO() | ||||
|             # We don't care about the payload | ||||
|             msg.get_payload(decode=True) | ||||
|         finally: | ||||
|             sys.stderr = old_stderr | ||||
|         self.assertEqual(sfp.getvalue(), '') | ||||
| 
 | ||||
|     def test_decoded_generator(self): | ||||
|         eq = self.assertEqual | ||||
|         msg = self._msgobj('msg_07.txt') | ||||
|  | @ -893,7 +903,7 @@ def setUp(self): | |||
|         self._au = MIMEAudio(self._audiodata) | ||||
| 
 | ||||
|     def test_guess_minor_type(self): | ||||
|         self.assertEqual(self._au.get_type(), 'audio/basic') | ||||
|         self.assertEqual(self._au.get_content_type(), 'audio/basic') | ||||
| 
 | ||||
|     def test_encoding(self): | ||||
|         payload = self._au.get_payload() | ||||
|  | @ -901,7 +911,7 @@ def test_encoding(self): | |||
| 
 | ||||
|     def test_checkSetMinor(self): | ||||
|         au = MIMEAudio(self._audiodata, 'fish') | ||||
|         self.assertEqual(au.get_type(), 'audio/fish') | ||||
|         self.assertEqual(au.get_content_type(), 'audio/fish') | ||||
| 
 | ||||
|     def test_add_header(self): | ||||
|         eq = self.assertEqual | ||||
|  | @ -936,7 +946,7 @@ def setUp(self): | |||
|         self._im = MIMEImage(self._imgdata) | ||||
| 
 | ||||
|     def test_guess_minor_type(self): | ||||
|         self.assertEqual(self._im.get_type(), 'image/gif') | ||||
|         self.assertEqual(self._im.get_content_type(), 'image/gif') | ||||
| 
 | ||||
|     def test_encoding(self): | ||||
|         payload = self._im.get_payload() | ||||
|  | @ -944,7 +954,7 @@ def test_encoding(self): | |||
| 
 | ||||
|     def test_checkSetMinor(self): | ||||
|         im = MIMEImage(self._imgdata, 'fish') | ||||
|         self.assertEqual(im.get_type(), 'image/fish') | ||||
|         self.assertEqual(im.get_content_type(), 'image/fish') | ||||
| 
 | ||||
|     def test_add_header(self): | ||||
|         eq = self.assertEqual | ||||
|  | @ -976,7 +986,7 @@ def setUp(self): | |||
|     def test_types(self): | ||||
|         eq = self.assertEqual | ||||
|         unless = self.failUnless | ||||
|         eq(self._msg.get_type(), 'text/plain') | ||||
|         eq(self._msg.get_content_type(), 'text/plain') | ||||
|         eq(self._msg.get_param('charset'), 'us-ascii') | ||||
|         missing = [] | ||||
|         unless(self._msg.get_param('foobar', missing) is missing) | ||||
|  | @ -1045,7 +1055,7 @@ def test_hierarchy(self): | |||
|         # tests | ||||
|         m = self._msg | ||||
|         unless(m.is_multipart()) | ||||
|         eq(m.get_type(), 'multipart/mixed') | ||||
|         eq(m.get_content_type(), 'multipart/mixed') | ||||
|         eq(len(m.get_payload()), 2) | ||||
|         raises(IndexError, m.get_payload, 2) | ||||
|         m0 = m.get_payload(0) | ||||
|  | @ -1379,7 +1389,7 @@ class TestNonConformant(TestEmailBase): | |||
|     def test_parse_missing_minor_type(self): | ||||
|         eq = self.assertEqual | ||||
|         msg = self._msgobj('msg_14.txt') | ||||
|         eq(msg.get_type(), 'text') | ||||
|         eq(msg.get_content_type(), 'text/plain') | ||||
|         eq(msg.get_content_maintype(), 'text') | ||||
|         eq(msg.get_content_subtype(), 'plain') | ||||
| 
 | ||||
|  | @ -1531,7 +1541,7 @@ def test_valid_argument(self): | |||
|         m = Message() | ||||
|         m['Subject'] = subject | ||||
|         r = MIMEMessage(m) | ||||
|         eq(r.get_type(), 'message/rfc822') | ||||
|         eq(r.get_content_type(), 'message/rfc822') | ||||
|         payload = r.get_payload() | ||||
|         unless(isinstance(payload, list)) | ||||
|         eq(len(payload), 1) | ||||
|  | @ -1572,7 +1582,7 @@ def test_parse_message_rfc822(self): | |||
|         eq = self.assertEqual | ||||
|         unless = self.failUnless | ||||
|         msg = self._msgobj('msg_11.txt') | ||||
|         eq(msg.get_type(), 'message/rfc822') | ||||
|         eq(msg.get_content_type(), 'message/rfc822') | ||||
|         payload = msg.get_payload() | ||||
|         unless(isinstance(payload, list)) | ||||
|         eq(len(payload), 1) | ||||
|  | @ -1586,12 +1596,12 @@ def test_dsn(self): | |||
|         unless = self.failUnless | ||||
|         # msg 16 is a Delivery Status Notification, see RFC 1894 | ||||
|         msg = self._msgobj('msg_16.txt') | ||||
|         eq(msg.get_type(), 'multipart/report') | ||||
|         eq(msg.get_content_type(), 'multipart/report') | ||||
|         unless(msg.is_multipart()) | ||||
|         eq(len(msg.get_payload()), 3) | ||||
|         # Subpart 1 is a text/plain, human readable section | ||||
|         subpart = msg.get_payload(0) | ||||
|         eq(subpart.get_type(), 'text/plain') | ||||
|         eq(subpart.get_content_type(), 'text/plain') | ||||
|         eq(subpart.get_payload(), """\ | ||||
| This report relates to a message you sent with the following header fields: | ||||
| 
 | ||||
|  | @ -1611,7 +1621,7 @@ def test_dsn(self): | |||
|         # consists of two blocks of headers, represented by two nested Message | ||||
|         # objects. | ||||
|         subpart = msg.get_payload(1) | ||||
|         eq(subpart.get_type(), 'message/delivery-status') | ||||
|         eq(subpart.get_content_type(), 'message/delivery-status') | ||||
|         eq(len(subpart.get_payload()), 2) | ||||
|         # message/delivery-status should treat each block as a bunch of | ||||
|         # headers, i.e. a bunch of Message objects. | ||||
|  | @ -1629,13 +1639,13 @@ def test_dsn(self): | |||
|         eq(dsn2.get_param('rfc822', header='final-recipient'), '') | ||||
|         # Subpart 3 is the original message | ||||
|         subpart = msg.get_payload(2) | ||||
|         eq(subpart.get_type(), 'message/rfc822') | ||||
|         eq(subpart.get_content_type(), 'message/rfc822') | ||||
|         payload = subpart.get_payload() | ||||
|         unless(isinstance(payload, list)) | ||||
|         eq(len(payload), 1) | ||||
|         subsubpart = payload[0] | ||||
|         unless(isinstance(subsubpart, Message)) | ||||
|         eq(subsubpart.get_type(), 'text/plain') | ||||
|         eq(subsubpart.get_content_type(), 'text/plain') | ||||
|         eq(subsubpart['message-id'], | ||||
|            '<002001c144a6$8752e060$56104586@oxy.edu>') | ||||
| 
 | ||||
|  | @ -1706,16 +1716,16 @@ def test_default_type(self): | |||
|             fp.close() | ||||
|         container1 = msg.get_payload(0) | ||||
|         eq(container1.get_default_type(), 'message/rfc822') | ||||
|         eq(container1.get_type(), None) | ||||
|         eq(container1.get_content_type(), 'message/rfc822') | ||||
|         container2 = msg.get_payload(1) | ||||
|         eq(container2.get_default_type(), 'message/rfc822') | ||||
|         eq(container2.get_type(), None) | ||||
|         eq(container2.get_content_type(), 'message/rfc822') | ||||
|         container1a = container1.get_payload(0) | ||||
|         eq(container1a.get_default_type(), 'text/plain') | ||||
|         eq(container1a.get_type(), 'text/plain') | ||||
|         eq(container1a.get_content_type(), 'text/plain') | ||||
|         container2a = container2.get_payload(0) | ||||
|         eq(container2a.get_default_type(), 'text/plain') | ||||
|         eq(container2a.get_type(), 'text/plain') | ||||
|         eq(container2a.get_content_type(), 'text/plain') | ||||
| 
 | ||||
|     def test_default_type_with_explicit_container_type(self): | ||||
|         eq = self.assertEqual | ||||
|  | @ -1726,16 +1736,16 @@ def test_default_type_with_explicit_container_type(self): | |||
|             fp.close() | ||||
|         container1 = msg.get_payload(0) | ||||
|         eq(container1.get_default_type(), 'message/rfc822') | ||||
|         eq(container1.get_type(), 'message/rfc822') | ||||
|         eq(container1.get_content_type(), 'message/rfc822') | ||||
|         container2 = msg.get_payload(1) | ||||
|         eq(container2.get_default_type(), 'message/rfc822') | ||||
|         eq(container2.get_type(), 'message/rfc822') | ||||
|         eq(container2.get_content_type(), 'message/rfc822') | ||||
|         container1a = container1.get_payload(0) | ||||
|         eq(container1a.get_default_type(), 'text/plain') | ||||
|         eq(container1a.get_type(), 'text/plain') | ||||
|         eq(container1a.get_content_type(), 'text/plain') | ||||
|         container2a = container2.get_payload(0) | ||||
|         eq(container2a.get_default_type(), 'text/plain') | ||||
|         eq(container2a.get_type(), 'text/plain') | ||||
|         eq(container2a.get_content_type(), 'text/plain') | ||||
| 
 | ||||
|     def test_default_type_non_parsed(self): | ||||
|         eq = self.assertEqual | ||||
|  | @ -1750,9 +1760,9 @@ def test_default_type_non_parsed(self): | |||
|         subpart2 = MIMEMessage(subpart2a) | ||||
|         container.attach(subpart1) | ||||
|         container.attach(subpart2) | ||||
|         eq(subpart1.get_type(), 'message/rfc822') | ||||
|         eq(subpart1.get_content_type(), 'message/rfc822') | ||||
|         eq(subpart1.get_default_type(), 'message/rfc822') | ||||
|         eq(subpart2.get_type(), 'message/rfc822') | ||||
|         eq(subpart2.get_content_type(), 'message/rfc822') | ||||
|         eq(subpart2.get_default_type(), 'message/rfc822') | ||||
|         neq(container.as_string(0), '''\ | ||||
| Content-Type: multipart/digest; boundary="BOUNDARY" | ||||
|  | @ -1784,9 +1794,9 @@ def test_default_type_non_parsed(self): | |||
|         del subpart1['mime-version'] | ||||
|         del subpart2['content-type'] | ||||
|         del subpart2['mime-version'] | ||||
|         eq(subpart1.get_type(), None) | ||||
|         eq(subpart1.get_content_type(), 'message/rfc822') | ||||
|         eq(subpart1.get_default_type(), 'message/rfc822') | ||||
|         eq(subpart2.get_type(), None) | ||||
|         eq(subpart2.get_content_type(), 'message/rfc822') | ||||
|         eq(subpart2.get_default_type(), 'message/rfc822') | ||||
|         neq(container.as_string(0), '''\ | ||||
| Content-Type: multipart/digest; boundary="BOUNDARY" | ||||
|  | @ -1847,7 +1857,7 @@ def _idempotent(self, msg, text): | |||
|     def test_parse_text_message(self): | ||||
|         eq = self.assertEquals | ||||
|         msg, text = self._msgobj('msg_01.txt') | ||||
|         eq(msg.get_type(), 'text/plain') | ||||
|         eq(msg.get_content_type(), 'text/plain') | ||||
|         eq(msg.get_content_maintype(), 'text') | ||||
|         eq(msg.get_content_subtype(), 'plain') | ||||
|         eq(msg.get_params()[1], ('charset', 'us-ascii')) | ||||
|  | @ -1859,7 +1869,7 @@ def test_parse_text_message(self): | |||
|     def test_parse_untyped_message(self): | ||||
|         eq = self.assertEquals | ||||
|         msg, text = self._msgobj('msg_03.txt') | ||||
|         eq(msg.get_type(), None) | ||||
|         eq(msg.get_content_type(), 'text/plain') | ||||
|         eq(msg.get_params(), None) | ||||
|         eq(msg.get_param('charset'), None) | ||||
|         self._idempotent(msg, text) | ||||
|  | @ -1933,7 +1943,7 @@ def test_content_type(self): | |||
|         unless = self.failUnless | ||||
|         # Get a message object and reset the seek pointer for other tests | ||||
|         msg, text = self._msgobj('msg_05.txt') | ||||
|         eq(msg.get_type(), 'multipart/report') | ||||
|         eq(msg.get_content_type(), 'multipart/report') | ||||
|         # Test the Content-Type: parameters | ||||
|         params = {} | ||||
|         for pk, pv in msg.get_params(): | ||||
|  | @ -1945,13 +1955,13 @@ def test_content_type(self): | |||
|         eq(len(msg.get_payload()), 3) | ||||
|         # Make sure the subparts are what we expect | ||||
|         msg1 = msg.get_payload(0) | ||||
|         eq(msg1.get_type(), 'text/plain') | ||||
|         eq(msg1.get_content_type(), 'text/plain') | ||||
|         eq(msg1.get_payload(), 'Yadda yadda yadda\n') | ||||
|         msg2 = msg.get_payload(1) | ||||
|         eq(msg2.get_type(), None) | ||||
|         eq(msg2.get_content_type(), 'text/plain') | ||||
|         eq(msg2.get_payload(), 'Yadda yadda yadda\n') | ||||
|         msg3 = msg.get_payload(2) | ||||
|         eq(msg3.get_type(), 'message/rfc822') | ||||
|         eq(msg3.get_content_type(), 'message/rfc822') | ||||
|         self.failUnless(isinstance(msg3, Message)) | ||||
|         payload = msg3.get_payload() | ||||
|         unless(isinstance(payload, list)) | ||||
|  | @ -1965,7 +1975,7 @@ def test_parser(self): | |||
|         unless = self.failUnless | ||||
|         msg, text = self._msgobj('msg_06.txt') | ||||
|         # Check some of the outer headers | ||||
|         eq(msg.get_type(), 'message/rfc822') | ||||
|         eq(msg.get_content_type(), 'message/rfc822') | ||||
|         # Make sure the payload is a list of exactly one sub-Message, and that | ||||
|         # that submessage has a type of text/plain | ||||
|         payload = msg.get_payload() | ||||
|  | @ -1973,7 +1983,7 @@ def test_parser(self): | |||
|         eq(len(payload), 1) | ||||
|         msg1 = payload[0] | ||||
|         self.failUnless(isinstance(msg1, Message)) | ||||
|         eq(msg1.get_type(), 'text/plain') | ||||
|         eq(msg1.get_content_type(), 'text/plain') | ||||
|         self.failUnless(isinstance(msg1.get_payload(), str)) | ||||
|         eq(msg1.get_payload(), '\n') | ||||
| 
 | ||||
|  | @ -2058,13 +2068,19 @@ def test__all__(self): | |||
|         module = __import__('email') | ||||
|         all = module.__all__ | ||||
|         all.sort() | ||||
|         self.assertEqual(all, ['Charset', 'Encoders', 'Errors', 'Generator', | ||||
|         self.assertEqual(all, [ | ||||
|             # Old names | ||||
|             'Charset', 'Encoders', 'Errors', 'Generator', | ||||
|             'Header', 'Iterators', 'MIMEAudio', 'MIMEBase', | ||||
|             'MIMEImage', 'MIMEMessage', 'MIMEMultipart', | ||||
|             'MIMENonMultipart', 'MIMEText', 'Message', | ||||
|             'Parser', 'Utils', 'base64MIME', | ||||
|                                'message_from_file', 'message_from_string', | ||||
|                                'quopriMIME']) | ||||
|             # new names | ||||
|             'base64mime', 'charset', 'encoders', 'errors', 'generator', | ||||
|             'header', 'iterators', 'message', 'message_from_file', | ||||
|             'message_from_string', 'mime', 'parser', | ||||
|             'quopriMIME', 'quoprimime', 'utils', | ||||
|             ]) | ||||
| 
 | ||||
|     def test_formatdate(self): | ||||
|         now = time.time() | ||||
|  | @ -2356,7 +2372,7 @@ def test_header_parser(self): | |||
|             fp.close() | ||||
|         eq(msg['from'], 'ppp-request@zzz.org') | ||||
|         eq(msg['to'], 'ppp@zzz.org') | ||||
|         eq(msg.get_type(), 'multipart/mixed') | ||||
|         eq(msg.get_content_type(), 'multipart/mixed') | ||||
|         self.failIf(msg.is_multipart()) | ||||
|         self.failUnless(isinstance(msg.get_payload(), str)) | ||||
| 
 | ||||
|  | @ -2405,10 +2421,10 @@ def test_crlf_separation(self): | |||
|             fp.close() | ||||
|         eq(len(msg.get_payload()), 2) | ||||
|         part1 = msg.get_payload(0) | ||||
|         eq(part1.get_type(), 'text/plain') | ||||
|         eq(part1.get_content_type(), 'text/plain') | ||||
|         eq(part1.get_payload(), 'Simple email with attachment.\r\n\r\n') | ||||
|         part2 = msg.get_payload(1) | ||||
|         eq(part2.get_type(), 'application/riscos') | ||||
|         eq(part2.get_content_type(), 'application/riscos') | ||||
| 
 | ||||
|     def test_multipart_digest_with_extra_mime_headers(self): | ||||
|         eq = self.assertEqual | ||||
|  | @ -2427,21 +2443,21 @@ def test_multipart_digest_with_extra_mime_headers(self): | |||
|         eq(msg.is_multipart(), 1) | ||||
|         eq(len(msg.get_payload()), 2) | ||||
|         part1 = msg.get_payload(0) | ||||
|         eq(part1.get_type(), 'message/rfc822') | ||||
|         eq(part1.get_content_type(), 'message/rfc822') | ||||
|         eq(part1.is_multipart(), 1) | ||||
|         eq(len(part1.get_payload()), 1) | ||||
|         part1a = part1.get_payload(0) | ||||
|         eq(part1a.is_multipart(), 0) | ||||
|         eq(part1a.get_type(), 'text/plain') | ||||
|         eq(part1a.get_content_type(), 'text/plain') | ||||
|         neq(part1a.get_payload(), 'message 1\n') | ||||
|         # next message/rfc822 | ||||
|         part2 = msg.get_payload(1) | ||||
|         eq(part2.get_type(), 'message/rfc822') | ||||
|         eq(part2.get_content_type(), 'message/rfc822') | ||||
|         eq(part2.is_multipart(), 1) | ||||
|         eq(len(part2.get_payload()), 1) | ||||
|         part2a = part2.get_payload(0) | ||||
|         eq(part2a.is_multipart(), 0) | ||||
|         eq(part2a.get_type(), 'text/plain') | ||||
|         eq(part2a.get_content_type(), 'text/plain') | ||||
|         neq(part2a.get_payload(), 'message 2\n') | ||||
| 
 | ||||
|     def test_three_lines(self): | ||||
|  | @ -2723,6 +2739,11 @@ def test_body_encode(self): | |||
|         c = Charset('fake') | ||||
|         eq('hello w\xf6rld', c.body_encode('hello w\xf6rld')) | ||||
| 
 | ||||
|     def test_unicode_charset_name(self): | ||||
|         charset = Charset(u'us-ascii') | ||||
|         self.assertEqual(str(charset), 'us-ascii') | ||||
|         self.assertRaises(Errors.CharsetError, Charset, 'asc\xffii') | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| # Test multilingual MIME headers. | ||||
|  |  | |||
|  | @ -10,6 +10,13 @@ | |||
| from email.Header import Header, decode_header | ||||
| from email.Message import Message | ||||
| 
 | ||||
| # We're compatible with Python 2.3, but it doesn't have the built-in Asian | ||||
| # codecs, so we have to skip all these tests. | ||||
| try: | ||||
|     unicode('foo', 'euc-jp') | ||||
| except LookupError: | ||||
|     raise TestSkipped | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| class TestEmailAsianCodecs(TestEmailBase): | ||||
|  |  | |||
							
								
								
									
										77
									
								
								Lib/email/test/test_email_codecs_renamed.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								Lib/email/test/test_email_codecs_renamed.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,77 @@ | |||
| # Copyright (C) 2002-2006 Python Software Foundation | ||||
| # Contact: email-sig@python.org | ||||
| # email package unit tests for (optional) Asian codecs | ||||
| 
 | ||||
| import unittest | ||||
| from test.test_support import TestSkipped, run_unittest | ||||
| 
 | ||||
| from email.test.test_email import TestEmailBase | ||||
| from email.charset import Charset | ||||
| from email.header import Header, decode_header | ||||
| from email.message import Message | ||||
| 
 | ||||
| # We're compatible with Python 2.3, but it doesn't have the built-in Asian | ||||
| # codecs, so we have to skip all these tests. | ||||
| try: | ||||
|     unicode('foo', 'euc-jp') | ||||
| except LookupError: | ||||
|     raise TestSkipped | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| class TestEmailAsianCodecs(TestEmailBase): | ||||
|     def test_japanese_codecs(self): | ||||
|         eq = self.ndiffAssertEqual | ||||
|         j = Charset("euc-jp") | ||||
|         g = Charset("iso-8859-1") | ||||
|         h = Header("Hello World!") | ||||
|         jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa' | ||||
|         ghello = 'Gr\xfc\xdf Gott!' | ||||
|         h.append(jhello, j) | ||||
|         h.append(ghello, g) | ||||
|         # BAW: This used to -- and maybe should -- fold the two iso-8859-1 | ||||
|         # chunks into a single encoded word.  However it doesn't violate the | ||||
|         # standard to have them as two encoded chunks and maybe it's | ||||
|         # reasonable <wink> for each .append() call to result in a separate | ||||
|         # encoded word. | ||||
|         eq(h.encode(), """\ | ||||
| Hello World! =?iso-2022-jp?b?GyRCJU8lbSE8JW8hPCVrJUkhKhsoQg==?= | ||||
|  =?iso-8859-1?q?Gr=FC=DF?= =?iso-8859-1?q?_Gott!?=""") | ||||
|         eq(decode_header(h.encode()), | ||||
|            [('Hello World!', None), | ||||
|             ('\x1b$B%O%m!<%o!<%k%I!*\x1b(B', 'iso-2022-jp'), | ||||
|             ('Gr\xfc\xdf Gott!', 'iso-8859-1')]) | ||||
|         long = 'test-ja \xa4\xd8\xc5\xea\xb9\xc6\xa4\xb5\xa4\xec\xa4\xbf\xa5\xe1\xa1\xbc\xa5\xeb\xa4\xcf\xbb\xca\xb2\xf1\xbc\xd4\xa4\xce\xbe\xb5\xc7\xa7\xa4\xf2\xc2\xd4\xa4\xc3\xa4\xc6\xa4\xa4\xa4\xde\xa4\xb9' | ||||
|         h = Header(long, j, header_name="Subject") | ||||
|         # test a very long header | ||||
|         enc = h.encode() | ||||
|         # TK: splitting point may differ by codec design and/or Header encoding | ||||
|         eq(enc , """\ | ||||
| =?iso-2022-jp?b?dGVzdC1qYSAbJEIkWEVqOUYkNSRsJD8lYSE8JWskTztKGyhC?= | ||||
|  =?iso-2022-jp?b?GyRCMnE8VCROPjVHJyRyQlQkQyRGJCQkXiQ5GyhC?=""") | ||||
|         # TK: full decode comparison | ||||
|         eq(h.__unicode__().encode('euc-jp'), long) | ||||
| 
 | ||||
|     def test_payload_encoding(self): | ||||
|         jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa' | ||||
|         jcode  = 'euc-jp' | ||||
|         msg = Message() | ||||
|         msg.set_payload(jhello, jcode) | ||||
|         ustr = unicode(msg.get_payload(), msg.get_content_charset()) | ||||
|         self.assertEqual(jhello, ustr.encode(jcode)) | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| def suite(): | ||||
|     suite = unittest.TestSuite() | ||||
|     suite.addTest(unittest.makeSuite(TestEmailAsianCodecs)) | ||||
|     return suite | ||||
| 
 | ||||
| 
 | ||||
| def test_main(): | ||||
|     run_unittest(TestEmailAsianCodecs) | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     unittest.main(defaultTest='suite') | ||||
							
								
								
									
										3078
									
								
								Lib/email/test/test_email_renamed.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3078
									
								
								Lib/email/test/test_email_renamed.py
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,9 +1,24 @@ | |||
| # Copyright (C) 2001-2004 Python Software Foundation | ||||
| # Copyright (C) 2001-2006 Python Software Foundation | ||||
| # Author: Barry Warsaw | ||||
| # Contact: email-sig@python.org | ||||
| 
 | ||||
| """Miscellaneous utilities.""" | ||||
| 
 | ||||
| __all__ = [ | ||||
|     'collapse_rfc2231_value', | ||||
|     'decode_params', | ||||
|     'decode_rfc2231', | ||||
|     'encode_rfc2231', | ||||
|     'formataddr', | ||||
|     'formatdate', | ||||
|     'getaddresses', | ||||
|     'make_msgid', | ||||
|     'parseaddr', | ||||
|     'parsedate', | ||||
|     'parsedate_tz', | ||||
|     'unquote', | ||||
|     ] | ||||
| 
 | ||||
| import os | ||||
| import re | ||||
| import time | ||||
|  | @ -24,7 +39,7 @@ | |||
| from quopri import decodestring as _qdecode | ||||
| 
 | ||||
| # Intrapackage imports | ||||
| from email.Encoders import _bencode, _qencode | ||||
| from email.encoders import _bencode, _qencode | ||||
| 
 | ||||
| COMMASPACE = ', ' | ||||
| EMPTYSTRING = '' | ||||
|  | @ -170,7 +170,7 @@ def test_others(self): | |||
|         cm('pydoc') | ||||
| 
 | ||||
|         # Tests for modules inside packages | ||||
|         cm('email.Parser') | ||||
|         cm('email.parser') | ||||
|         cm('test.test_pyclbr') | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Barry Warsaw
						Barry Warsaw