"email.parser": Analizar mensajes de correo electrónico
*******************************************************

**Código fuente:** Lib/email/parser.py

======================================================================

Se pueden construir estructuras de objetos de mensaje de dos formas:
pueden ser creados de puro invento al crear un objeto "EmailMessage",
añadir encabezados usando la interfaz de diccionario, y añadir
carga(s) usando el método "set_content()" y otros relacionados, o
pueden ser creados al analizar una representación serializada de un
mensaje de correo electrónico.

El paquete "email" proporciona un analizador estándar que entiende la
mayoría de estructuras de documentos de correo electrónico, incluyendo
documentos MIME.  Le puedes pasar al analizador bytes, una cadena de
caracteres o una archivo de objeto, y el analizador te retornará la
instancia "EmailMessage" raíz de la estructura del objeto. Para
mensajes simples que no sean MIME, la carga de su objeto raíz
probablemente será una cadena de caracteres conteniendo el texto o el
mensaje. Para mensajes MIME, el objeto raíz retornará "True" de su
método "is_multipart()", y las subpartes pueden ser accedidas a través
de los métodos de manipulación de carga, tales como "get_body()",
"iter_parts()", y "walk()".

De hecho hay dos interfaces de analizadores disponibles para usar, la
API "Parser" y la API progresiva "FeedParser".  La API "Parser" es más
útil si tú tienes el texto del mensaje entero en memoria, o si el
mensaje entero reside en un archivo en el sistema. "FeedParser" es más
apropiado cuando estás leyendo el mensaje de un *stream* que puede ser
bloqueado esperando más entrada (tal como leer un mensaje de correo
electrónico de un socket).  El "FeedParser" puede consumir y analizar
el mensaje de forma progresiva, y sólo retorna el objeto raíz cuando
cierras el analizador.

Note that the parser can be extended in limited ways, and of course
you can implement your own parser completely from scratch.  All of the
logic that connects the "email" package's bundled parser and the
"EmailMessage" class is embodied in the "Policy" class, so a custom
parser can create message object trees any way it finds necessary by
implementing custom versions of the appropriate "Policy" methods.


API *FeedParser*
================

La clase "BytesFeedParser", importado del módulo "email.feedparser",
proporciona una API que es propicia para el análisis progresivo de
mensajes de correo electrónico, tal como sería necesario cuando se
esté leyendo el texto de un mensaje de correo electrónico de una
fuente que puede bloquear (tal como un socket).  Desde luego se puede
usar la clase "BytesFeedParser" para analizar un mensaje de correo
electrónico completamente contenido en un *bytes-like object*, cadena
de caracteres, o archivo, pero la API "BytesParser" puede ser más
conveniente para tales casos de uso.  Las semánticas y resultados de
las dos API de los analizadores son idénticas.

La API de "BytesFeedParser" es simple; puedes crear una instancia, le
proporcionas un montón de bytes hasta que no haya más necesidad de
hacerlo, entonces cierras el analizador para recuperar el objeto del
mensaje raíz. El "BytesFeedParser" es extremadamente preciso cuando
está analizando mensajes conformes al estándar, y hace un buen trabajo
al analizar mensajes no conformes, proporcionando información acerca
de cómo un mensaje fue considerado inservible.  Ingresará una lista de
cualquier problema que encontró en el atributo "defects" del objeto
mensaje.  Véase el módulo "email.errors" para la lista de defectos que
puede encontrar.

Aquí está el API para "BytesFeedParser":

class email.parser.BytesFeedParser(_factory=None, *, policy=policy.compat32)

   Crea una instancia de "BytesFeedParser". El argumento opcional
   *_factory* es un invocable sin argumentos; si no se especifica, usa
   el "message_factory" de *policy*.  Llama a *_factory* cuando sea
   necesario un nuevo objeto mensaje.

   Si se especifica *policy*, usa las reglas que especifica para
   actualizar la representación del mensaje.  Si *policy* no está
   puesta, usa la política (*policy*) "compat32", que mantiene
   compatibilidad con la versión 3.2 de Python del paquete de correo
   electrónico y proporciona a "Message" como la fábrica por defecto.
   Todas las otras políticas proveen a "EmailMessage" como el
   *_factory* por defecto. Para más información en lo demás que
   *policy* controla, véase la documentación "policy".

   Nota: **La palabra clave *policy* siempre debe estar
   especificada**; El valor por defecto cambiará a
   "email.policy.default" en una versión futura de Python.

   Nuevo en la versión 3.2.

   Distinto en la versión 3.3: Se añadió la palabra clave *policy*.

   Distinto en la versión 3.6: *_factory* es por defecto la *policy*
   "message_factory".

   feed(data)

      Le proporciona al analizador algunos datos más.  *data* debe ser
      un *bytes-like object* conteniendo una o más líneas.  Las líneas
      pueden ser parciales y el analizador va a juntar tales líneas
      parciales apropiadamente.  las líneas pueden tener cualquiera de
      las tres terminaciones de línea comunes: retorno de cargo
      (*retorno de cargo*), nueva línea (*newline*), o retorno de
      cargo y nueva línea (pueden ser mezclados).

   close()

      Completa el análisis de todos los datos previamente
      proporcionados y retorna la raíz del objeto mensaje. No está
      definido lo que pasa si se llama a "feed()" después de que este
      método haya sido llamado.

