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 | #!/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 os | ||||||
| import getopt | import sys | ||||||
| import smtplib | import smtplib | ||||||
| # For guessing MIME type based on file name extension | # For guessing MIME type based on file name extension | ||||||
| import mimetypes | import mimetypes | ||||||
| 
 | 
 | ||||||
| from email import Encoders | from optparse import OptionParser | ||||||
| from email.Message import Message | 
 | ||||||
| from email.MIMEAudio import MIMEAudio | from email import encoders | ||||||
| from email.MIMEBase import MIMEBase | from email.message import Message | ||||||
| from email.MIMEMultipart import MIMEMultipart | from email.mime.audio import MIMEAudio | ||||||
| from email.MIMEImage import MIMEImage | from email.mime.base import MIMEBase | ||||||
| from email.MIMEText import MIMEText | from email.mime.image import MIMEImage | ||||||
|  | from email.mime.multipart import MIMEMultipart | ||||||
|  | from email.mime.text import MIMEText | ||||||
| 
 | 
 | ||||||
| COMMASPACE = ', ' | COMMASPACE = ', ' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def usage(code, msg=''): |  | ||||||
|     print >> sys.stderr, __doc__ |  | ||||||
|     if msg: |  | ||||||
|         print >> sys.stderr, msg |  | ||||||
|     sys.exit(code) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def main(): | def main(): | ||||||
|     try: |     parser = OptionParser(usage="""\ | ||||||
|         opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) | Send the contents of a directory as a MIME message. | ||||||
|     except getopt.error, msg: |  | ||||||
|         usage(1, msg) |  | ||||||
| 
 | 
 | ||||||
|     dir = os.curdir | Usage: %prog [options] | ||||||
|     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:] |  | ||||||
| 
 | 
 | ||||||
|  | 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 |     # Create the enclosing (outer) message | ||||||
|     outer = MIMEMultipart() |     outer = MIMEMultipart() | ||||||
|     outer['Subject'] = 'Contents of directory %s' % os.path.abspath(dir) |     outer['Subject'] = 'Contents of directory %s' % os.path.abspath(directory) | ||||||
|     outer['To'] = COMMASPACE.join(recips) |     outer['To'] = COMMASPACE.join(opts.recipients) | ||||||
|     outer['From'] = sender |     outer['From'] = opts.sender | ||||||
|     outer.preamble = 'You will not see this in a MIME-aware mail reader.\n' |     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): |     for filename in os.listdir(directory): | ||||||
|         path = os.path.join(dir, filename) |         path = os.path.join(directory, filename) | ||||||
|         if not os.path.isfile(path): |         if not os.path.isfile(path): | ||||||
|             continue |             continue | ||||||
|         # Guess the content type based on the file's extension.  Encoding |         # Guess the content type based on the file's extension.  Encoding | ||||||
|  | @ -108,16 +94,21 @@ def main(): | ||||||
|             msg.set_payload(fp.read()) |             msg.set_payload(fp.read()) | ||||||
|             fp.close() |             fp.close() | ||||||
|             # Encode the payload using Base64 |             # Encode the payload using Base64 | ||||||
|             Encoders.encode_base64(msg) |             encoders.encode_base64(msg) | ||||||
|         # Set the filename parameter |         # Set the filename parameter | ||||||
|         msg.add_header('Content-Disposition', 'attachment', filename=filename) |         msg.add_header('Content-Disposition', 'attachment', filename=filename) | ||||||
|         outer.attach(msg) |         outer.attach(msg) | ||||||
| 
 |     # Now send or store the message | ||||||
|     # Now send the message |     composed = outer.as_string() | ||||||
|     s = smtplib.SMTP() |     if opts.output: | ||||||
|     s.connect() |         fp = open(opts.output, 'w') | ||||||
|     s.sendmail(sender, recips, outer.as_string()) |         fp.write(composed) | ||||||
|     s.close() |         fp.close() | ||||||
|  |     else: | ||||||
|  |         s = smtplib.SMTP() | ||||||
|  |         s.connect() | ||||||
|  |         s.sendmail(opts.sender, opts.recipients, composed) | ||||||
|  |         s.close() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|  |  | ||||||
|  | @ -2,8 +2,8 @@ | ||||||
| import smtplib | import smtplib | ||||||
| 
 | 
 | ||||||
| # Here are the email package modules we'll need | # Here are the email package modules we'll need | ||||||
| from email.MIMEImage import MIMEImage | from email.mime.image import MIMEImage | ||||||
| from email.MIMEMultipart import MIMEMultipart | from email.mime.multipart import MIMEMultipart | ||||||
| 
 | 
 | ||||||
| COMMASPACE = ', ' | COMMASPACE = ', ' | ||||||
| 
 | 
 | ||||||
|  | @ -15,8 +15,6 @@ | ||||||
| msg['From'] = me | msg['From'] = me | ||||||
| msg['To'] = COMMASPACE.join(family) | msg['To'] = COMMASPACE.join(family) | ||||||
| msg.preamble = 'Our family reunion' | 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 | # Assume we know that the image files are all in PNG format | ||||||
| for file in pngfiles: | for file in pngfiles: | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| import smtplib | import smtplib | ||||||
| 
 | 
 | ||||||
| # Import the email modules we'll need | # 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 | # Open a plain text file for reading.  For this example, assume that | ||||||
| # the text file contains only ASCII characters. | # the text file contains only ASCII characters. | ||||||
|  |  | ||||||
|  | @ -1,59 +1,44 @@ | ||||||
| #!/usr/bin/env python | #!/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 os | ||||||
| import getopt | import sys | ||||||
|  | import email | ||||||
| import errno | import errno | ||||||
| import mimetypes | import mimetypes | ||||||
| import email |  | ||||||
| 
 | 
 | ||||||
| 
 | from optparse import OptionParser | ||||||
| def usage(code, msg=''): |  | ||||||
|     print >> sys.stderr, __doc__ |  | ||||||
|     if msg: |  | ||||||
|         print >> sys.stderr, msg |  | ||||||
|     sys.exit(code) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def main(): | def main(): | ||||||
|     try: |     parser = OptionParser(usage="""\ | ||||||
|         opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) | Unpack a MIME message into a directory of files. | ||||||
|     except getopt.error, msg: |  | ||||||
|         usage(1, msg) |  | ||||||
| 
 | 
 | ||||||
|     dir = os.curdir | Usage: %prog [options] msgfile | ||||||
|     for opt, arg in opts: | """) | ||||||
|         if opt in ('-h', '--help'): |     parser.add_option('-d', '--directory', | ||||||
|             usage(0) |                       type='string', action='store', | ||||||
|         elif opt in ('-d', '--directory'): |                       help="""Unpack the MIME message into the named | ||||||
|             dir = arg |                       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: |     try: | ||||||
|         msgfile = args[0] |         msgfile = args[0] | ||||||
|     except IndexError: |     except IndexError: | ||||||
|         usage(1) |         parser.print_help() | ||||||
|  |         sys.exit(1) | ||||||
| 
 | 
 | ||||||
|     try: |     try: | ||||||
|         os.mkdir(dir) |         os.mkdir(opts.directory) | ||||||
|     except OSError, e: |     except OSError, e: | ||||||
|         # Ignore directory exists error |         # Ignore directory exists error | ||||||
|         if e.errno <> errno.EEXIST: raise |         if e.errno <> errno.EEXIST: | ||||||
|  |             raise | ||||||
| 
 | 
 | ||||||
|     fp = open(msgfile) |     fp = open(msgfile) | ||||||
|     msg = email.message_from_file(fp) |     msg = email.message_from_file(fp) | ||||||
|  | @ -74,8 +59,8 @@ def main(): | ||||||
|                 ext = '.bin' |                 ext = '.bin' | ||||||
|             filename = 'part-%03d%s' % (counter, ext) |             filename = 'part-%03d%s' % (counter, ext) | ||||||
|         counter += 1 |         counter += 1 | ||||||
|         fp = open(os.path.join(dir, filename), 'wb') |         fp = open(os.path.join(opts.directory, filename), 'wb') | ||||||
|         fp.write(part.get_payload(decode=1)) |         fp.write(part.get_payload(decode=True)) | ||||||
|         fp.close() |         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) | % Author: barry@python.org (Barry Warsaw) | ||||||
| 
 | 
 | ||||||
| \section{\module{email} --- | \section{\module{email} --- | ||||||
|  | @ -18,10 +18,10 @@ subsumes most of the functionality in several older standard modules | ||||||
| such as \refmodule{rfc822}, \refmodule{mimetools}, | such as \refmodule{rfc822}, \refmodule{mimetools}, | ||||||
| \refmodule{multifile}, and other non-standard packages such as | \refmodule{multifile}, and other non-standard packages such as | ||||||
| \module{mimecntl}.  It is specifically \emph{not} designed to do any | \module{mimecntl}.  It is specifically \emph{not} designed to do any | ||||||
| sending of email messages to SMTP (\rfc{2821}) servers; that is the | sending of email messages to SMTP (\rfc{2821}), NNTP, or other servers; those | ||||||
| function of the \refmodule{smtplib} module.  The \module{email} | are functions of modules such as \refmodule{smtplib} and \refmodule{nntplib}. | ||||||
| package attempts to be as RFC-compliant as possible, supporting in | The \module{email} package attempts to be as RFC-compliant as possible, | ||||||
| addition to \rfc{2822}, such MIME-related RFCs as | supporting in addition to \rfc{2822}, such MIME-related RFCs as | ||||||
| \rfc{2045}, \rfc{2046}, \rfc{2047}, and \rfc{2231}. | \rfc{2045}, \rfc{2046}, \rfc{2047}, and \rfc{2231}. | ||||||
| 
 | 
 | ||||||
| The primary distinguishing feature of the \module{email} package is | 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 | 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 | text from a file or other source, the text is parsed to produce the | ||||||
| object structure of the email message, this structure is manipulated, | 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 | It is perfectly feasible to create the object structure out of whole | ||||||
| cloth --- i.e. completely from scratch.  From there, a similar | 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} | \begin{seealso} | ||||||
|     \seemodule{smtplib}{SMTP protocol client} |     \seemodule{smtplib}{SMTP protocol client} | ||||||
|  |     \seemodule{nntplib}{NNTP protocol client} | ||||||
| \end{seealso} | \end{seealso} | ||||||
| 
 | 
 | ||||||
| \subsection{Representing an email message} | \subsection{Representing an email message} | ||||||
|  | @ -88,22 +89,51 @@ package, a section on differences and porting is provided. | ||||||
| \subsection{Iterators} | \subsection{Iterators} | ||||||
| \input{emailiter} | \input{emailiter} | ||||||
| 
 | 
 | ||||||
| \subsection{Package History} | \subsection{Package History\label{email-pkg-history}} | ||||||
| 
 | 
 | ||||||
| Version 1 of the \module{email} package was bundled with Python | This table describes the release history of the email package, corresponding | ||||||
| releases up to Python 2.2.1.  Version 2 was developed for the Python | to the version of Python that the package was released with.  For purposes of | ||||||
| 2.3 release, and backported to Python 2.2.2.  It was also available as | this document, when you see a note about change or added versions, these refer | ||||||
| a separate distutils-based package, and is compatible back to Python 2.1. | 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 | \begin{tableiii}{l|l|l}{constant}{email version}{distributed with}{compatible with} | ||||||
| distutils-based package.  It is compatible back to Python 2.3. | \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} | \begin{itemize} | ||||||
| \item The \class{FeedParser} class was introduced, and the \class{Parser} | \item The \class{FeedParser} class was introduced, and the \class{Parser} | ||||||
|       class was implemented in terms of the \class{FeedParser}.  All parsing |       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 |       raise an exception.  Problems found while parsing messages are stored in | ||||||
|       the message's \var{defect} attribute. |       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{Generator.__call__()}, \method{Message.get_type()}, | ||||||
|       \method{Message.get_main_type()}, \method{Message.get_subtype()}, and |       \method{Message.get_main_type()}, \method{Message.get_subtype()}, and | ||||||
|       the \var{strict} argument to the \class{Parser} class.  These are |       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. | \item Support for Pythons earlier than 2.3 has been removed. | ||||||
| \end{itemize} | \end{itemize} | ||||||
|  | @ -278,12 +308,12 @@ The \class{Message} class has the following differences: | ||||||
| \item The method \method{getpayloadastext()} was removed.  Similar | \item The method \method{getpayloadastext()} was removed.  Similar | ||||||
|       functionality |       functionality | ||||||
|       is supported by the \class{DecodedGenerator} class in the |       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 | \item The method \method{getbodyastext()} was removed.  You can get | ||||||
|       similar functionality by creating an iterator with |       similar functionality by creating an iterator with | ||||||
|       \function{typed_subpart_iterator()} in the |       \function{typed_subpart_iterator()} in the | ||||||
|       \refmodule{email.Iterators} module. |       \refmodule{email.iterators} module. | ||||||
| \end{itemize} | \end{itemize} | ||||||
| 
 | 
 | ||||||
