19.1.6. "email.contentmanager": Managing MIME Content
*****************************************************

Note: The contentmanager module has been included in the standard
  library on a *provisional basis*. Backwards incompatible changes (up
  to and including removal of the module) may occur if deemed
  necessary by the core developers.

New in version 3.4: as a *provisional module*.

The "message" module provides a class that can represent an arbitrary
email message.  That basic message model has a useful and flexible
API, but it provides only a lower-level API for interacting with the
generic parts of a message (the headers, generic header parameters,
and the payload, which may be a list of sub-parts).  This module
provides classes and tools that provide an enhanced and extensible API
for dealing with various specific types of content, including the
ability to retrieve the content of the message as a specialized object
type rather than as a simple bytes object.  The module automatically
takes care of the RFC-specified MIME details (required headers and
parameters, etc.) for the certain common content types content
properties, and support for additional types can be added by an
application using the extension mechanisms.

This module defines the eponymous “Content Manager” classes.  The base
"ContentManager" class defines an API for registering content
management functions which extract data from "Message" objects or
insert data and headers into "Message" objects, thus providing a way
of converting between "Message" objects containing data and other
representations of that data (Python data types, specialized Python
objects, external files, etc).  The module also defines one concrete
content manager: "raw_data_manager" converts between MIME content
types and "str" or "bytes" data.  It also provides a convenient API
for managing the MIME parameters when inserting content into
"Message"s.  It also handles inserting and extracting "Message"
objects when dealing with the "message/rfc822" content type.

Another part of the enhanced interface is subclasses of "Message" that
provide new convenience API functions, including convenience methods
for calling the Content Managers derived from this module.

Note: Although "EmailMessage" and "MIMEPart" are currently
  documented in this module because of the provisional nature of the
  code, the implementation lives in the "email.message" module.