class email.parser.FeedParser(_factory=None, *, policy=policy.compat32)

   Funciona como "BytesFeedParser" excepto que la entrada al método
   "feed()" no debe ser una cadena de caracteres.  Esto es utilidad
   limitada, ya que la única manera de que tal mensaje sea válido es
   que sólo contenga texto ASCII o, si "utf8" es "True", sin binarios
   adjuntos.

   Distinto en la versión 3.3: Se añadió la palabra clave *policy*.


API *Parser*
============

La clase "BytesParser", importado del módulo "email.parser",
proporciona una API que puede ser usada para analizar un mensaje
cuando el contenido completo del mensaje esté disponible en un *bytes-
like object* o archivo. El módulo "email.parser" también proporciona a
"Parser" para analizar cadenas de caracteres, y analizadores de sólo
cabeceras, "BytesHeaderParser" y "HeaderParser" que pueden ser usados
si sólo estás interesado en las cabeceras del mensaje.
"BytesHeaderParser" y "HeaderParser" puede ser más rápidos en estas
situaciones, ya que no intentan analizar el cuerpo del mensaje, en vez
de eso configuran la carga al cuerpo puro.

class email.parser.BytesParser(_class=None, *, policy=policy.compat32)

   Crea una instancia de "BytesParser". Los argumentos *_class* y
   *policy* tiene el mismo significado y semántica que los argumentos
   *_factory* y *policy* de "BytesFeedParser".

   Nota: **La palabra clave *policy* siempre debe estar
   especificada**; El valor por defecto cambiará a
   "email.policy.default" en una versión futura de Python.

   Distinto en la versión 3.3: Se eliminó el argumento *strict* que
   fue deprecado en 2.4.  Se añadió la palabra clave *policy*.

   Distinto en la versión 3.6: *_class* es por defecto la política
   "message_factory".

   parse(fp, headersonly=False)

      Lee todos los datos del objeto binario parecido a archivo *fp*,
      analiza los bytes resultantes, y retorna el objeto mensaje.
      *fp* debe soportar tanto el método "readline()" como el método
      "read()".

      Los bytes contenidos en *fp* deben ser formateados como un
      bloque de cabeceras de estilo y líneas de continuación de
      cabecera de **RFC 5322** (o, si "utf8" es "True", **RFC 6532**).
      El bloque cabecera se termina o al final de los datos o por una
      línea blanca.  Después del bloque de cabecera esta él cuerpo del
      mensaje (que puede contener subpartes codificadas como MIME,
      incluyendo subpartes con un *Content-Transfer-Encoding* de
      "8bit").

      El argumento opcional *headersonly* es un flag que especifica si
      se debe analizar después de leer las cabeceras o no.  El valor
      por defecto es "False", significando que analiza el contenido
      entero del archivo.

   parsebytes(bytes, headersonly=False)

      Similar al método "parse()", excepto que toma un *bytes-like
      object* en vez de un objeto similar a un archivo.  Llamar a este
      método en un *bytes-like object* es equivalente a envolver a
      *bytes* en una instancia de "BytesIO" primero y llamar a
      "parse()".

      El argumento opcional *headersonly* es como el método "parse()".

   Nuevo en la versión 3.2.

class email.parser.BytesHeaderParser(_class=None, *, policy=policy.compat32)

   Exactamente como "BytesParser", excepto que *headersonly* es por
   defecto "True".

   Nuevo en la versión 3.3.