| The \class{Parser} class has no differences in its public interface. | 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}.}. | in \rfc{1894}.}. | ||||||
| 
 | 
 | ||||||
| The \class{Generator} class has no differences in its public | 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 | module though, called \class{DecodedGenerator} which provides most of | ||||||
| the functionality previously available in the | the functionality previously available in the | ||||||
| \method{Message.getpayloadastext()} method. | \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{mimelib} provided some utility functions in its | ||||||
| \module{address} and \module{date} modules.  All of these functions | \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 | The \code{MsgReader} class/module has been removed.  Its functionality | ||||||
| is most closely supported in the \function{body_line_iterator()} | 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} | \subsection{Examples} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| \declaremodule{standard}{email.Charset} | \declaremodule{standard}{email.charset} | ||||||
| \modulesynopsis{Character Sets} | \modulesynopsis{Character Sets} | ||||||
| 
 | 
 | ||||||
| This module provides a class \class{Charset} for representing | 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 | manipulating this registry.  Instances of \class{Charset} are used in | ||||||
| several other modules within the \module{email} package. | several other modules within the \module{email} package. | ||||||
| 
 | 
 | ||||||
|  | Import this class from the \module{email.charset} module. | ||||||
|  | 
 | ||||||
| \versionadded{2.2.2} | \versionadded{2.2.2} | ||||||
| 
 | 
 | ||||||
| \begin{classdesc}{Charset}{\optional{input_charset}} | \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 | for multibyte character sets, which have line length issues (multibyte | ||||||
| characters must be split on a character, not a byte boundary); use the | characters must be split on a character, not a byte boundary); use the | ||||||
| higher-level \class{Header} class to deal with these issues (see | 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 type of encoding (base64 or quoted-printable) will be based on | ||||||
| the \var{header_encoding} attribute. | 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. | This method allows you to compare two \class{Charset} instances for inequality. | ||||||
| \end{methoddesc} | \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, | functions for adding new entries to the global character set, alias, | ||||||
| and codec registries: | and codec registries: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| \declaremodule{standard}{email.Encoders} | \declaremodule{standard}{email.encoders} | ||||||
| \modulesynopsis{Encoders for email message payloads.} | \modulesynopsis{Encoders for email message payloads.} | ||||||
| 
 | 
 | ||||||
| When creating \class{Message} objects from scratch, you often need to | 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. | type messages containing binary data. | ||||||
| 
 | 
 | ||||||
| The \module{email} package provides some convenient encodings in its | 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 | \class{MIMEAudio} and \class{MIMEImage} class constructors to provide default | ||||||
| encodings.  All encoder functions take exactly one argument, the message | encodings.  All encoder functions take exactly one argument, the message | ||||||
| object to encode.  They usually extract the payload, encode it, and reset the | 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.} | \modulesynopsis{The exception classes used by the email package.} | ||||||
| 
 | 
 | ||||||
| The following exception classes are defined in the | The following exception classes are defined in the | ||||||
| \module{email.Errors} module: | \module{email.errors} module: | ||||||
| 
 | 
 | ||||||
| \begin{excclassdesc}{MessageError}{} | \begin{excclassdesc}{MessageError}{} | ||||||
| This is the base class for all exceptions that the \module{email} | 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 | \mimetype{multipart/alternative} had a malformed header, that nested message | ||||||
| object would have a defect, but the containing messages would not. | 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! | this class is \emph{not} an exception! | ||||||
| 
 | 
 | ||||||
| \versionadded[All the defect classes were added]{2.4} | \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.} | \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 | 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 | console.  Taking a message object structure and producing a flat text | ||||||
| document is the job of the \class{Generator} class. | 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 | to the functionality of the bundled generator; you could write one | ||||||
| from scratch yourself.  However the bundled generator knows how to | from scratch yourself.  However the bundled generator knows how to | ||||||
| generate most email in a standards-compliant way, should handle MIME | 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 | \class{Parser} class, and back to flat text, is idempotent (the input | ||||||
| is identical to the output). | 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{, | \begin{classdesc}{Generator}{outfp\optional{, mangle_from_\optional{, | ||||||
|     maxheaderlen}}} |     maxheaderlen}}} | ||||||
|  | @ -40,7 +41,7 @@ mailbox format files. | ||||||
| Optional \var{maxheaderlen} specifies the longest length for a | Optional \var{maxheaderlen} specifies the longest length for a | ||||||
| non-continued header.  When a header line is longer than | non-continued header.  When a header line is longer than | ||||||
| \var{maxheaderlen} (in characters, with tabs expanded to 8 spaces), | \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 | class.  Set to zero to disable header wrapping.  The default is 78, as | ||||||
| recommended (but not required) by \rfc{2822}. | recommended (but not required) by \rfc{2822}. | ||||||
| \end{classdesc} | \end{classdesc} | ||||||
|  | @ -81,9 +82,9 @@ be used in extended print statements. | ||||||
| As a convenience, see the methods \method{Message.as_string()} and | As a convenience, see the methods \method{Message.as_string()} and | ||||||
| \code{str(aMessage)}, a.k.a. \method{Message.__str__()}, which | \code{str(aMessage)}, a.k.a. \method{Message.__str__()}, which | ||||||
| simplify the generation of a formatted string representation of a | 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} | called \class{DecodedGenerator} which is like the \class{Generator} | ||||||
| base class, except that non-\mimetype{text} parts are substituted with | base class, except that non-\mimetype{text} parts are substituted with | ||||||
| a format string representing the part. | a format string representing the part. | ||||||
|  | @ -128,13 +129,5 @@ The default value for \var{fmt} is \code{None}, meaning | ||||||
| \versionadded{2.2.2} | \versionadded{2.2.2} | ||||||
| \end{classdesc} | \end{classdesc} | ||||||
| 
 | 
 | ||||||
| \subsubsection{Deprecated methods} | \versionchanged[The previously deprecated method \method{__call__()} was | ||||||
| 
 | removed]{2.5} | ||||||
| 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} |  | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| \declaremodule{standard}{email.Header} | \declaremodule{standard}{email.header} | ||||||
| \modulesynopsis{Representing non-ASCII headers} | \modulesynopsis{Representing non-ASCII headers} | ||||||
| 
 | 
 | ||||||
| \rfc{2822} is the base standard that describes the format of email | \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. | containing non-\ASCII{} characters into \rfc{2822}-compliant format. | ||||||
| These RFCs include \rfc{2045}, \rfc{2046}, \rfc{2047}, and \rfc{2231}. | These RFCs include \rfc{2045}, \rfc{2046}, \rfc{2047}, and \rfc{2231}. | ||||||
| The \module{email} package supports these standards in its | 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, | If you want to include non-\ASCII{} characters in your email headers, | ||||||
| say in the \mailheader{Subject} or \mailheader{To} fields, you should | say in the \mailheader{Subject} or \mailheader{To} fields, you should | ||||||
| use the \class{Header} class and assign the field in the | use the \class{Header} class and assign the field in the | ||||||
| \class{Message} object to an instance of \class{Header} instead of | \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} | \begin{verbatim} | ||||||
| >>> from email.Message import Message | >>> from email.message import Message | ||||||
| >>> from email.Header import Header | >>> from email.header import Header | ||||||
| >>> msg = Message() | >>> msg = Message() | ||||||
| >>> h = Header('p\xf6stal', 'iso-8859-1') | >>> h = Header('p\xf6stal', 'iso-8859-1') | ||||||
| >>> msg['Subject'] = h | >>> 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. | Append the string \var{s} to the MIME header. | ||||||
| 
 | 
 | ||||||
| Optional \var{charset}, if given, should be a \class{Charset} instance | 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 | will be converted to a \class{Charset} instance.  A value of | ||||||
| \code{None} (the default) means that the \var{charset} given in the | \code{None} (the default) means that the \var{charset} given in the | ||||||
| constructor is used. | 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. | This method allows you to compare two \class{Header} instances for inequality. | ||||||
| \end{methoddesc} | \end{methoddesc} | ||||||
| 
 | 
 | ||||||
| The \module{email.Header} module also provides the following | The \module{email.header} module also provides the following | ||||||
| convenient functions. | convenient functions. | ||||||
| 
 | 
 | ||||||
| \begin{funcdesc}{decode_header}{header} | \begin{funcdesc}{decode_header}{header} | ||||||
|  | @ -155,7 +156,7 @@ encoded string. | ||||||
| Here's an example: | Here's an example: | ||||||
| 
 | 
 | ||||||
| \begin{verbatim} | \begin{verbatim} | ||||||
| >>> from email.Header import decode_header | >>> from email.header import decode_header | ||||||
| >>> decode_header('=?iso-8859-1?q?p=F6stal?=') | >>> decode_header('=?iso-8859-1?q?p=F6stal?=') | ||||||
| [('p\xf6stal', 'iso-8859-1')] | [('p\xf6stal', 'iso-8859-1')] | ||||||
| \end{verbatim} | \end{verbatim} | ||||||
|  |  | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| \declaremodule{standard}{email.Iterators} | \declaremodule{standard}{email.iterators} | ||||||
| \modulesynopsis{Iterate over a  message object tree.} | \modulesynopsis{Iterate over a  message object tree.} | ||||||
| 
 | 
 | ||||||
| Iterating over a message object tree is fairly easy with the | 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 | provides some useful higher level iterations over message object | ||||||
| trees. | trees. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,10 +1,11 @@ | ||||||
| \declaremodule{standard}{email.Message} | \declaremodule{standard}{email.message} | ||||||
| \modulesynopsis{The base class representing email messages.} | \modulesynopsis{The base class representing email messages.} | ||||||
| 
 | 
 | ||||||
| The central class in the \module{email} package is the | The central class in the \module{email} package is the | ||||||
| \class{Message} class; it is the base class for the \module{email} | \class{Message} class, imported from the \module{email.message} module.  It is | ||||||
| object model.  \class{Message} provides the core functionality for | the base class for the \module{email} object model.  \class{Message} provides | ||||||
| setting and querying header fields, and for accessing message bodies. | the core functionality for setting and querying header fields, and for | ||||||
|  | accessing message bodies. | ||||||
| 
 | 
 | ||||||
