# `email.message`: Representando un mensaje de correo electrónico

Código fuente: Lib/email/message.py

Nuevo en la versión 3.6: 1

La clase central en el paquete de `email` es la clase `EmailMessage`, importada desde el módulo `email.message`. Esta es la clase base para el modelo de objeto `email`. `EmailMessage` provee la funcionalidad clave para configurar y consultar los headers, para acceder al cuerpo del mensaje, y para crear o modificar la estructura del mensaje.

Un mensaje de e-mail consiste en headers y un payload (al que también nos referimos como content). Headers como RFC 5322 o RFC 6532 son nombres de campos de estilo y valores, donde el nombre y valor están separados por un “:”. Los dos puntos no son parte ni del nombre ni del valor. El payload puede ser un simple mensaje, un objeto binario, o una secuencia estructurada de sub-mensajes, cada uno con su propio conjunto de headers y su propio payload. El último tipo de payload es indicado por el mensaje con un MIME como multipart/* o message/rfc822 .

El modelo conceptual provisto por un objeto `EmailMessage` es el de un diccionario ordenado de headers emparejados con un payload que representa al cuerpo del mensaje RFC 5322, que podría ser una lista de objetos sub-`EmailMessage`. Además de los métodos normales de diccionario para acceder a los headers y valores, tiene métodos para acceder a información especializada desde los headers (por ejemplo, el tipo de contenido MIME), para operar en el payload, generar una versión serializada del mensaje, y recorrer recursivamente el árbol de objetos.

The `EmailMessage` dictionary-like interface is indexed by the header names, which must be ASCII values. The values of the dictionary are strings with some extra methods. Headers are stored and returned in case-preserving form, but field names are matched case-insensitively. Unlike a real dict, there is an ordering to the keys, and there can be duplicate keys. Additional methods are provided for working with headers that have duplicate keys.

El payload es un objeto de cadena de caracteres o bytes, en el caso de objetos de mensaje simples, o una lista de objetos `EmailMessage`, para documentos de contenedor MIME como multipart/* y objetos de mensaje message/rfc822.

class `email.message.``EmailMessage`(policy=default)

  Si se especifica policy, use las reglas especificadas para actualizar y serializar la representación del mensaje. Si policy no es establecida, use `default`, que sigue las reglas RFC de email excepto para el fin de línea(en lugar del RFC `\r\n`, usa los finales estándar de Python `\n` como final de línea). Para más información ve a la documentación del `policy`.

  `as_string`(unixfrom=False, maxheaderlen=None, policy=None)

    Retorna el mensaje entero como cadena de caracteres. Cuando la opción unixform es verdadera, el header está incluido en la cadena de caracteres retornada. unixform está predeterminado con valor `False`. Por compatibilidad con versiones anteriores, la base `Message`, la case maxheaderlen es aceptada pero con valor `None` como predeterminado, por lo que la longitud de línea se controla mediante `max_line_length`. El argumento policy puede ser usado para anular el valor predeterminado obtenido de la instancia del mensaje. Esto puede ser usado para controlar parte del formato producido por el método, ya que el policy especificado pasará a `Generator`.

    Aplanar el mensaje puede acarrear cambios en `EmailMessage` si es necesario rellenar los valores predeterminados para completar la transformación a una cadena de caracteres (por ejemplo, se pueden generar o modificar límites MIME).

    Tenga en cuenta que este método se proporciona como una comodidad y quizás no sea la forma más eficiente de serializar mensajes en su aplicación, especialmente si estás tratando con múltiples mensajes. Consulte `Generator` por una API más flexible para serializar mensajes. No olvide también que este método está restringido a producir mensajes serializados como «7 bit clean» cuando `utf8` es `False`, que es el valor predeterminado.

    Distinto en la versión 3.6: el comportamiento predeterminado cuando maxheaderlen no está especificado cambió de 0 al valor de max_line_length .

  `__str__`()

    Equivalente a `as_string(policy=self.policy.clone(utf8=True))`. Permite `str(msg)` para producir un string que contenga un mensaje serializado en un formato legible.

    Distinto en la versión 3.4: el método se cambió para usar `utf8=True`, produciendo así un RFC 6531 como representación del mensaje, en vez de ser un alias de `as_string()`.

  `as_bytes`(unixfrom=False, policy=None)

    Retorna el mensaje plano como un objeto de bytes. Cuando unixform es verdadero, el header es incluido en la cadena de caracteres retornada. El valor predeterminado de unixform es `False`. El argumento policy puede ser usado para sobreescribir el valor predeterminado obtenido de la instancia del mensaje. Esto puede ser usado para controlar parte del formato producido por el método, ya que el policy especificado pasará a `Generator`.

    Aplanar el mensaje puede acarrear cambios en `EmailMessage` si es necesario rellenar los valores predeterminados para completar la transformación a una cadena de caracteres (por ejemplo, se pueden generar o modificar límites MIME).

    Tenga en cuenta que este método se proporciona como una comodidad y quizás no sea la forma más eficiente de serializar mensajes en su aplicación, especialmente si estas tratando con múltiples mensajes. Consulte `Generator` por una API más flexible para serializar mensajes.

  `__bytes__`()

    Equivalente a `as_bytes()`. Permite `bytes(msg)` para producir un objeto byte que contenga el mensaje serializado.

  `is_multipart`()

    Retorna `True` si el payload del mensaje es una lista de objetos de sub-`EmailMessage`, de otra manera retorna `False`. Cuando `is_multipart()` retorna `False`, el payload deberá ser un objeto cadena de caracteres (que podría ser un payload binario codificado con CTE). Note que si `is_multipart()` retorna `True` no necesariamente significa que «msg.get_content_maintype() == “multipart”» retornará `True`. Por ejemplo, `is_multipart` retornará `True` cuando la `EmailMessage` sea del tipo `message/rfc822`.

  `set_unixfrom`(unixfrom)

    Configura la cabecera del mensaje a unixform, que debería ser una cadena de caracteres. (Consulte `mboxMessage` para una descripción de este header)

  `get_unixfrom`()

    Retorna la cabecera del mensaje. Predeterminado `None` si la cabecera no ha sido configurada.

  Los siguientes métodos implementan el mapeo como una interfaz para acceder al header del mensaje. Tenga en cuenta que hay algunas diferencias semánticas entre esos métodos y una interfaz de mapeo normal(es decir, diccionario). Por ejemplo, en un diccionario no hay claves duplicadas, pero pueden haber headers duplicados. Además, en los diccionarios no hay un orden garantizado para las claves retornadas por `keys()`, pero en un objeto `EmailMessage`, los headers siempre regresan en orden de aparición en el mensaje original, o en el que fueron agregados luego. Cualquier header borrado y vuelto a añadir siempre se agrega al final de la lista.

  Estas diferencias semánticas son intencionales y están sesgadas hacia la conveniencia en los casos de uso más comunes.

  Note que en todos los casos, cualquier header presente en el mensaje no se incluye en la interfaz de mapeo.

  `__len__`()

    Retorna el número total de headers, incluidos los duplicados.

  `__contains__`(name)

    Retorna `True` si el objeto del mensaje tiene un campo llamado “nombre”. La comparación se realiza sin tener en cuenta mayúsculas o minúsculas y “nombre” no incluye “:”. Se utiliza para el operador `in` Por ejemplo:

        if 'message-id' in myMessage:
           print('Message-ID:', myMessage['message-id'])

  `__getitem__`(name)

    Retorna el valor del header nombrado. name no incluye el separador de dos puntos, “:”. Si el header se pierde, regresa `None`, un `KeyError` no se genera nunca.

    Tenga en cuenta que si el campo nombrado aparece más de una vez en el header del mensaje, esa cantidad de veces el valor regresado será indefinido. Use el método `get_all()` para obtener los valores de todos los headers existentes llamados name.

    Usando el standard non-“compat32”, el valor regresado es una instancia de una subclase de `email.headerregistry.BaseHeader`.

  `__setitem__`(name, val)

    Agrega un header al mensaje con un campo “nombre” y un valor “val”. El campo se agrega al final de los headers existentes en el mensaje.

    Tenga en cuenta que esto no sobrescribe ni borra ningún header con el mismo nombre. Si quiere asegurarse de que el nuevo header es el único en el mensaje con el campo “nombre”, borre el campo primero, por ejemplo:

        del msg['subject']
        msg['subject'] = 'Python roolz!'

    Si el `policy` define ciertos headers para ser únicos(como lo hace el standard), este método puede generar un `ValueError` cuando se intenta asignar un valor a un header preexistente. Este comportamiento es intencional por consistencia, pero no dependa de ello, ya que podemos optar por hacer que tales asignaciones eliminen el header en el futuro.

  `__delitem__`(name)

    Elimine todas las apariciones del campo “nombre” de los headers del mensaje. No se genera ninguna excepción si el campo nombrado no está presente en los encabezados.

  `keys`()

    Retorna una lista de los nombres de todos los campos del header del mensaje.

  `values`()

    Retorna una lista de todos los valores de los campos del mensaje.

  `items`()

    Retorna una lista de 2 tuplas que contienen todos los campos header y value del mensaje.

  `get`(name, failobj=None)

    Retorna el valor del header nombrado. Esto es idéntico a `__getitem__()` excepto si el opcional failobj regresado en el header nombrado no se encuentra(failobj es por defecto `None`).

  Aquí hay algunos métodos adicionales útiles relacionados con el header:

  `get_all`(name, failobj=None)

    Retorna una lista de todos los valores para el campo nombre. Si no se nombran tales headers en el mensaje, regresa failobj (por defecto `None`)

  `add_header`(_name, _value, **_params)

    Configuración extendida de headers. Este método es similar a `__setitem__()`, excepto que se pueden proporcionar parámetros de header adicionales como argumentos de palabras clave.

    Por cada ítem en los parámetros del diccionario _params, la clave se toma como el nombre del parámetro, con barra baja (“_”) convertidos a guiones (“-“) (ya que en Python no se permiten “-“ como identificadores). Normalmente, el parámetro debe ser añadido como `key='value'` a menos que el valor sea `None`, en ese caso solo la clave debe ser añadida.

    Si el valor contiene caracteres no-ASCII, el charset y el lenguaje deben ser controlados especificando el valor como una triple tupla en formato `(CHARSET, LANGUAJE, VALUE)`, donde `CHARSET` es una string llamando al charset usado para codificar el valor, `LANGUAJE` generalmente se establece en `None` o en una cadena de caracteres vacía (consulte RFC 2231 para más opciones), y `VALUE` es el valor de la cadena de caracteres que contiene puntos de código no-ASCII. Si la triple tupla no pasa y el valor contiene caracteres no-ASCII, es automáticamente codificada en formato RFC 2231, usando `CHARSET` de `utf-8` y `LANGUAJE` `None`.

    Aquí hay un ejemplo:

        msg.add_header('Content-Disposition', 'attachment', filename='bud.gif')

    Esto agregará un header que se ve como:

        Content-Disposition: attachment; filename="bud.gif"

    Un ejemplo de la interfaz extendida con caracteres no-ASCII:

        msg.add_header('Content-Disposition', 'attachment',
                       filename=('iso-8859-1', '', 'Fußballer.ppt'))

  `replace_header`(_name, _value)

    Reemplaza un header. Reemplaza el primer header encontrado en el mensaje que coincida con _name, conservando el orden de header y uso de minúsculas (y mayúsculas) del nombre de campo del header original. Si no hay coincidencia, se lanzará un `KeyError`.

  `get_content_type`()

    Retorna el tipo de contenido del mensaje, pasado a minúsculas de la forma maintype/subtype. Si no hay header llamado Content-Type en el mensaje, regresa el valor de `get_default_type()`. Si Content-Type no es válido, retorna `text/plain`.

    (According to RFC 2045, messages always have a default type, `get_content_type()` will always return a value. RFC 2045 defines a message’s default type to be text/plain unless it appears inside a multipart/digest container, in which case it would be message/rfc822. If the Content-Type header has an invalid type specification, RFC 2045 mandates that the default type be text/plain.)

  `get_content_maintype`()

    Return the message’s main content type. This is the maintype part of the string returned by `get_content_type()`.

  `get_content_subtype`()

    Return the message’s sub-content type. This is the subtype part of the string returned by `get_content_type()`.

  `get_default_type`()

    Return the default content type. Most messages have a default content type of text/plain, except for messages that are subparts of multipart/digest containers. Such subparts have a default content type of message/rfc822.

  `set_default_type`(ctype)

    Set the default content type. ctype should either be text/plain or message/rfc822, although this is not enforced. The default content type is not stored in the Content-Type header, so it only affects the return value of the `get_content_type` methods when no Content-Type header is present in the message.

  `set_param`(param, value, header='Content-Type', requote=True, charset=None, language='', replace=False)

    Set a parameter in the Content-Type header. If the parameter already exists in the header, replace its value with value. When header is `Content-Type` (the default) and the header does not yet exist in the message, add it, set its value to text/plain, and append the new parameter value. Optional header specifies an alternative header to Content-Type.

    If the value contains non-ASCII characters, the charset and language may be explicitly specified using the optional charset and language parameters. Optional language specifies the RFC 2231 language, defaulting to the empty string. Both charset and language should be strings. The default is to use the `utf8` charset and `None` for the language.

    If replace is `False` (the default) the header is moved to the end of the list of headers. If replace is `True`, the header will be updated in place.

    El uso del parámetro requote con objetos `EmailMessage` está obsoleto.

    Note that existing parameter values of headers may be accessed through the `params` attribute of the header value (for example, `msg['Content-Type'].params['charset']`).

    Distinto en la versión 3.4: Se agregó la palabra clave `replace`.

  `del_param`(param, header='content-type', requote=True)

    Remove the given parameter completely from the Content-Type header. The header will be re-written in place without the parameter or its value. Optional header specifies an alternative to Content-Type.

    El uso del parámetro requote con objetos `EmailMessage` está obsoleto.

  `get_filename`(failobj=None)

    Return the value of the `filename` parameter of the Content-Disposition header of the message. If the header does not have a `filename` parameter, this method falls back to looking for the `name` parameter on the Content-Type header. If neither is found, or the header is missing, then failobj is returned. The returned string will always be unquoted as per `email.utils.unquote()`.

  `get_boundary`(failobj=None)

    Return the value of the `boundary` parameter of the Content-Type header of the message, or failobj if either the header is missing, or has no `boundary` parameter. The returned string will always be unquoted as per `email.utils.unquote()`.

  `set_boundary`(boundary)

    Set the `boundary` parameter of the Content-Type header to boundary. `set_boundary()` will always quote boundary if necessary. A `HeaderParseError` is raised if the message object has no Content-Type header.

    Note that using this method is subtly different from deleting the old Content-Type header and adding a new one with the new boundary via `add_header()`, because `set_boundary()` preserves the order of the Content-Type header in the list of headers.

  `get_content_charset`(failobj=None)

    Return the `charset` parameter of the Content-Type header, coerced to lower case. If there is no Content-Type header, or if that header has no `charset` parameter, failobj is returned.

  `get_charsets`(failobj=None)

    Return a list containing the character set names in the message. If the message is a multipart, then the list will contain one element for each subpart in the payload, otherwise, it will be a list of length 1.

    Each item in the list will be a string which is the value of the `charset` parameter in the Content-Type header for the represented subpart. If the subpart has no Content-Type header, no `charset` parameter, or is not of the text main MIME type, then that item in the returned list will be failobj.

  `is_attachment`()

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

    Distinto en la versión 3.4.2: is_attachment is now a method instead of a property, for consistency with `is_multipart()`.

  `get_content_disposition`()

    Return the lowercased value (without parameters) of the message’s Content-Disposition header if it has one, or `None`. The possible values for this method are inline, attachment or `None` if the message follows RFC 2183.

    Nuevo en la versión 3.5.

  Los siguientes métodos se refieren a interrogar y manipular el contenido (payload) del mensaje.

  `walk`()

    The `walk()` method is an all-purpose generator which can be used to iterate over all the parts and subparts of a message object tree, in depth-first traversal order. You will typically use `walk()` as the iterator in a `for` loop; each iteration returns the next subpart.

    Aquí hay un ejemplo que imprime el tipo MIME de cada parte de una estructura de mensaje de varias partes:

        >>> for part in msg.walk():
        ...     print(part.get_content_type())
        multipart/report
        text/plain
        message/delivery-status
        text/plain
        text/plain
        message/rfc822
        text/plain

    `walk` iterates over the subparts of any part where `is_multipart()` returns `True`, even though `msg.get_content_maintype() == 'multipart'` may return `False`. We can see this in our example by making use of the `_structure` debug helper function:

        >>> from email.iterators import _structure
        >>> for part in msg.walk():
        ...     print(part.get_content_maintype() == 'multipart',
        ...           part.is_multipart())
        True True
        False False
        False True
        False False
        False False
        False True
        False False
        >>> _structure(msg)
        multipart/report
            text/plain
            message/delivery-status
                text/plain
                text/plain
            message/rfc822
                text/plain

    Here the `message` parts are not `multiparts`, but they do contain subparts. `is_multipart()` returns `True` and `walk` descends into the subparts.

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

    Retorna la parte MIME que es la mejor candidata para ser el «cuerpo» del mensaje.

    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.

    Empieza a buscar coincidencias candidatas con el objeto en el que se llama al método `get_body`”.

    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`.

    Si ninguno de los candidatos coincide con ninguna de las preferencias en preferencelist, retorna `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 immediate sub-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`()

    Elimina el payload y todos los headers.

  `clear_content`()

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

  `EmailMessage` objects have the following instance attributes:

  `preamble`

    The format of a MIME document allows for some text between the blank line following the headers, and the first multipart boundary string. Normally, this text is never visible in a MIME-aware mail reader because it falls outside the standard MIME armor. However, when viewing the raw text of the message, or when viewing the message in a non-MIME aware reader, this text can become visible.

    The preamble attribute contains this leading extra-armor text for MIME documents. When the `Parser` discovers some text after the headers but before the first boundary string, it assigns this text to the message’s preamble attribute. When the `Generator` is writing out the plain text representation of a MIME message, and it finds the message has a preamble attribute, it will write this text in the area between the headers and the first boundary. See `email.parser` and `email.generator` for details.

    Note that if the message object has no preamble, the preamble attribute will be `None`.

  `epilogue`

    The epilogue attribute acts the same way as the preamble attribute, except that it contains text that appears between the last boundary and the end of the message. As with the `preamble`, if there is no epilog text this attribute will be `None`.

  `defects`

    The defects attribute contains a list of all the problems found when parsing this message. See `email.errors` for a detailed description of the possible parsing defects.

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.

Notas al pie

1

  Originally added in 3.4 as a provisional module. Docs for legacy message class moved to email.message.Message: Representar un mensaje de correo electrónico usando la API compat32.