class email.parser.Parser(_class=None, *, policy=policy.compat32)

   Esta clase es paralela a "BytesParser", pero trata entradas de
   cadenas de caracteres.

   Distinto en la versión 3.3: Se eliminó el argumento *strict*.  Se
   añadió la palabra clave *policy*.

   Distinto en la versión 3.6: *_class* es por defecto la política
   "message_factory".

   parse(fp, headersonly=False)

      Lee todos los datos del modo texto del objeto parecido a archivo
      *fp*, analiza el texto resultante, y retorna el objeto mensaje
      raíz.  *fp* debe soportar tanto el método "readline()" y el
      método "read()" en objetos parecidos a archivos.

      Además de el requisito del modo texto, este método opera como
      "BytesParser.parse()".

   parsestr(text, headersonly=False)

      Similar al método "parse()", excepto que toma un objeto de
      cadena de caracteres de un objeto similar a un archivo.  Llamar
      a este método en una cadena de caracteres es equivalente a
      envolver a *text* en una instancia de "StringIO" primero y
      llamar a "parse()".

      El argumento opcional *headersonly* es como el método "parse()".

class email.parser.HeaderParser(_class=None, *, policy=policy.compat32)

   Exactamente como "Parser", excepto que *headersonly* es por defecto
   "True".

Ya que crear una estructura de un objeto mensaje de una cadena de
caracteres o un objeto archivo es una tarea tan común, Se
proporcionaron 4 funciones como una conveniencia.  Están disponibles
en paquete de espacio de nombres de alto nivel "email".

email.message_from_bytes(s, _class=None, *, policy=policy.compat32)

   Retorna una estructura del objeto mensaje de un *bytes-like
   object*. Esto es equivalente a "BytesParser().parsebytes(s)". El
   argumento opcional *_class* y *policy* son interpretados como
   sucede con el constructor de clase "BytesParser".

   Nuevo en la versión 3.2.

   Distinto en la versión 3.3: Se eliminó el argumento *strict*.  Se
   añadió la palabra clave *policy*.

email.message_from_binary_file(fp, _class=None, *, policy=policy.compat32)

   Retorna una estructura árbol del objeto mensaje de un *file object*
   binario abierto.  Esto es equivalente a "BytesParser().parse(fp)".
   *_class* y *policy* son interpretados como sucede con el
   constructor de clase "BytesParser".

   Nuevo en la versión 3.2.

   Distinto en la versión 3.3: Se eliminó el argumento *strict*.  Se
   añadió la palabra clave *policy*.

email.message_from_string(s, _class=None, *, policy=policy.compat32)

   Retorna una estructura del objeto mensaje de una cadena de
   caracteres.  Esto es equivalente a "Parser().parsestr(s)". *_class*
   y *policy* son interpretados como sucede con el constructor de
   clase "Parser".

   Distinto en la versión 3.3: Se eliminó el argumento *strict*.  Se
   añadió la palabra clave *policy*.

email.message_from_file(fp, _class=None, *, policy=policy.compat32)

   Retorna una estructura árbol del objeto mensaje de un *file object*
   abierto. Esto es equivalente a "Parser().parse(fp)".  *_class* y
   *policy* son interpretados como sucede con el constructor de clase
   "Parser".

   Distinto en la versión 3.3: Se eliminó el argumento *strict*.  Se
   añadió la palabra clave *policy*.

   Distinto en la versión 3.6: *_class* es por defecto la política
   "message_factory".

Aquí está un ejemplo de cómo puedes usar "message_from_bytes()" en una
entrada interactiva de Python:

   >>> import email
   >>> msg = email.message_from_bytes(myBytes)  


Notas adicionales
=================

Aquí están algunas notas sobre la semántica del análisis:

* La mayoría de los mensajes de tipo que no son *multipart* son
  actualizados como un solo objeto mensaje con una carga de cadena de
  caracteres.  Estos objetos retornarán "False" para "is_multipart()",
  y "iter_parts()" cederá (*yield*) una lista vacía.

* Todos los mensajes de tipo *multipart* serán analizados como un
  objeto mensaje contenedor con una lista de objetos sub-mensajes para
  sus cargas.  El mensaje del contenedor externo retornará "True" para
  "is_multipart()", y "iter_parts()" cederá (*yield*) una lista de
  subpartes.

* La mayoría de mensajes con una tipo de contenido de *message/** (tal
  como *message/delivery-status* y *message/rfc822*) también serán
  analizados como objetos contenedores que contienen una lista de
  cargas de longitud 1. Su método "is_multipart()" retornará "True".
  El único elemento cedido (*yielded*) por "iter_parts()" será un
  objeto sub-mensaje.

* Algunos mensajes de conformidad no estándar pueden no ser
  internamente consistentes acerca de su *multipart*-idad. Tales
  mensajes pueden tener una cabecera *Content-Type* de tipo
  *multipart*, pero su método "is_multipart()" puede retornar "False".
  Si tales mensajes son analizados con "FeedParser", tendrán una
  instancia de la clase "MultipartInvariantViolationDefect" en su
  lista de atributos *defects*.  Véase "email.errors" para más
  detalles.