| Conceptually, a \class{Message} object consists of \emph{headers} and | Conceptually, a \class{Message} object consists of \emph{headers} and | ||||||
| \emph{payloads}.  Headers are \rfc{2822} style field names 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} | \begin{verbatim} | ||||||
| from cStringIO import StringIO | from cStringIO import StringIO | ||||||
| from email.Generator import Generator | from email.generator import Generator | ||||||
| fp = StringIO() | fp = StringIO() | ||||||
| g = Generator(fp, mangle_from_=False, maxheaderlen=60) | g = Generator(fp, mangle_from_=False, maxheaderlen=60) | ||||||
| g.flatten(msg) | g.flatten(msg) | ||||||
|  | @ -119,7 +120,7 @@ client's responsibility to ensure the payload invariants.  Optional | ||||||
| 
 | 
 | ||||||
| \begin{methoddesc}[Message]{set_charset}{charset} | \begin{methoddesc}[Message]{set_charset}{charset} | ||||||
| Set the character set of the payload to \var{charset}, which can | 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, | string naming a character set, | ||||||
| or \code{None}.  If it is a string, it will be converted to a | or \code{None}.  If it is a string, it will be converted to a | ||||||
| \class{Charset} instance.  If \var{charset} is \code{None}, the | \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}. | \exception{TypeError}. | ||||||
| 
 | 
 | ||||||