class email.message.EmailMessage(policy=default)

   If *policy* is specified (it must be an instance of a "policy"
   class) use the rules it specifies to udpate and serialize the
   representation of the message.  If *policy* is not set, use the
   "default" policy, which follows the rules of the email RFCs except
   for line endings (instead of the RFC mandated "\r\n", it uses the
   Python standard "\n" line endings).  For more information see the
   "policy" documentation.

   This class is a subclass of "Message".  It adds the following
   methods:

   is_attachment()

      Return "True" if there is a *Content-Disposition* header and its
      (case insensitive) value is "attachment", "False" otherwise.

      Changed in version 3.4.2: is_attachment is now a method instead
      of a property, for consistency with "is_multipart()".

   get_body(preferencelist=('related', 'html', 'plain'))

      Return the MIME part that is the best candidate to be the “body”
      of the message.

      *preferencelist* must be a sequence of strings from the set
      "related", "html", and "plain", and indicates the order of
      preference for the content type of the part returned.

      Start looking for candidate matches with the object on which the
      "get_body" method is called.

      If "related" is not included in *preferencelist*, consider the
      root part (or subpart of the root part) of any related
      encountered as a candidate if the (sub-)part matches a
      preference.

      When encountering a "multipart/related", check the "start"
      parameter and if a part with a matching *Content-ID* is found,
      consider only it when looking for candidate matches.  Otherwise
      consider only the first (default root) part of the
      "multipart/related".

      If a part has a *Content-Disposition* header, only consider the
      part a candidate match if the value of the header is "inline".

      If none of the candidates matches any of the preferences in
      *preferneclist*, return "None".

      Notes: (1) For most applications the only *preferencelist*
      combinations that really make sense are "('plain',)", "('html',
      'plain')", and the default, "('related', 'html', 'plain')".  (2)
      Because matching starts with the object on which "get_body" is
      called, calling "get_body" on a "multipart/related" will return
      the object itself unless *preferencelist* has a non-default
      value. (3) Messages (or message parts) that do not specify a
      *Content-Type* or whose *Content-Type* header is invalid will be
      treated as if they are of type "text/plain", which may
      occasionally cause "get_body" to return unexpected results.

   iter_attachments()

      Return an iterator over all of the parts of the message that are
      not candidate “body” parts.  That is, skip the first occurrence
      of each of "text/plain", "text/html", "multipart/related", or
      "multipart/alternative" (unless they are explicitly marked as
      attachments via *Content-Disposition: attachment*), and return
      all remaining parts.  When applied directly to a
      "multipart/related", return an iterator over the all the related
      parts except the root part (ie: the part pointed to by the
      "start" parameter, or the first part if there is no "start"
      parameter or the "start" parameter doesn’t match the *Content-
      ID* of any of the parts).  When applied directly to a
      "multipart/alternative" or a non-"multipart", return an empty
      iterator.

   iter_parts()

      Return an iterator over all of the immediate sub-parts of the
      message, which will be empty for a non-"multipart".  (See also
      "walk()".)

   get_content(*args, content_manager=None, **kw)

      Call the "get_content" method of the *content_manager*, passing
      self as the message object, and passing along any other
      arguments or keywords as additional arguments.  If
      *content_manager* is not specified, use the "content_manager"
      specified by the current "policy".

   set_content(*args, content_manager=None, **kw)

      Call the "set_content" method of the *content_manager*, passing
      self as the message object, and passing along any other
      arguments or keywords as additional arguments.  If
      *content_manager* is not specified, use the "content_manager"
      specified by the current "policy".

   make_related(boundary=None)

      Convert a non-"multipart" message into a "multipart/related"
      message, moving any existing *Content-* headers and payload into
      a (new) first part of the "multipart".  If *boundary* is
      specified, use it as the boundary string in the multipart,
      otherwise leave the boundary to be automatically created when it
      is needed (for example, when the message is serialized).

   make_alternative(boundary=None)

      Convert a non-"multipart" or a "multipart/related" into a
      "multipart/alternative", moving any existing *Content-* headers
      and payload into a (new) first part of the "multipart".  If
      *boundary* is specified, use it as the boundary string in the
      multipart, otherwise leave the boundary to be automatically
      created when it is needed (for example, when the message is
      serialized).

   make_mixed(boundary=None)

      Convert a non-"multipart", a "multipart/related", or a
      "multipart-alternative" into a "multipart/mixed", moving any
      existing *Content-* headers and payload into a (new) first part
      of the "multipart".  If *boundary* is specified, use it as the
      boundary string in the multipart, otherwise leave the boundary
      to be automatically created when it is needed (for example, when
      the message is serialized).

   add_related(*args, content_manager=None, **kw)

      If the message is a "multipart/related", create a new message
      object, pass all of the arguments to its "set_content()" method,
      and "attach()" it to the "multipart".  If the message is a
      non-"multipart", call "make_related()" and then proceed as
      above.  If the message is any other type of "multipart", raise a
      "TypeError". If *content_manager* is not specified, use the
      "content_manager" specified by the current "policy". If the
      added part has no *Content-Disposition* header, add one with the
      value "inline".

   add_alternative(*args, content_manager=None, **kw)

      If the message is a "multipart/alternative", create a new
      message object, pass all of the arguments to its "set_content()"
      method, and "attach()" it to the "multipart".  If the message is
      a non-"multipart" or "multipart/related", call
      "make_alternative()" and then proceed as above.  If the message
      is any other type of "multipart", raise a "TypeError". If
      *content_manager* is not specified, use the "content_manager"
      specified by the current "policy".

   add_attachment(*args, content_manager=None, **kw)

      If the message is a "multipart/mixed", create a new message
      object, pass all of the arguments to its "set_content()" method,
      and "attach()" it to the "multipart".  If the message is a
      non-"multipart", "multipart/related", or
      "multipart/alternative", call "make_mixed()" and then proceed as
      above. If *content_manager* is not specified, use the
      "content_manager" specified by the current "policy".  If the
      added part has no *Content-Disposition* header, add one with the
      value "attachment".  This method can be used both for explicit
      attachments (*Content-Disposition: attachment* and "inline"
      attachments (*Content-Disposition: inline*), by passing
      appropriate options to the "content_manager".

   clear()

      Remove the payload and all of the headers.

   clear_content()

      Remove the payload and all of the "Content-" headers, leaving
      all other headers intact and in their original order.

class email.message.MIMEPart(policy=default)

   This class represents a subpart of a MIME message.  It is identical
   to "EmailMessage", except that no *MIME-Version* headers are added
   when "set_content()" is called, since sub-parts do not need their
   own *MIME-Version* headers.

class email.contentmanager.ContentManager

   Base class for content managers.  Provides the standard registry
   mechanisms to register converters between MIME content and other
   representations, as well as the "get_content" and "set_content"
   dispatch methods.

   get_content(msg, *args, **kw)

      Look up a handler function based on the "mimetype" of *msg* (see
      next paragraph), call it, passing through all arguments, and
      return the result of the call.  The expectation is that the
      handler will extract the payload from *msg* and return an object
      that encodes information about the extracted data.

      To find the handler, look for the following keys in the
      registry, stopping with the first one found:

         * the string representing the full MIME type
           ("maintype/subtype")

         * the string representing the "maintype"

         * the empty string

      If none of these keys produce a handler, raise a "KeyError" for
      the full MIME type.

   set_content(msg, obj, *args, **kw)

      If the "maintype" is "multipart", raise a "TypeError"; otherwise
      look up a handler function based on the type of *obj* (see next
      paragraph), call "clear_content()" on the *msg*, and call the
      handler function, passing through all arguments.  The
      expectation is that the handler will transform and store *obj*
      into *msg*, possibly making other changes to *msg* as well, such
      as adding various MIME headers to encode information needed to
      interpret the stored data.

      To find the handler, obtain the type of *obj* ("typ =
      type(obj)"), and look for the following keys in the registry,
      stopping with the first one found:

         * the type itself ("typ")

         * the type’s fully qualified name ("typ.__module__ + '.' +
           typ.__qualname__").

         * the type’s qualname ("typ.__qualname__")

         * the type’s name ("typ.__name__").

      If none of the above match, repeat all of the checks above for
      each of the types in the *MRO* ("typ.__mro__").  Finally, if no
      other key yields a handler, check for a handler for the key
      "None".  If there is no handler for "None", raise a "KeyError"
      for the fully qualified name of the type.

      Also add a *MIME-Version* header if one is not present (see also
      "MIMEPart").

   add_get_handler(key, handler)

      Record the function *handler* as the handler for *key*.  For the
      possible values of *key*, see "get_content()".

   add_set_handler(typekey, handler)

      Record *handler* as the function to call when an object of a
      type matching *typekey* is passed to "set_content()".  For the
      possible values of *typekey*, see "set_content()".


19.1.6.1. Content Manager Instances
===================================

Currently the email package provides only one concrete content
manager, "raw_data_manager", although more may be added in the future.
"raw_data_manager" is the "content_manager" provided by "EmailPolicy"
and its derivatives.

email.contentmanager.raw_data_manager

   This content manager provides only a minimum interface beyond that
   provided by "Message" itself:  it deals only with text, raw byte
   strings, and "Message" objects.  Nevertheless, it provides
   significant advantages compared to the base API: "get_content" on a
   text part will return a unicode string without the application
   needing to manually decode it, "set_content" provides a rich set of
   options for controlling the headers added to a part and controlling
   the content transfer encoding, and it enables the use of the
   various "add_" methods, thereby simplifying the creation of
   multipart messages.

   email.contentmanager.get_content(msg, errors='replace')

      Return the payload of the part as either a string (for "text"
      parts), a "EmailMessage" object (for "message/rfc822" parts), or
      a "bytes" object (for all other non-multipart types).  Raise a
      "KeyError" if called on a "multipart".  If the part is a "text"
      part and *errors* is specified, use it as the error handler when
      decoding the payload to unicode.  The default error handler is
      "replace".

   email.contentmanager.set_content(msg, <'str'>, subtype="plain", charset='utf-8'                     cte=None, disposition=None, filename=None, cid=None, params=None, headers=None)
   email.contentmanager.set_content(msg, <'bytes'>, maintype, subtype, cte="base64", disposition=None, filename=None, cid=None, params=None, headers=None)
   email.contentmanager.set_content(msg, <'Message'>, cte=None, disposition=None, filename=None, cid=None, params=None, headers=None)
   email.contentmanager.set_content(msg, <'list'>, subtype='mixed', disposition=None, filename=None, cid=None, params=None, headers=None)

      Add headers and payload to *msg*:

      Add a *Content-Type* header with a "maintype/subtype" value.

         * For "str", set the MIME "maintype" to "text", and set the
           subtype to *subtype* if it is specified, or "plain" if it
           is not.

         * For "bytes", use the specified *maintype* and *subtype*,
           or raise a "TypeError" if they are not specified.

         * For "Message" objects, set the maintype to "message", and
           set the subtype to *subtype* if it is specified or "rfc822"
           if it is not.  If *subtype* is "partial", raise an error
           ("bytes" objects must be used to construct
           "message/partial" parts).

         * For *<’list’>*, which should be a list of "Message"
           objects, set the "maintype" to "multipart", and the
           "subtype" to *subtype* if it is specified, and "mixed" if
           it is not.  If the message parts in the *<’list’>* have
           *MIME-Version* headers, remove them.

      If *charset* is provided (which is valid only for "str"), encode
      the string to bytes using the specified character set.  The
      default is "utf-8".  If the specified *charset* is a known alias
      for a standard MIME charset name, use the standard charset
      instead.

      If *cte* is set, encode the payload using the specified content
      transfer encoding, and set the *Content-Transfer-Endcoding*
      header to that value.  For "str" objects, if it is not set use
      heuristics to determine the most compact encoding.  Possible
      values for *cte* are "quoted-printable", "base64", "7bit",
      "8bit", and "binary". If the input cannot be encoded in the
      specified encoding (eg: "7bit"), raise a "ValueError".  For
      "Message", per **RFC 2046**, raise an error if a *cte* of
      "quoted-printable" or "base64" is requested for *subtype*
      "rfc822", and for any *cte* other than "7bit" for *subtype*
      "external-body".  For "message/rfc822", use "8bit" if *cte* is
      not specified.  For all other values of *subtype*, use "7bit".

      Note: A *cte* of "binary" does not actually work correctly
        yet. The "Message" object as modified by "set_content" is
        correct, but "BytesGenerator" does not serialize it correctly.

      If *disposition* is set, use it as the value of the *Content-
      Disposition* header.  If not specified, and *filename* is
      specified, add the header with the value "attachment". If it is
      not specified and *filename* is also not specified, do not add
      the header.  The only valid values for *disposition* are
      "attachment" and "inline".

      If *filename* is specified, use it as the value of the
      "filename" parameter of the *Content-Disposition* header.  There
      is no default.

      If *cid* is specified, add a *Content-ID* header with *cid* as
      its value.

      If *params* is specified, iterate its "items" method and use the
      resulting "(key, value)" pairs to set additional parameters on
      the *Content-Type* header.

      If *headers* is specified and is a list of strings of the form
      "headername: headervalue" or a list of "header" objects
      (distinguised from strings by having a "name" attribute), add
      the headers to *msg*.