| The message will be assumed to be of type \mimetype{text/*} encoded with | The message will be assumed to be of type \mimetype{text/*} encoded with | ||||||
| \code{charset.input_charset}.  It will be converted to | \var{charset.input_charset}.  It will be converted to | ||||||
| \code{charset.output_charset} | \var{charset.output_charset} | ||||||
| and encoded properly, if needed, when generating the plain text | and encoded properly, if needed, when generating the plain text | ||||||
| representation of the message.  MIME headers | representation of the message.  MIME headers | ||||||
| (\mailheader{MIME-Version}, \mailheader{Content-Type}, | (\mailheader{MIME-Version}, \mailheader{Content-Type}, | ||||||
|  | @ -513,6 +514,9 @@ message/rfc822 | ||||||
| \end{verbatim} | \end{verbatim} | ||||||
| \end{methoddesc} | \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 | \class{Message} objects can also optionally contain two instance | ||||||
| attributes, which can be used when generating the plain text of a MIME | attributes, which can be used when generating the plain text of a MIME | ||||||
| message. | 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 | 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 | finds the message has a \var{preamble} attribute, it will write this | ||||||
| text in the area between the headers and the first boundary.  See | 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 | Note that if the message object has no preamble, the | ||||||
| \var{preamble} attribute will be \code{None}. | \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 | attribute, except that it contains text that appears between the last | ||||||
| boundary and the end of the message. | boundary and the end of the message. | ||||||
| 
 | 
 | ||||||
| One note: when generating the flat text for a \mimetype{multipart} | \versionchanged[You do not need to set the epilogue to the empty string in | ||||||
| message that has no \var{epilogue} (using the standard | order for the \class{Generator} to print a newline at the end of the | ||||||
| \class{Generator} class), no newline is added after the closing | file]{2.5} | ||||||
| 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. |  | ||||||
| \end{datadesc} | \end{datadesc} | ||||||
| 
 | 
 | ||||||
| \begin{datadesc}{defects} | \begin{datadesc}{defects} | ||||||
| The \var{defects} attribute contains a list of all the problems found when | 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. | of the possible parsing defects. | ||||||
| 
 | 
 | ||||||
| \versionadded{2.4} | \versionadded{2.4} | ||||||
| \end{datadesc} | \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 | 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 | some text to a parser, which parses the text and returns the root | ||||||
| message object.  However you can also build a complete message | 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 | \class{Message} objects, move them around, etc.  This makes a very | ||||||
| convenient interface for slicing-and-dicing MIME messages. | convenient interface for slicing-and-dicing MIME messages. | ||||||
| 
 | 
 | ||||||
| You can create a new object structure by creating \class{Message} | You can create a new object structure by creating \class{Message} instances, | ||||||
| instances, adding attachments and all the appropriate headers manually. | adding attachments and all the appropriate headers manually.  For MIME | ||||||
| For MIME messages though, the \module{email} package provides some | messages though, the \module{email} package provides some convenient | ||||||
| convenient subclasses to make things easier.  Each of these classes | subclasses to make things easier. | ||||||
| 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} |  | ||||||
| 
 | 
 | ||||||
| Here are the classes: | Here are the classes: | ||||||
| 
 | 
 | ||||||
| \begin{classdesc}{MIMEBase}{_maintype, _subtype, **_params} | \begin{classdesc}{MIMEBase}{_maintype, _subtype, **_params} | ||||||
|  | Module: \module{email.mime.base} | ||||||
|  | 
 | ||||||
| This is the base class for all the MIME-specific subclasses of | This is the base class for all the MIME-specific subclasses of | ||||||
| \class{Message}.  Ordinarily you won't create instances specifically | \class{Message}.  Ordinarily you won't create instances specifically | ||||||
| of \class{MIMEBase}, although you could.  \class{MIMEBase} is provided | 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} | \end{classdesc} | ||||||
| 
 | 
 | ||||||
| \begin{classdesc}{MIMENonMultipart}{} | \begin{classdesc}{MIMENonMultipart}{} | ||||||
|  | Module: \module{email.mime.nonmultipart} | ||||||
|  | 
 | ||||||
| A subclass of \class{MIMEBase}, this is an intermediate base class for | A subclass of \class{MIMEBase}, this is an intermediate base class for | ||||||
| MIME messages that are not \mimetype{multipart}.  The primary purpose | MIME messages that are not \mimetype{multipart}.  The primary purpose | ||||||
| of this class is to prevent the use of the \method{attach()} method, | 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{, | \begin{classdesc}{MIMEMultipart}{\optional{subtype\optional{, | ||||||
|     boundary\optional{, _subparts\optional{, _params}}}}} |     boundary\optional{, _subparts\optional{, _params}}}}} | ||||||
|  | Module: \module{email.mime.multipart} | ||||||
| 
 | 
 | ||||||
| A subclass of \class{MIMEBase}, this is an intermediate base class for | A subclass of \class{MIMEBase}, this is an intermediate base class for | ||||||
| MIME messages that are \mimetype{multipart}.  Optional \var{_subtype} | MIME messages that are \mimetype{multipart}.  Optional \var{_subtype} | ||||||
|  | @ -80,8 +81,31 @@ argument, which is a keyword dictionary. | ||||||
| \versionadded{2.2.2} | \versionadded{2.2.2} | ||||||
| \end{classdesc} | \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{, | \begin{classdesc}{MIMEAudio}{_audiodata\optional{, _subtype\optional{, | ||||||
|     _encoder\optional{, **_params}}}} |     _encoder\optional{, **_params}}}} | ||||||
|  | Module: \module{email.mime.audio} | ||||||
| 
 | 
 | ||||||
| A subclass of \class{MIMENonMultipart}, the \class{MIMEAudio} class | A subclass of \class{MIMENonMultipart}, the \class{MIMEAudio} class | ||||||
| is used to create MIME message objects of major type \mimetype{audio}. | 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 | change the payload to encoded form.  It should also add any | ||||||
| \mailheader{Content-Transfer-Encoding} or other headers to the message | \mailheader{Content-Transfer-Encoding} or other headers to the message | ||||||
| object as necessary.  The default encoding is base64.  See the | 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. | \var{_params} are passed straight through to the base class constructor. | ||||||
| \end{classdesc} | \end{classdesc} | ||||||
| 
 | 
 | ||||||
| \begin{classdesc}{MIMEImage}{_imagedata\optional{, _subtype\optional{, | \begin{classdesc}{MIMEImage}{_imagedata\optional{, _subtype\optional{, | ||||||
|     _encoder\optional{, **_params}}}} |     _encoder\optional{, **_params}}}} | ||||||
|  | Module: \module{email.mime.image} | ||||||
| 
 | 
 | ||||||
| A subclass of \class{MIMENonMultipart}, the \class{MIMEImage} class is | A subclass of \class{MIMENonMultipart}, the \class{MIMEImage} class is | ||||||
| used to create MIME message objects of major type \mimetype{image}. | 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 | change the payload to encoded form.  It should also add any | ||||||
| \mailheader{Content-Transfer-Encoding} or other headers to the message | \mailheader{Content-Transfer-Encoding} or other headers to the message | ||||||
| object as necessary.  The default encoding is base64.  See the | 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} | \var{_params} are passed straight through to the \class{MIMEBase} | ||||||
| constructor. | constructor. | ||||||
| \end{classdesc} | \end{classdesc} | ||||||
| 
 | 
 | ||||||
| \begin{classdesc}{MIMEMessage}{_msg\optional{, _subtype}} | \begin{classdesc}{MIMEMessage}{_msg\optional{, _subtype}} | ||||||
|  | Module: \module{email.mime.message} | ||||||
|  | 
 | ||||||
| A subclass of \class{MIMENonMultipart}, the \class{MIMEMessage} class | A subclass of \class{MIMENonMultipart}, the \class{MIMEMessage} class | ||||||
| is used to create MIME objects of main type \mimetype{message}. | 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 | \var{_msg} is used as the payload, and must be an instance of class | ||||||
|  | @ -143,6 +170,8 @@ to \mimetype{rfc822}. | ||||||
| \end{classdesc} | \end{classdesc} | ||||||
| 
 | 
 | ||||||
| \begin{classdesc}{MIMEText}{_text\optional{, _subtype\optional{, _charset}}} | \begin{classdesc}{MIMEText}{_text\optional{, _subtype\optional{, _charset}}} | ||||||
|  | Module: \module{email.mime.text} | ||||||
|  | 
 | ||||||
| A subclass of \class{MIMENonMultipart}, the \class{MIMEText} class is | A subclass of \class{MIMENonMultipart}, the \class{MIMEText} class is | ||||||
| used to create MIME objects of major type \mimetype{text}. | used to create MIME objects of major type \mimetype{text}. | ||||||
| \var{_text} is the string for the payload.  \var{_subtype} is the | \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 | \modulesynopsis{Parse flat text email messages to produce a message | ||||||
| 	        object structure.} | 	        object structure.} | ||||||
| 
 | 
 | ||||||
|  | @ -41,9 +41,10 @@ message object trees any way it finds necessary. | ||||||
| 
 | 
 | ||||||
| \versionadded{2.4} | \versionadded{2.4} | ||||||
| 
 | 
 | ||||||
| The \class{FeedParser} provides an API that is conducive to incremental | The \class{FeedParser}, imported from the \module{email.feedparser} module, | ||||||
| parsing of email messages, such as would be necessary when reading the text of | provides an API that is conducive to incremental parsing of email messages, | ||||||
| an email message from a source that can block (e.g. a socket).  The | 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 | \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 | 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 | 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 | job of parsing non-compliant messages, providing information about how a | ||||||
| message was deemed broken.  It will populate a message object's \var{defects} | 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 | 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}: | Here is the API for the \class{FeedParser}: | ||||||
| 
 | 
 | ||||||
| \begin{classdesc}{FeedParser}{\optional{_factory}} | \begin{classdesc}{FeedParser}{\optional{_factory}} | ||||||
| Create a \class{FeedParser} instance.  Optional \var{_factory} is a | Create a \class{FeedParser} instance.  Optional \var{_factory} is a | ||||||
| no-argument callable that will be called whenever a new message object is | 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} | \end{classdesc} | ||||||
| 
 | 
 | ||||||
| \begin{methoddesc}[FeedParser]{feed}{data} | \begin{methoddesc}[FeedParser]{feed}{data} | ||||||
|  | @ -82,21 +83,22 @@ more data to a closed \class{FeedParser}. | ||||||
| 
 | 
 | ||||||
| \subsubsection{Parser class API} | \subsubsection{Parser class API} | ||||||
| 
 | 
 | ||||||
| The \class{Parser} provides an API that can be used to parse a message when | The \class{Parser} class, imported from the \module{email.parser} module, | ||||||
| the complete contents of the message are available in a string or file.  The | provides an API that can be used to parse a message when the complete contents | ||||||
| \module{email.Parser} module also provides a second class, called | 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 | \class{HeaderParser} which can be used if you're only interested in | ||||||
| the headers of the message. \class{HeaderParser} can be much faster 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, | these situations, since it does not attempt to parse the message body, | ||||||
| instead setting the payload to the raw body as a string. | instead setting the payload to the raw body as a string. | ||||||
| \class{HeaderParser} has the same API as the \class{Parser} class. | \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 | The constructor for the \class{Parser} class takes an optional | ||||||
| argument \var{_class}.  This must be a callable factory (such as a | 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 | function or a class), and it is used whenever a sub-message object | ||||||
| needs to be created.  It defaults to \class{Message} (see | 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. | arguments. | ||||||
| 
 | 
 | ||||||
| The optional \var{strict} flag is ignored.  \deprecated{2.4}{Because the | 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 |       \method{is_multipart()} method may return \code{False}.  If such | ||||||
|       messages were parsed with the \class{FeedParser}, they will have an |       messages were parsed with the \class{FeedParser}, they will have an | ||||||
|       instance of the \class{MultipartInvariantViolationDefect} class in their |       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. |       details. | ||||||
| \end{itemize} | \end{itemize} | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| \declaremodule{standard}{email.Utils} | \declaremodule{standard}{email.utils} | ||||||
| \modulesynopsis{Miscellaneous email package utilities.} | \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: | module: | ||||||
| 
 | 
 | ||||||
| \begin{funcdesc}{quote}{str} | \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: | simple example that gets all the recipients of a message: | ||||||
| 
 | 
 | ||||||
| \begin{verbatim} | \begin{verbatim} | ||||||
| from email.Utils import getaddresses | from email.utils import getaddresses | ||||||
| 
 | 
 | ||||||
| tos = msg.get_all('to', []) | tos = msg.get_all('to', []) | ||||||
| ccs = msg.get_all('cc', []) | ccs = msg.get_all('cc', []) | ||||||
|  |  | ||||||
|  | @ -12,9 +12,9 @@ | ||||||
| \authoraddress{\email{barry@python.org}} | \authoraddress{\email{barry@python.org}} | ||||||
| 
 | 
 | ||||||
| \date{\today} | \date{\today} | ||||||
| \release{3.0}			% software release, not documentation | \release{4.0}			% software release, not documentation | ||||||
| \setreleaseinfo{}		% empty for final release | \setreleaseinfo{}		% empty for final release | ||||||
| \setshortversion{3.0}		% major.minor only for software | \setshortversion{4.0}		% major.minor only for software | ||||||
| 
 | 
 | ||||||
| \begin{document} | \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 | parse, generate, and modify email messages, conforming to all the | ||||||
| relevant email and MIME related RFCs. | relevant email and MIME related RFCs. | ||||||
| 
 | 
 | ||||||
| This document describes version 3.0 of the \module{email} package, which is | This document describes version 4.0 of the \module{email} package, which is | ||||||
| distributed with Python 2.4 and is available as a standalone distutils-based | distributed with Python 2.5 and is available as a standalone distutils-based | ||||||
| package for use with Python 2.3.  \module{email} 3.0 is not compatible with | package for use with earlier Python versions.  \module{email} 4.0 is not | ||||||
| Python versions earlier than 2.3.  For more information about the | compatible with Python versions earlier than 2.3.  For more information about | ||||||
| \module{email} package, including download links and mailing lists, see | the \module{email} package, including download links and mailing lists, see | ||||||
| \ulink{Python's email SIG}{http://www.python.org/sigs/email-sig}. | \ulink{Python's email SIG}{http://www.python.org/sigs/email-sig}. | ||||||
| 
 | 
 | ||||||
| The documentation that follows was written for the Python project, so | 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} | \begin{itemize} | ||||||
| \item Deprecation and ``version added'' notes are relative to the | \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 | \item If you're reading this documentation as part of the | ||||||
|       standalone \module{email} package, some of the internal links to |       standalone \module{email} package, some of the internal links to | ||||||
|  |  | ||||||
|  | @ -4,9 +4,10 @@ | ||||||
| 
 | 
 | ||||||
| """A package for parsing, handling, and generating email messages.""" | """A package for parsing, handling, and generating email messages.""" | ||||||
| 
 | 
 | ||||||
| __version__ = '3.0.1' | __version__ = '4.0a2' | ||||||
| 
 | 
 | ||||||
| __all__ = [ | __all__ = [ | ||||||
|  |     # Old names | ||||||
|     'base64MIME', |     'base64MIME', | ||||||
|     'Charset', |     'Charset', | ||||||
|     'Encoders', |     'Encoders', | ||||||
|  | @ -27,6 +28,19 @@ | ||||||
|     'Utils', |     'Utils', | ||||||
|     'message_from_string', |     'message_from_string', | ||||||
|     'message_from_file', |     '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. |     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) |     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. |     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) |     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. | Lifted directly from rfc822.py.  This should eventually be rewritten. | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
|  | __all__ = [ | ||||||
|  |     'mktime_tz', | ||||||
|  |     'parsedate', | ||||||
|  |     'parsedate_tz', | ||||||
|  |     'quote', | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
| import time | import time | ||||||
| 
 | 
 | ||||||
| SPACE = ' ' | SPACE = ' ' | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| # Copyright (C) 2002-2004 Python Software Foundation | # Copyright (C) 2002-2006 Python Software Foundation | ||||||
| # Author: Ben Gertzfield | # Author: Ben Gertzfield | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
|  | @ -24,9 +24,21 @@ | ||||||
| module. | module. | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
|  | __all__ = [ | ||||||
|  |     'base64_len', | ||||||
|  |     'body_decode', | ||||||
|  |     'body_encode', | ||||||
|  |     'decode', | ||||||
|  |     'decodestring', | ||||||
|  |     'encode', | ||||||
|  |     'encodestring', | ||||||
|  |     'header_encode', | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
| import re | import re | ||||||
|  | 
 | ||||||
| from binascii import b2a_base64, a2b_base64 | from binascii import b2a_base64, a2b_base64 | ||||||
| from email.Utils import fix_eols | from email.utils import fix_eols | ||||||
| 
 | 
 | ||||||
| CRLF = '\r\n' | CRLF = '\r\n' | ||||||
| NL = '\n' | NL = '\n' | ||||||
|  | @ -2,9 +2,18 @@ | ||||||
| # Author: Ben Gertzfield, Barry Warsaw | # Author: Ben Gertzfield, Barry Warsaw | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
| import email.base64MIME | __all__ = [ | ||||||
| import email.quopriMIME |     'Charset', | ||||||
| from email.Encoders import encode_7or8bit |     '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): |     def __init__(self, input_charset=DEFAULT_CHARSET): | ||||||
|         # RFC 2046, $4.1.2 says charsets are not case sensitive.  We coerce to |         # RFC 2046, $4.1.2 says charsets are not case sensitive.  We coerce to | ||||||
|         # unicode because its .lower() is locale insensitive. |         # unicode because its .lower() is locale insensitive.  If the argument | ||||||
|         input_charset = unicode(input_charset, 'ascii').lower() |         # 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 |         # Set the input charset after filtering through the aliases | ||||||
|         self.input_charset = ALIASES.get(input_charset, input_charset) |         self.input_charset = ALIASES.get(input_charset, input_charset) | ||||||
|         # We can try to guess which encoding and conversion to use by the |         # 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() |         cset = self.get_output_charset() | ||||||
|         # The len(s) of a 7bit encoding is len(s) |         # The len(s) of a 7bit encoding is len(s) | ||||||
|         if self.header_encoding == BASE64: |         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: |         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: |         elif self.header_encoding == SHORTEST: | ||||||
|             lenb64 = email.base64MIME.base64_len(s) |             lenb64 = email.base64mime.base64_len(s) | ||||||
|             lenqp = email.quopriMIME.header_quopri_len(s) |             lenqp = email.quoprimime.header_quopri_len(s) | ||||||
|             return min(lenb64, lenqp) + len(cset) + MISC_LEN |             return min(lenb64, lenqp) + len(cset) + MISC_LEN | ||||||
|         else: |         else: | ||||||
|             return len(s) |             return len(s) | ||||||
|  | @ -335,16 +353,16 @@ def header_encode(self, s, convert=False): | ||||||
|             s = self.convert(s) |             s = self.convert(s) | ||||||
|         # 7bit/8bit encodings return the string unchanged (modulo conversions) |         # 7bit/8bit encodings return the string unchanged (modulo conversions) | ||||||
|         if self.header_encoding == BASE64: |         if self.header_encoding == BASE64: | ||||||
|             return email.base64MIME.header_encode(s, cset) |             return email.base64mime.header_encode(s, cset) | ||||||
|         elif self.header_encoding == QP: |         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: |         elif self.header_encoding == SHORTEST: | ||||||
|             lenb64 = email.base64MIME.base64_len(s) |             lenb64 = email.base64mime.base64_len(s) | ||||||
|             lenqp = email.quopriMIME.header_quopri_len(s) |             lenqp = email.quoprimime.header_quopri_len(s) | ||||||
|             if lenb64 < lenqp: |             if lenb64 < lenqp: | ||||||
|                 return email.base64MIME.header_encode(s, cset) |                 return email.base64mime.header_encode(s, cset) | ||||||
|             else: |             else: | ||||||
|                 return email.quopriMIME.header_encode(s, cset, maxlinelen=None) |                 return email.quoprimime.header_encode(s, cset, maxlinelen=None) | ||||||
|         else: |         else: | ||||||
|             return s |             return s | ||||||
| 
 | 
 | ||||||
|  | @ -363,8 +381,8 @@ def body_encode(self, s, convert=True): | ||||||
|             s = self.convert(s) |             s = self.convert(s) | ||||||
|         # 7bit/8bit encodings return the string unchanged (module conversions) |         # 7bit/8bit encodings return the string unchanged (module conversions) | ||||||
|         if self.body_encoding is BASE64: |         if self.body_encoding is BASE64: | ||||||
|             return email.base64MIME.body_encode(s) |             return email.base64mime.body_encode(s) | ||||||
|         elif self.body_encoding is QP: |         elif self.body_encoding is QP: | ||||||
|             return email.quopriMIME.body_encode(s) |             return email.quoprimime.body_encode(s) | ||||||
|         else: |         else: | ||||||
|             return s |             return s | ||||||
|  | @ -1,12 +1,22 @@ | ||||||
| # Copyright (C) 2001-2004 Python Software Foundation | # Copyright (C) 2001-2006 Python Software Foundation | ||||||
| # Author: Barry Warsaw | # Author: Barry Warsaw | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
| """Encodings and related functions.""" | """Encodings and related functions.""" | ||||||
| 
 | 
 | ||||||
|  | __all__ = [ | ||||||
|  |     'encode_7or8bit', | ||||||
|  |     'encode_base64', | ||||||
|  |     'encode_noop', | ||||||
|  |     'encode_quopri', | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
| import base64 | import base64 | ||||||
|  | 
 | ||||||
| from quopri import encodestring as _encodestring | from quopri import encodestring as _encodestring | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |  | ||||||
| def _qencode(s): | def _qencode(s): | ||||||
|     enc = _encodestring(s, quotetabs=True) |     enc = _encodestring(s, quotetabs=True) | ||||||
|     # Must encode spaces, which quopri.encodestring() doesn't do |     # 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 | # Author: Barry Warsaw | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
|  | @ -26,6 +26,10 @@ class MultipartConversionError(MessageError, TypeError): | ||||||
|     """Conversion to a multipart is prohibited.""" |     """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. | # These are parsing defects which the parser was able to work around. | ||||||
| class MessageDefect: | class MessageDefect: | ||||||
|  | @ -19,9 +19,12 @@ | ||||||
| object's .defects attribute. | object's .defects attribute. | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
|  | __all__ = ['FeedParser'] | ||||||
|  | 
 | ||||||
| import re | 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 = re.compile('\r\n|\r|\n') | ||||||
| NLCRE_bol = re.compile('(\r\n|\r|\n)') | NLCRE_bol = re.compile('(\r\n|\r|\n)') | ||||||
|  | @ -130,7 +133,7 @@ def next(self): | ||||||
| class FeedParser: | class FeedParser: | ||||||
|     """A feed-style parser of email.""" |     """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""" |         """_factory is called with no arguments to create a new message obj""" | ||||||
|         self._factory = _factory |         self._factory = _factory | ||||||
|         self._input = BufferedSubFile() |         self._input = BufferedSubFile() | ||||||
|  | @ -164,7 +167,7 @@ def close(self): | ||||||
|         # Look for final set of defects |         # Look for final set of defects | ||||||
|         if root.get_content_maintype() == 'multipart' \ |         if root.get_content_maintype() == 'multipart' \ | ||||||
|                and not root.is_multipart(): |                and not root.is_multipart(): | ||||||
|             root.defects.append(Errors.MultipartInvariantViolationDefect()) |             root.defects.append(errors.MultipartInvariantViolationDefect()) | ||||||
|         return root |         return root | ||||||
| 
 | 
 | ||||||
|     def _new_message(self): |     def _new_message(self): | ||||||
|  | @ -277,7 +280,7 @@ def _parsegen(self): | ||||||
|                 # defined a boundary.  That's a problem which we'll handle by |                 # defined a boundary.  That's a problem which we'll handle by | ||||||
|                 # reading everything until the EOF and marking the message as |                 # reading everything until the EOF and marking the message as | ||||||
|                 # defective. |                 # defective. | ||||||
|                 self._cur.defects.append(Errors.NoBoundaryInMultipartDefect()) |                 self._cur.defects.append(errors.NoBoundaryInMultipartDefect()) | ||||||
|                 lines = [] |                 lines = [] | ||||||
|                 for line in self._input: |                 for line in self._input: | ||||||
|                     if line is NeedMoreData: |                     if line is NeedMoreData: | ||||||
|  | @ -381,7 +384,7 @@ def _parsegen(self): | ||||||
|             # that as a defect and store the captured text as the payload. |             # that as a defect and store the captured text as the payload. | ||||||
|             # Everything from here to the EOF is epilogue. |             # Everything from here to the EOF is epilogue. | ||||||
|             if capturing_preamble: |             if capturing_preamble: | ||||||
|                 self._cur.defects.append(Errors.StartBoundaryNotFoundDefect()) |                 self._cur.defects.append(errors.StartBoundaryNotFoundDefect()) | ||||||
|                 self._cur.set_payload(EMPTYSTRING.join(preamble)) |                 self._cur.set_payload(EMPTYSTRING.join(preamble)) | ||||||
|                 epilogue = [] |                 epilogue = [] | ||||||
|                 for line in self._input: |                 for line in self._input: | ||||||
|  | @ -432,7 +435,7 @@ def _parse_headers(self, lines): | ||||||
|                     # The first line of the headers was a continuation.  This |                     # The first line of the headers was a continuation.  This | ||||||
|                     # is illegal, so let's note the defect, store the illegal |                     # is illegal, so let's note the defect, store the illegal | ||||||
|                     # line, and ignore it for purposes of headers. |                     # line, and ignore it for purposes of headers. | ||||||
|                     defect = Errors.FirstHeaderLineIsContinuationDefect(line) |                     defect = errors.FirstHeaderLineIsContinuationDefect(line) | ||||||
|                     self._cur.defects.append(defect) |                     self._cur.defects.append(defect) | ||||||
|                     continue |                     continue | ||||||
|                 lastvalue.append(line) |                 lastvalue.append(line) | ||||||
|  | @ -460,13 +463,13 @@ def _parse_headers(self, lines): | ||||||
|                 else: |                 else: | ||||||
|                     # Weirdly placed unix-from line.  Note this as a defect |                     # Weirdly placed unix-from line.  Note this as a defect | ||||||
|                     # and ignore it. |                     # and ignore it. | ||||||
|                     defect = Errors.MisplacedEnvelopeHeaderDefect(line) |                     defect = errors.MisplacedEnvelopeHeaderDefect(line) | ||||||
|                     self._cur.defects.append(defect) |                     self._cur.defects.append(defect) | ||||||
|                     continue |                     continue | ||||||
|             # Split the line on the colon separating field name from value. |             # Split the line on the colon separating field name from value. | ||||||
|             i = line.find(':') |             i = line.find(':') | ||||||
|             if i < 0: |             if i < 0: | ||||||
|                 defect = Errors.MalformedHeaderDefect(line) |                 defect = errors.MalformedHeaderDefect(line) | ||||||
|                 self._cur.defects.append(defect) |                 self._cur.defects.append(defect) | ||||||
|                 continue |                 continue | ||||||
|             lastheader = line[:i] |             lastheader = line[:i] | ||||||
|  | @ -4,14 +4,16 @@ | ||||||
| 
 | 
 | ||||||
| """Classes to generate plain text from a message object tree.""" | """Classes to generate plain text from a message object tree.""" | ||||||
| 
 | 
 | ||||||
|  | __all__ = ['Generator', 'DecodedGenerator'] | ||||||
|  | 
 | ||||||
| import re | import re | ||||||
| import sys | import sys | ||||||
| import time | import time | ||||||
| import random | import random | ||||||
| import warnings | import warnings | ||||||
| from cStringIO import StringIO |  | ||||||
| 
 | 
 | ||||||
| from email.Header import Header | from cStringIO import StringIO | ||||||
|  | from email.header import Header | ||||||
| 
 | 
 | ||||||
| UNDERSCORE = '_' | UNDERSCORE = '_' | ||||||
| NL = '\n' | NL = '\n' | ||||||
|  | @ -81,12 +83,6 @@ def flatten(self, msg, unixfrom=False): | ||||||
|             print >> self._fp, ufrom |             print >> self._fp, ufrom | ||||||
|         self._write(msg) |         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): |     def clone(self, fp): | ||||||
|         """Clone this generator with the exact same options.""" |         """Clone this generator with the exact same options.""" | ||||||
|         return self.__class__(fp, self._mangle_from_, self._maxheaderlen) |         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 | # Author: Ben Gertzfield, Barry Warsaw | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
| """Header encoding and decoding functionality.""" | """Header encoding and decoding functionality.""" | ||||||
| 
 | 
 | ||||||
|  | __all__ = [ | ||||||
|  |     'Header', | ||||||
|  |     'decode_header', | ||||||
|  |     'make_header', | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
| import re | import re | ||||||
| import binascii | import binascii | ||||||
| 
 | 
 | ||||||
| import email.quopriMIME | import email.quoprimime | ||||||
| import email.base64MIME | import email.base64mime | ||||||
| from email.Errors import HeaderParseError | 
 | ||||||
| from email.Charset import Charset | from email.errors import HeaderParseError | ||||||
|  | from email.charset import Charset | ||||||
| 
 | 
 | ||||||
| NL = '\n' | NL = '\n' | ||||||
| SPACE = ' ' | SPACE = ' ' | ||||||
|  | @ -42,7 +49,7 @@ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
| # Helpers | # Helpers | ||||||
| _max_append = email.quopriMIME._max_append | _max_append = email.quoprimime._max_append | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -82,10 +89,10 @@ def decode_header(header): | ||||||
|                 encoded = parts[2] |                 encoded = parts[2] | ||||||
|                 dec = None |                 dec = None | ||||||
|                 if encoding == 'q': |                 if encoding == 'q': | ||||||
|                     dec = email.quopriMIME.header_decode(encoded) |                     dec = email.quoprimime.header_decode(encoded) | ||||||
|                 elif encoding == 'b': |                 elif encoding == 'b': | ||||||
|                     try: |                     try: | ||||||
|                         dec = email.base64MIME.decode(encoded) |                         dec = email.base64mime.decode(encoded) | ||||||
|                     except binascii.Error: |                     except binascii.Error: | ||||||
|                         # Turn this into a higher level exception.  BAW: Right |                         # Turn this into a higher level exception.  BAW: Right | ||||||
|                         # now we throw the lower level exception away but |                         # 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 | # Author: Barry Warsaw | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
| """Various types of useful iterators and generators.""" | """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 | import sys | ||||||
| from cStringIO import StringIO | from cStringIO import StringIO | ||||||
| 
 | 
 | ||||||
|  | @ -25,7 +32,6 @@ def walk(self): | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
| # These two functions are imported into the Iterators.py interface module. | # 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): | def body_line_iterator(msg, decode=False): | ||||||
|     """Iterate over the parts, returning string payloads line-by-line. |     """Iterate over the parts, returning string payloads line-by-line. | ||||||
| 
 | 
 | ||||||
|  | @ -4,6 +4,8 @@ | ||||||
| 
 | 
 | ||||||
| """Basic message object for the email package object model.""" | """Basic message object for the email package object model.""" | ||||||
| 
 | 
 | ||||||
|  | __all__ = ['Message'] | ||||||
|  | 
 | ||||||
| import re | import re | ||||||
| import uu | import uu | ||||||
| import binascii | import binascii | ||||||
|  | @ -11,9 +13,9 @@ | ||||||
| from cStringIO import StringIO | from cStringIO import StringIO | ||||||
| 
 | 
 | ||||||
| # Intrapackage imports | # Intrapackage imports | ||||||
| from email import Utils | import email.charset | ||||||
| from email import Errors | from email import utils | ||||||
| from email import Charset | from email import errors | ||||||
| 
 | 
 | ||||||
| SEMISPACE = '; ' | SEMISPACE = '; ' | ||||||
| 
 | 
 | ||||||
|  | @ -41,11 +43,11 @@ def _formatparam(param, value=None, quote=True): | ||||||
|         if isinstance(value, tuple): |         if isinstance(value, tuple): | ||||||
|             # Encode as per RFC 2231 |             # Encode as per RFC 2231 | ||||||
|             param += '*' |             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 |         # BAW: Please check this.  I think that if quote is set it should | ||||||
|         # force quoting even if not necessary. |         # force quoting even if not necessary. | ||||||
|         if quote or tspecials.search(value): |         if quote or tspecials.search(value): | ||||||
|             return '%s="%s"' % (param, Utils.quote(value)) |             return '%s="%s"' % (param, utils.quote(value)) | ||||||
|         else: |         else: | ||||||
|             return '%s=%s' % (param, value) |             return '%s=%s' % (param, value) | ||||||
|     else: |     else: | ||||||
|  | @ -70,14 +72,14 @@ def _parseparam(s): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def _unquotevalue(value): | 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 |     # try to convert the value to a unicode.  Message.get_param() and | ||||||
|     # Message.get_params() are both currently defined to return the tuple in |     # Message.get_params() are both currently defined to return the tuple in | ||||||
|     # the face of RFC 2231 parameters. |     # the face of RFC 2231 parameters. | ||||||
|     if isinstance(value, tuple): |     if isinstance(value, tuple): | ||||||
|         return value[0], value[1], Utils.unquote(value[2]) |         return value[0], value[1], utils.unquote(value[2]) | ||||||
|     else: |     else: | ||||||
|         return Utils.unquote(value) |         return utils.unquote(value) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -188,17 +190,17 @@ def get_payload(self, i=None, decode=False): | ||||||
|                 return None |                 return None | ||||||
|             cte = self.get('content-transfer-encoding', '').lower() |             cte = self.get('content-transfer-encoding', '').lower() | ||||||
|             if cte == 'quoted-printable': |             if cte == 'quoted-printable': | ||||||
|                 return Utils._qdecode(payload) |                 return utils._qdecode(payload) | ||||||
|             elif cte == 'base64': |             elif cte == 'base64': | ||||||
|                 try: |                 try: | ||||||
|                     return Utils._bdecode(payload) |                     return utils._bdecode(payload) | ||||||
|                 except binascii.Error: |                 except binascii.Error: | ||||||
|                     # Incorrect padding |                     # Incorrect padding | ||||||
|                     return payload |                     return payload | ||||||
|             elif cte in ('x-uuencode', 'uuencode', 'uue', 'x-uue'): |             elif cte in ('x-uuencode', 'uuencode', 'uue', 'x-uue'): | ||||||
|                 sfp = StringIO() |                 sfp = StringIO() | ||||||
|                 try: |                 try: | ||||||
|                     uu.decode(StringIO(payload+'\n'), sfp) |                     uu.decode(StringIO(payload+'\n'), sfp, quiet=True) | ||||||
|                     payload = sfp.getvalue() |                     payload = sfp.getvalue() | ||||||
|                 except uu.Error: |                 except uu.Error: | ||||||
|                     # Some decoding problem |                     # Some decoding problem | ||||||
|  | @ -237,8 +239,8 @@ def set_charset(self, charset): | ||||||
|             self._charset = None |             self._charset = None | ||||||
|             return |             return | ||||||
|         if isinstance(charset, str): |         if isinstance(charset, str): | ||||||
|             charset = Charset.Charset(charset) |             charset = email.charset.Charset(charset) | ||||||
|         if not isinstance(charset, Charset.Charset): |         if not isinstance(charset, email.charset.Charset): | ||||||
|             raise TypeError(charset) |             raise TypeError(charset) | ||||||
|         # BAW: should we accept strings that can serve as arguments to the |         # BAW: should we accept strings that can serve as arguments to the | ||||||
|         # Charset constructor? |         # Charset constructor? | ||||||
|  | @ -412,49 +414,6 @@ def replace_header(self, _name, _value): | ||||||
|         else: |         else: | ||||||
|             raise KeyError(_name) |             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. |     # Use these three methods instead of the three above. | ||||||
|     # |     # | ||||||
|  | @ -537,7 +496,7 @@ def _get_params_preserve(self, failobj, header): | ||||||
|                 name = p.strip() |                 name = p.strip() | ||||||
|                 val = '' |                 val = '' | ||||||
|             params.append((name, val)) |             params.append((name, val)) | ||||||
|         params = Utils.decode_params(params) |         params = utils.decode_params(params) | ||||||
|         return params |         return params | ||||||
| 
 | 
 | ||||||
|     def get_params(self, failobj=None, header='content-type', unquote=True): |     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') |             filename = self.get_param('name', missing, 'content-disposition') | ||||||
|         if filename is missing: |         if filename is missing: | ||||||
|             return failobj |             return failobj | ||||||
|         return Utils.collapse_rfc2231_value(filename).strip() |         return utils.collapse_rfc2231_value(filename).strip() | ||||||
| 
 | 
 | ||||||
|     def get_boundary(self, failobj=None): |     def get_boundary(self, failobj=None): | ||||||
|         """Return the boundary associated with the payload if present. |         """Return the boundary associated with the payload if present. | ||||||
|  | @ -727,7 +686,7 @@ def get_boundary(self, failobj=None): | ||||||
|         if boundary is missing: |         if boundary is missing: | ||||||
|             return failobj |             return failobj | ||||||
|         # RFC 2046 says that boundaries may begin but not end in w/s |         # 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): |     def set_boundary(self, boundary): | ||||||
|         """Set the boundary parameter in Content-Type to 'boundary'. |         """Set the boundary parameter in Content-Type to 'boundary'. | ||||||
|  | @ -744,7 +703,7 @@ def set_boundary(self, boundary): | ||||||
|         if params is missing: |         if params is missing: | ||||||
|             # There was no Content-Type header, and we don't know what type |             # There was no Content-Type header, and we don't know what type | ||||||
|             # to set it to, so raise an exception. |             # 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 = [] |         newparams = [] | ||||||
|         foundp = False |         foundp = False | ||||||
|         for pk, pv in params: |         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 | # Author: Anthony Baxter | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
| """Class representing audio/* type MIME documents.""" | """Class representing audio/* type MIME documents.""" | ||||||
| 
 | 
 | ||||||
| import sndhdr | __all__ = ['MIMEAudio'] | ||||||
| from cStringIO import StringIO |  | ||||||
| 
 | 
 | ||||||
| from email import Errors | import sndhdr | ||||||
| from email import Encoders | 
 | ||||||
| from email.MIMENonMultipart import MIMENonMultipart | 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.""" |     """Class for generating audio/* MIME documents.""" | ||||||
| 
 | 
 | ||||||
|     def __init__(self, _audiodata, _subtype=None, |     def __init__(self, _audiodata, _subtype=None, | ||||||
|                  _encoder=Encoders.encode_base64, **_params): |                  _encoder=encoders.encode_base64, **_params): | ||||||
|         """Create an audio/* type MIME document. |         """Create an audio/* type MIME document. | ||||||
| 
 | 
 | ||||||
|         _audiodata is a string containing the raw audio data.  If this data |         _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 | # Author: Barry Warsaw | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
| """Base class for MIME specializations.""" | """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.""" |     """Base class for MIME specializations.""" | ||||||
| 
 | 
 | ||||||
|     def __init__(self, _maintype, _subtype, **_params): |     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 |         arguments.  Additional parameters for this header are taken from the | ||||||
|         keyword arguments. |         keyword arguments. | ||||||
|         """ |         """ | ||||||
|         Message.Message.__init__(self) |         message.Message.__init__(self) | ||||||
|         ctype = '%s/%s' % (_maintype, _subtype) |         ctype = '%s/%s' % (_maintype, _subtype) | ||||||
|         self.add_header('Content-Type', ctype, **_params) |         self.add_header('Content-Type', ctype, **_params) | ||||||
|         self['MIME-Version'] = '1.0' |         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 | # Author: Barry Warsaw | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
| """Class representing image/* type MIME documents.""" | """Class representing image/* type MIME documents.""" | ||||||
| 
 | 
 | ||||||
|  | __all__ = ['MIMEImage'] | ||||||
|  | 
 | ||||||
| import imghdr | import imghdr | ||||||
| 
 | 
 | ||||||
| from email import Errors | from email import encoders | ||||||
| from email import Encoders | from email.mime.nonmultipart import MIMENonMultipart | ||||||
| from email.MIMENonMultipart import MIMENonMultipart |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -16,7 +17,7 @@ class MIMEImage(MIMENonMultipart): | ||||||
|     """Class for generating image/* type MIME documents.""" |     """Class for generating image/* type MIME documents.""" | ||||||
| 
 | 
 | ||||||
|     def __init__(self, _imagedata, _subtype=None, |     def __init__(self, _imagedata, _subtype=None, | ||||||
|                  _encoder=Encoders.encode_base64, **_params): |                  _encoder=encoders.encode_base64, **_params): | ||||||
|         """Create an image/* type MIME document. |         """Create an image/* type MIME document. | ||||||
| 
 | 
 | ||||||
|         _imagedata is a string containing the raw image data.  If this data |         _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 | # Author: Barry Warsaw | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
| """Class representing message/* MIME documents.""" | """Class representing message/* MIME documents.""" | ||||||
| 
 | 
 | ||||||
| from email import Message | __all__ = ['MIMEMessage'] | ||||||
| from email.MIMENonMultipart import MIMENonMultipart | 
 | ||||||
|  | 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). |         the term "rfc822" is technically outdated by RFC 2822). | ||||||
|         """ |         """ | ||||||
|         MIMENonMultipart.__init__(self, 'message', _subtype) |         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') |             raise TypeError('Argument is not an instance of Message') | ||||||
|         # It's convenient to use this base class method.  We need to do it |         # It's convenient to use this base class method.  We need to do it | ||||||
|         # this way or we'll get an exception |         # 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 |         # And be sure our default type is set correctly | ||||||
|         self.set_default_type('message/rfc822') |         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 | # Author: Barry Warsaw | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
| """Base class for MIME multipart/* type messages.""" | """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.""" |     """Base class for MIME multipart/* type messages.""" | ||||||
| 
 | 
 | ||||||
|     def __init__(self, _subtype='mixed', boundary=None, _subparts=None, |     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 |         Additional parameters for the Content-Type header are taken from the | ||||||
|         keyword arguments (or passed into the _params argument). |         keyword arguments (or passed into the _params argument). | ||||||
|         """ |         """ | ||||||
|         MIMEBase.MIMEBase.__init__(self, 'multipart', _subtype, **_params) |         MIMEBase.__init__(self, 'multipart', _subtype, **_params) | ||||||
|         if _subparts: |         if _subparts: | ||||||
|             for p in _subparts: |             for p in _subparts: | ||||||
|                 self.attach(p) |                 self.attach(p) | ||||||
|  | @ -1,15 +1,17 @@ | ||||||
| # Copyright (C) 2002-2004 Python Software Foundation | # Copyright (C) 2002-2006 Python Software Foundation | ||||||
| # Author: Barry Warsaw | # Author: Barry Warsaw | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
| """Base class for MIME type messages that are not multipart.""" | """Base class for MIME type messages that are not multipart.""" | ||||||
| 
 | 
 | ||||||
| from email import Errors | __all__ = ['MIMENonMultipart'] | ||||||
| from email import MIMEBase | 
 | ||||||
|  | from email import errors | ||||||
|  | from email.mime.base import MIMEBase | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
| class MIMENonMultipart(MIMEBase.MIMEBase): | class MIMENonMultipart(MIMEBase): | ||||||
|     """Base class for MIME multipart/* type messages.""" |     """Base class for MIME multipart/* type messages.""" | ||||||
| 
 | 
 | ||||||
|     __pychecker__ = 'unusednames=payload' |     __pychecker__ = 'unusednames=payload' | ||||||
|  | @ -18,7 +20,7 @@ def attach(self, payload): | ||||||
|         # The public API prohibits attaching multiple subparts to MIMEBase |         # The public API prohibits attaching multiple subparts to MIMEBase | ||||||
|         # derived subtypes since none of them are, by definition, of content |         # derived subtypes since none of them are, by definition, of content | ||||||
|         # type multipart/* |         # type multipart/* | ||||||
|         raise Errors.MultipartConversionError( |         raise errors.MultipartConversionError( | ||||||
|             'Cannot attach additional subparts to non-multipart/*') |             'Cannot attach additional subparts to non-multipart/*') | ||||||
| 
 | 
 | ||||||
|     del __pychecker__ |     del __pychecker__ | ||||||
|  | @ -1,11 +1,13 @@ | ||||||
| # Copyright (C) 2001-2004 Python Software Foundation | # Copyright (C) 2001-2006 Python Software Foundation | ||||||
| # Author: Barry Warsaw | # Author: Barry Warsaw | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
| """Class representing text/* type MIME documents.""" | """Class representing text/* type MIME documents.""" | ||||||
| 
 | 
 | ||||||
| from email.MIMENonMultipart import MIMENonMultipart | __all__ = ['MIMEText'] | ||||||
| from email.Encoders import encode_7or8bit | 
 | ||||||
|  | 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 | # Author: Barry Warsaw, Thomas Wouters, Anthony Baxter | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
| """A parser of RFC 2822 and MIME email messages.""" | """A parser of RFC 2822 and MIME email messages.""" | ||||||
| 
 | 
 | ||||||
|  | __all__ = ['Parser', 'HeaderParser'] | ||||||
|  | 
 | ||||||
| import warnings | import warnings | ||||||
| from cStringIO import StringIO | 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 | # Author: Ben Gertzfield | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
|  | @ -26,9 +26,27 @@ | ||||||
| wrapping issues, use the email.Header module. | 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 | import re | ||||||
|  | 
 | ||||||
| from string import hexdigits | from string import hexdigits | ||||||
| from email.Utils import fix_eols | from email.utils import fix_eols | ||||||
| 
 | 
 | ||||||
| CRLF = '\r\n' | CRLF = '\r\n' | ||||||
| NL = '\n' | NL = '\n' | ||||||
|  | @ -39,9 +39,6 @@ | ||||||
| EMPTYSTRING = '' | EMPTYSTRING = '' | ||||||
| SPACE = ' ' | SPACE = ' ' | ||||||
| 
 | 
 | ||||||
| # We don't care about DeprecationWarnings |  | ||||||
| warnings.filterwarnings('ignore', '', DeprecationWarning, __name__) |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
| def openfile(filename, mode='r'): | def openfile(filename, mode='r'): | ||||||
|  | @ -87,7 +84,7 @@ def test_getset_charset(self): | ||||||
|         charset = Charset('iso-8859-1') |         charset = Charset('iso-8859-1') | ||||||
|         msg.set_charset(charset) |         msg.set_charset(charset) | ||||||
|         eq(msg['mime-version'], '1.0') |         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['content-type'], 'text/plain; charset="iso-8859-1"') | ||||||
|         eq(msg.get_param('charset'), 'iso-8859-1') |         eq(msg.get_param('charset'), 'iso-8859-1') | ||||||
|         eq(msg['content-transfer-encoding'], 'quoted-printable') |         eq(msg['content-transfer-encoding'], 'quoted-printable') | ||||||
|  | @ -211,6 +208,19 @@ def test_get_decoded_uu_payload(self): | ||||||
|         msg.set_payload('foo') |         msg.set_payload('foo') | ||||||
|         eq(msg.get_payload(decode=True), '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): |     def test_decoded_generator(self): | ||||||
|         eq = self.assertEqual |         eq = self.assertEqual | ||||||
|         msg = self._msgobj('msg_07.txt') |         msg = self._msgobj('msg_07.txt') | ||||||
|  | @ -893,7 +903,7 @@ def setUp(self): | ||||||
|         self._au = MIMEAudio(self._audiodata) |         self._au = MIMEAudio(self._audiodata) | ||||||
| 
 | 
 | ||||||
|     def test_guess_minor_type(self): |     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): |     def test_encoding(self): | ||||||
|         payload = self._au.get_payload() |         payload = self._au.get_payload() | ||||||
|  | @ -901,7 +911,7 @@ def test_encoding(self): | ||||||
| 
 | 
 | ||||||
|     def test_checkSetMinor(self): |     def test_checkSetMinor(self): | ||||||
|         au = MIMEAudio(self._audiodata, 'fish') |         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): |     def test_add_header(self): | ||||||
|         eq = self.assertEqual |         eq = self.assertEqual | ||||||
|  | @ -936,7 +946,7 @@ def setUp(self): | ||||||
|         self._im = MIMEImage(self._imgdata) |         self._im = MIMEImage(self._imgdata) | ||||||
| 
 | 
 | ||||||
|     def test_guess_minor_type(self): |     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): |     def test_encoding(self): | ||||||
|         payload = self._im.get_payload() |         payload = self._im.get_payload() | ||||||
|  | @ -944,7 +954,7 @@ def test_encoding(self): | ||||||
| 
 | 
 | ||||||
|     def test_checkSetMinor(self): |     def test_checkSetMinor(self): | ||||||
|         im = MIMEImage(self._imgdata, 'fish') |         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): |     def test_add_header(self): | ||||||
|         eq = self.assertEqual |         eq = self.assertEqual | ||||||
|  | @ -976,7 +986,7 @@ def setUp(self): | ||||||
|     def test_types(self): |     def test_types(self): | ||||||
|         eq = self.assertEqual |         eq = self.assertEqual | ||||||
|         unless = self.failUnless |         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') |         eq(self._msg.get_param('charset'), 'us-ascii') | ||||||
|         missing = [] |         missing = [] | ||||||
|         unless(self._msg.get_param('foobar', missing) is missing) |         unless(self._msg.get_param('foobar', missing) is missing) | ||||||
|  | @ -1045,7 +1055,7 @@ def test_hierarchy(self): | ||||||
|         # tests |         # tests | ||||||
|         m = self._msg |         m = self._msg | ||||||
|         unless(m.is_multipart()) |         unless(m.is_multipart()) | ||||||
|         eq(m.get_type(), 'multipart/mixed') |         eq(m.get_content_type(), 'multipart/mixed') | ||||||
|         eq(len(m.get_payload()), 2) |         eq(len(m.get_payload()), 2) | ||||||
|         raises(IndexError, m.get_payload, 2) |         raises(IndexError, m.get_payload, 2) | ||||||
|         m0 = m.get_payload(0) |         m0 = m.get_payload(0) | ||||||
|  | @ -1379,7 +1389,7 @@ class TestNonConformant(TestEmailBase): | ||||||
|     def test_parse_missing_minor_type(self): |     def test_parse_missing_minor_type(self): | ||||||
|         eq = self.assertEqual |         eq = self.assertEqual | ||||||
|         msg = self._msgobj('msg_14.txt') |         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_maintype(), 'text') | ||||||
|         eq(msg.get_content_subtype(), 'plain') |         eq(msg.get_content_subtype(), 'plain') | ||||||
| 
 | 
 | ||||||
|  | @ -1531,7 +1541,7 @@ def test_valid_argument(self): | ||||||
|         m = Message() |         m = Message() | ||||||
|         m['Subject'] = subject |         m['Subject'] = subject | ||||||
|         r = MIMEMessage(m) |         r = MIMEMessage(m) | ||||||
|         eq(r.get_type(), 'message/rfc822') |         eq(r.get_content_type(), 'message/rfc822') | ||||||
|         payload = r.get_payload() |         payload = r.get_payload() | ||||||
|         unless(isinstance(payload, list)) |         unless(isinstance(payload, list)) | ||||||
|         eq(len(payload), 1) |         eq(len(payload), 1) | ||||||
|  | @ -1572,7 +1582,7 @@ def test_parse_message_rfc822(self): | ||||||
|         eq = self.assertEqual |         eq = self.assertEqual | ||||||
|         unless = self.failUnless |         unless = self.failUnless | ||||||
|         msg = self._msgobj('msg_11.txt') |         msg = self._msgobj('msg_11.txt') | ||||||
|         eq(msg.get_type(), 'message/rfc822') |         eq(msg.get_content_type(), 'message/rfc822') | ||||||
|         payload = msg.get_payload() |         payload = msg.get_payload() | ||||||
|         unless(isinstance(payload, list)) |         unless(isinstance(payload, list)) | ||||||
|         eq(len(payload), 1) |         eq(len(payload), 1) | ||||||
|  | @ -1586,12 +1596,12 @@ def test_dsn(self): | ||||||
|         unless = self.failUnless |         unless = self.failUnless | ||||||
|         # msg 16 is a Delivery Status Notification, see RFC 1894 |         # msg 16 is a Delivery Status Notification, see RFC 1894 | ||||||
|         msg = self._msgobj('msg_16.txt') |         msg = self._msgobj('msg_16.txt') | ||||||
|         eq(msg.get_type(), 'multipart/report') |         eq(msg.get_content_type(), 'multipart/report') | ||||||
|         unless(msg.is_multipart()) |         unless(msg.is_multipart()) | ||||||
|         eq(len(msg.get_payload()), 3) |         eq(len(msg.get_payload()), 3) | ||||||
|         # Subpart 1 is a text/plain, human readable section |         # Subpart 1 is a text/plain, human readable section | ||||||
|         subpart = msg.get_payload(0) |         subpart = msg.get_payload(0) | ||||||
|         eq(subpart.get_type(), 'text/plain') |         eq(subpart.get_content_type(), 'text/plain') | ||||||
|         eq(subpart.get_payload(), """\ |         eq(subpart.get_payload(), """\ | ||||||
| This report relates to a message you sent with the following header fields: | 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 |         # consists of two blocks of headers, represented by two nested Message | ||||||
|         # objects. |         # objects. | ||||||
|         subpart = msg.get_payload(1) |         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) |         eq(len(subpart.get_payload()), 2) | ||||||
|         # message/delivery-status should treat each block as a bunch of |         # message/delivery-status should treat each block as a bunch of | ||||||
|         # headers, i.e. a bunch of Message objects. |         # headers, i.e. a bunch of Message objects. | ||||||
|  | @ -1629,13 +1639,13 @@ def test_dsn(self): | ||||||
|         eq(dsn2.get_param('rfc822', header='final-recipient'), '') |         eq(dsn2.get_param('rfc822', header='final-recipient'), '') | ||||||
|         # Subpart 3 is the original message |         # Subpart 3 is the original message | ||||||
|         subpart = msg.get_payload(2) |         subpart = msg.get_payload(2) | ||||||
|         eq(subpart.get_type(), 'message/rfc822') |         eq(subpart.get_content_type(), 'message/rfc822') | ||||||
|         payload = subpart.get_payload() |         payload = subpart.get_payload() | ||||||
|         unless(isinstance(payload, list)) |         unless(isinstance(payload, list)) | ||||||
|         eq(len(payload), 1) |         eq(len(payload), 1) | ||||||
|         subsubpart = payload[0] |         subsubpart = payload[0] | ||||||
|         unless(isinstance(subsubpart, Message)) |         unless(isinstance(subsubpart, Message)) | ||||||
|         eq(subsubpart.get_type(), 'text/plain') |         eq(subsubpart.get_content_type(), 'text/plain') | ||||||
|         eq(subsubpart['message-id'], |         eq(subsubpart['message-id'], | ||||||
|            '<002001c144a6$8752e060$56104586@oxy.edu>') |            '<002001c144a6$8752e060$56104586@oxy.edu>') | ||||||
| 
 | 
 | ||||||
|  | @ -1706,16 +1716,16 @@ def test_default_type(self): | ||||||
|             fp.close() |             fp.close() | ||||||
|         container1 = msg.get_payload(0) |         container1 = msg.get_payload(0) | ||||||
|         eq(container1.get_default_type(), 'message/rfc822') |         eq(container1.get_default_type(), 'message/rfc822') | ||||||
|         eq(container1.get_type(), None) |         eq(container1.get_content_type(), 'message/rfc822') | ||||||
|         container2 = msg.get_payload(1) |         container2 = msg.get_payload(1) | ||||||
|         eq(container2.get_default_type(), 'message/rfc822') |         eq(container2.get_default_type(), 'message/rfc822') | ||||||
|         eq(container2.get_type(), None) |         eq(container2.get_content_type(), 'message/rfc822') | ||||||
|         container1a = container1.get_payload(0) |         container1a = container1.get_payload(0) | ||||||
|         eq(container1a.get_default_type(), 'text/plain') |         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) |         container2a = container2.get_payload(0) | ||||||
|         eq(container2a.get_default_type(), 'text/plain') |         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): |     def test_default_type_with_explicit_container_type(self): | ||||||
|         eq = self.assertEqual |         eq = self.assertEqual | ||||||
|  | @ -1726,16 +1736,16 @@ def test_default_type_with_explicit_container_type(self): | ||||||
|             fp.close() |             fp.close() | ||||||
|         container1 = msg.get_payload(0) |         container1 = msg.get_payload(0) | ||||||
|         eq(container1.get_default_type(), 'message/rfc822') |         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) |         container2 = msg.get_payload(1) | ||||||
|         eq(container2.get_default_type(), 'message/rfc822') |         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) |         container1a = container1.get_payload(0) | ||||||
|         eq(container1a.get_default_type(), 'text/plain') |         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) |         container2a = container2.get_payload(0) | ||||||
|         eq(container2a.get_default_type(), 'text/plain') |         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): |     def test_default_type_non_parsed(self): | ||||||
|         eq = self.assertEqual |         eq = self.assertEqual | ||||||
|  | @ -1750,9 +1760,9 @@ def test_default_type_non_parsed(self): | ||||||
|         subpart2 = MIMEMessage(subpart2a) |         subpart2 = MIMEMessage(subpart2a) | ||||||
|         container.attach(subpart1) |         container.attach(subpart1) | ||||||
|         container.attach(subpart2) |         container.attach(subpart2) | ||||||
|         eq(subpart1.get_type(), 'message/rfc822') |         eq(subpart1.get_content_type(), 'message/rfc822') | ||||||
|         eq(subpart1.get_default_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') |         eq(subpart2.get_default_type(), 'message/rfc822') | ||||||
|         neq(container.as_string(0), '''\ |         neq(container.as_string(0), '''\ | ||||||
| Content-Type: multipart/digest; boundary="BOUNDARY" | Content-Type: multipart/digest; boundary="BOUNDARY" | ||||||
|  | @ -1784,9 +1794,9 @@ def test_default_type_non_parsed(self): | ||||||
|         del subpart1['mime-version'] |         del subpart1['mime-version'] | ||||||
|         del subpart2['content-type'] |         del subpart2['content-type'] | ||||||
|         del subpart2['mime-version'] |         del subpart2['mime-version'] | ||||||
|         eq(subpart1.get_type(), None) |         eq(subpart1.get_content_type(), 'message/rfc822') | ||||||
|         eq(subpart1.get_default_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') |         eq(subpart2.get_default_type(), 'message/rfc822') | ||||||
|         neq(container.as_string(0), '''\ |         neq(container.as_string(0), '''\ | ||||||
| Content-Type: multipart/digest; boundary="BOUNDARY" | Content-Type: multipart/digest; boundary="BOUNDARY" | ||||||
|  | @ -1847,7 +1857,7 @@ def _idempotent(self, msg, text): | ||||||
|     def test_parse_text_message(self): |     def test_parse_text_message(self): | ||||||
|         eq = self.assertEquals |         eq = self.assertEquals | ||||||
|         msg, text = self._msgobj('msg_01.txt') |         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_maintype(), 'text') | ||||||
|         eq(msg.get_content_subtype(), 'plain') |         eq(msg.get_content_subtype(), 'plain') | ||||||
|         eq(msg.get_params()[1], ('charset', 'us-ascii')) |         eq(msg.get_params()[1], ('charset', 'us-ascii')) | ||||||
|  | @ -1859,7 +1869,7 @@ def test_parse_text_message(self): | ||||||
|     def test_parse_untyped_message(self): |     def test_parse_untyped_message(self): | ||||||
|         eq = self.assertEquals |         eq = self.assertEquals | ||||||
|         msg, text = self._msgobj('msg_03.txt') |         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_params(), None) | ||||||
|         eq(msg.get_param('charset'), None) |         eq(msg.get_param('charset'), None) | ||||||
|         self._idempotent(msg, text) |         self._idempotent(msg, text) | ||||||
|  | @ -1933,7 +1943,7 @@ def test_content_type(self): | ||||||
|         unless = self.failUnless |         unless = self.failUnless | ||||||
|         # Get a message object and reset the seek pointer for other tests |         # Get a message object and reset the seek pointer for other tests | ||||||
|         msg, text = self._msgobj('msg_05.txt') |         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 |         # Test the Content-Type: parameters | ||||||
|         params = {} |         params = {} | ||||||
|         for pk, pv in msg.get_params(): |         for pk, pv in msg.get_params(): | ||||||
|  | @ -1945,13 +1955,13 @@ def test_content_type(self): | ||||||
|         eq(len(msg.get_payload()), 3) |         eq(len(msg.get_payload()), 3) | ||||||
|         # Make sure the subparts are what we expect |         # Make sure the subparts are what we expect | ||||||
|         msg1 = msg.get_payload(0) |         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') |         eq(msg1.get_payload(), 'Yadda yadda yadda\n') | ||||||
|         msg2 = msg.get_payload(1) |         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') |         eq(msg2.get_payload(), 'Yadda yadda yadda\n') | ||||||
|         msg3 = msg.get_payload(2) |         msg3 = msg.get_payload(2) | ||||||
|         eq(msg3.get_type(), 'message/rfc822') |         eq(msg3.get_content_type(), 'message/rfc822') | ||||||
|         self.failUnless(isinstance(msg3, Message)) |         self.failUnless(isinstance(msg3, Message)) | ||||||
|         payload = msg3.get_payload() |         payload = msg3.get_payload() | ||||||
|         unless(isinstance(payload, list)) |         unless(isinstance(payload, list)) | ||||||
|  | @ -1965,7 +1975,7 @@ def test_parser(self): | ||||||
|         unless = self.failUnless |         unless = self.failUnless | ||||||
|         msg, text = self._msgobj('msg_06.txt') |         msg, text = self._msgobj('msg_06.txt') | ||||||
|         # Check some of the outer headers |         # 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 |         # Make sure the payload is a list of exactly one sub-Message, and that | ||||||
|         # that submessage has a type of text/plain |         # that submessage has a type of text/plain | ||||||
|         payload = msg.get_payload() |         payload = msg.get_payload() | ||||||
|  | @ -1973,7 +1983,7 @@ def test_parser(self): | ||||||
|         eq(len(payload), 1) |         eq(len(payload), 1) | ||||||
|         msg1 = payload[0] |         msg1 = payload[0] | ||||||
|         self.failUnless(isinstance(msg1, Message)) |         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)) |         self.failUnless(isinstance(msg1.get_payload(), str)) | ||||||
|         eq(msg1.get_payload(), '\n') |         eq(msg1.get_payload(), '\n') | ||||||
| 
 | 
 | ||||||
|  | @ -2058,13 +2068,19 @@ def test__all__(self): | ||||||
|         module = __import__('email') |         module = __import__('email') | ||||||
|         all = module.__all__ |         all = module.__all__ | ||||||
|         all.sort() |         all.sort() | ||||||
|         self.assertEqual(all, ['Charset', 'Encoders', 'Errors', 'Generator', |         self.assertEqual(all, [ | ||||||
|                                'Header', 'Iterators', 'MIMEAudio', 'MIMEBase', |             # Old names | ||||||
|                                'MIMEImage', 'MIMEMessage', 'MIMEMultipart', |             'Charset', 'Encoders', 'Errors', 'Generator', | ||||||
|                                'MIMENonMultipart', 'MIMEText', 'Message', |             'Header', 'Iterators', 'MIMEAudio', 'MIMEBase', | ||||||
|                                'Parser', 'Utils', 'base64MIME', |             'MIMEImage', 'MIMEMessage', 'MIMEMultipart', | ||||||
|                                'message_from_file', 'message_from_string', |             'MIMENonMultipart', 'MIMEText', 'Message', | ||||||
|                                'quopriMIME']) |             'Parser', 'Utils', 'base64MIME', | ||||||
|  |             # 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): |     def test_formatdate(self): | ||||||
|         now = time.time() |         now = time.time() | ||||||
|  | @ -2356,7 +2372,7 @@ def test_header_parser(self): | ||||||
|             fp.close() |             fp.close() | ||||||
|         eq(msg['from'], 'ppp-request@zzz.org') |         eq(msg['from'], 'ppp-request@zzz.org') | ||||||
|         eq(msg['to'], 'ppp@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.failIf(msg.is_multipart()) | ||||||
|         self.failUnless(isinstance(msg.get_payload(), str)) |         self.failUnless(isinstance(msg.get_payload(), str)) | ||||||
| 
 | 
 | ||||||
|  | @ -2405,10 +2421,10 @@ def test_crlf_separation(self): | ||||||
|             fp.close() |             fp.close() | ||||||
|         eq(len(msg.get_payload()), 2) |         eq(len(msg.get_payload()), 2) | ||||||
|         part1 = msg.get_payload(0) |         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') |         eq(part1.get_payload(), 'Simple email with attachment.\r\n\r\n') | ||||||
|         part2 = msg.get_payload(1) |         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): |     def test_multipart_digest_with_extra_mime_headers(self): | ||||||
|         eq = self.assertEqual |         eq = self.assertEqual | ||||||
|  | @ -2427,21 +2443,21 @@ def test_multipart_digest_with_extra_mime_headers(self): | ||||||
|         eq(msg.is_multipart(), 1) |         eq(msg.is_multipart(), 1) | ||||||
|         eq(len(msg.get_payload()), 2) |         eq(len(msg.get_payload()), 2) | ||||||
|         part1 = msg.get_payload(0) |         part1 = msg.get_payload(0) | ||||||
|         eq(part1.get_type(), 'message/rfc822') |         eq(part1.get_content_type(), 'message/rfc822') | ||||||
|         eq(part1.is_multipart(), 1) |         eq(part1.is_multipart(), 1) | ||||||
|         eq(len(part1.get_payload()), 1) |         eq(len(part1.get_payload()), 1) | ||||||
|         part1a = part1.get_payload(0) |         part1a = part1.get_payload(0) | ||||||
|         eq(part1a.is_multipart(), 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') |         neq(part1a.get_payload(), 'message 1\n') | ||||||
|         # next message/rfc822 |         # next message/rfc822 | ||||||
|         part2 = msg.get_payload(1) |         part2 = msg.get_payload(1) | ||||||
|         eq(part2.get_type(), 'message/rfc822') |         eq(part2.get_content_type(), 'message/rfc822') | ||||||
|         eq(part2.is_multipart(), 1) |         eq(part2.is_multipart(), 1) | ||||||
|         eq(len(part2.get_payload()), 1) |         eq(len(part2.get_payload()), 1) | ||||||
|         part2a = part2.get_payload(0) |         part2a = part2.get_payload(0) | ||||||
|         eq(part2a.is_multipart(), 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') |         neq(part2a.get_payload(), 'message 2\n') | ||||||
| 
 | 
 | ||||||
|     def test_three_lines(self): |     def test_three_lines(self): | ||||||
|  | @ -2723,6 +2739,11 @@ def test_body_encode(self): | ||||||
|         c = Charset('fake') |         c = Charset('fake') | ||||||
|         eq('hello w\xf6rld', c.body_encode('hello w\xf6rld')) |         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. | # Test multilingual MIME headers. | ||||||
|  |  | ||||||
|  | @ -10,6 +10,13 @@ | ||||||
| from email.Header import Header, decode_header | from email.Header import Header, decode_header | ||||||
| from email.Message import Message | 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): | 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 | # Author: Barry Warsaw | ||||||
| # Contact: email-sig@python.org | # Contact: email-sig@python.org | ||||||
| 
 | 
 | ||||||
| """Miscellaneous utilities.""" | """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 os | ||||||
| import re | import re | ||||||
| import time | import time | ||||||
|  | @ -24,7 +39,7 @@ | ||||||
| from quopri import decodestring as _qdecode | from quopri import decodestring as _qdecode | ||||||
| 
 | 
 | ||||||
| # Intrapackage imports | # Intrapackage imports | ||||||
| from email.Encoders import _bencode, _qencode | from email.encoders import _bencode, _qencode | ||||||
| 
 | 
 | ||||||
| COMMASPACE = ', ' | COMMASPACE = ', ' | ||||||
| EMPTYSTRING = '' | EMPTYSTRING = '' | ||||||
|  | @ -170,7 +170,7 @@ def test_others(self): | ||||||
|         cm('pydoc') |         cm('pydoc') | ||||||
| 
 | 
 | ||||||
|         # Tests for modules inside packages |         # Tests for modules inside packages | ||||||
|         cm('email.Parser') |         cm('email.parser') | ||||||
|         cm('test.test_pyclbr') |         cm('test.test_pyclbr') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Barry Warsaw
						Barry Warsaw