"email.parser" : analyser des e-mails
*************************************

**Code source :** Lib/email/parser.py

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

Les instances de messages peuvent être créées de deux façons : elles
peuvent être créées de toutes pièces en créant un objet
"EmailMessage", en ajoutant des en-têtes en utilisant l'interface de
dictionnaire, et en ajoutant un ou plusieurs corps de message en
utilisant "set_content()" et les méthodes associées, ou elles peuvent
être créées en analysant une représentation sérialisée de l'e-mail.

Le paquet "email" fournit un analyseur standard qui comprend la
plupart des structures de documents de courrier électronique, y
compris les documents MIME. Vous pouvez passer à l'analyseur un objet
*bytes*, chaîne ou fichier, et l'analyseur vous renverra l'instance
racine "EmailMessage" de la structure de l'objet. Pour les messages
simples non MIME, la charge utile de cet objet racine sera
probablement une chaîne contenant le texte du message. Pour les
messages MIME, la méthode "is_multipart()" de l'objet racine renvoie
"True", et les sous-parties sont accessibles via les méthodes de
manipulation de la charge utile, telles que "get_body()",
"iter_parts()" et "walk()".

Il existe en fait deux interfaces d'analyseur disponibles, l'API
"Parser" et l'API incrémentale "FeedParser". L'API "Parser" est plus
utile si vous avez le texte entier du message en mémoire ou si le
message entier réside dans un fichier sur le système de fichiers.
"FeedParser" est plus appropriée lorsque vous lisez le message à
partir d'un flux qui peut bloquer en attente d'une entrée
supplémentaire (comme la lecture d'un message électronique à partir
d'un connecteur réseau). "FeedParser" peut consommer et analyser le
message de manière incrémentielle et ne renvoie l'objet racine que
lorsque vous fermez l'analyseur.

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*
================

"BytesFeedParser", importée du module "email.feedparser", fournit une
API propice à l'analyse incrémentielle des messages électroniques,
adaptée à la lecture du texte d'un message électronique à partir d'une
source qui peut bloquer (comme un connecteur). "BytesFeedParser" peut
bien sûr être utilisée pour analyser un message électronique
entièrement contenu dans un *objet octets-compatible*, une chaîne ou
un fichier, mais l'API "BytesParser" peut être plus pratique dans ces
utilisations. La sémantique et les résultats des deux API d'analyseurs
sont identiques.

L'API de "BytesFeedParser" est simple ; vous créez une instance,
l'alimentez d'une suite d'octets jusqu'à ce qu'il n'y en ait plus pour
l'alimenter, puis fermez l'analyseur pour récupérer l'objet message
racine. "BytesFeedParser" est extrêmement précise lors de l'analyse
des messages conformes aux normes, et elle fait un très bon travail
d'analyse des messages non conformes, fournissant des informations sur
ce qu'elle considère comme non approprié dans un message. Elle remplit
l'attribut "defects" d'un objet message avec une liste de tous les
problèmes trouvés dans un message. Voir le module "email.errors" pour
la liste des défauts qu'elle peut trouver.

Voici l’API de "BytesFeedParser" :

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

   Crée une instance "BytesFeedParser". *_factory* est un appelable
   facultatif sans argument ; s'il n'est pas spécifié, elle utilise la
   "message_factory" de la *policy*. Elle appelle *_factory* chaque
   fois qu'un nouvel objet de message est nécessaire.

   Si *policy* est spécifiée, elle utilise les règles spécifiées pour
   mettre à jour la représentation du message. Si *policy* n'est pas
   définie, elle utilise la stratégie "compat32", qui maintient la
   rétrocompatibilité avec la version Python 3.2 du paquet de
   messagerie et fournit "Message" comme usine par défaut. Toutes les
   autres stratégies fournissent "EmailMessage" comme *_factory* par
   défaut. Pour plus d'informations sur ce que *policy* régit,
   consultez la documentation "policy".

   Remarque : **Le paramètre nommé « policy » doit toujours être
   spécifié** ; La valeur par défaut deviendra "email.policy.default"
   dans une future version de Python.

   Nouveau dans la version 3.2.

   Modifié dans la version 3.3: ajout du paramètre nommé *policy*.

   Modifié dans la version 3.6: *_factory* utilise par défaut la
   politique "message_factory".

   feed(data)

      Alimente l'analyseur avec plus de données. *data* doit être un
      *objet octets-compatible* contenant une ou plusieurs lignes. Les
      lignes peuvent être partielles et l'analyseur assemble
      correctement ces lignes partielles. Les lignes peuvent avoir
      l'une des trois fins de ligne courantes : retour chariot,
      nouvelle ligne ou retour chariot et nouvelle ligne (elles
      peuvent même être mélangées).

   close()

      Termine l'analyse de toutes les données précédemment alimentées
      et renvoie l'objet message racine. Ce qui se passe si "feed()"
      est appelée après l'appel de cette méthode n'est pas défini.

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

   Fonctionne comme "BytesFeedParser" sauf que l'entrée de la méthode
   "feed()" doit être une chaîne. Ceci est d'une utilité limitée, car
   la seule façon pour qu'un tel message soit valide est qu'il ne
   contienne que du texte ASCII ou, si "utf8" vaut "True", aucun
   binaire en pièce jointe.

   Modifié dans la version 3.3: ajout du paramètre nommé *policy*.


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

La classe "BytesParser", importée du module "email.parser", fournit
une API qui peut être utilisée pour analyser un message lorsque le
contenu complet du message est disponible dans un *objet octets-
compatible* ou un fichier. Le module "email.parser" fournit également
"Parser" pour l'analyse des chaînes et des analyseurs d'en-tête
uniquement, "BytesHeaderParser" et "HeaderParser", qui peuvent être
utilisés si vous ne vous intéressez qu'aux en-têtes du message.
"BytesHeaderParser" et "HeaderParser" peuvent être beaucoup plus
rapides dans ces situations, car ils n'essaient pas d'analyser le
corps du message.

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

   Crée une instance "BytesParser". Les arguments *_class* et *policy*
   ont la même signification et la même sémantique que les arguments
   *_factory* et *policy* de "BytesFeedParser".

   Remarque : **Le paramètre nommé « policy » doit toujours être
   spécifié** ; La valeur par défaut deviendra "email.policy.default"
   dans une future version de Python.

   Modifié dans la version 3.3: suppression de l'argument *strict* qui
   était obsolète dans 2.4. Ajout du paramètre nommé *policy*.

   Modifié dans la version 3.6: *_class* utilise par défaut la
   politique "message_factory".

   parse(fp, headersonly=False)

      Lit toutes les données de l'objet de type fichier binaire *fp*,
      analyse les octets résultants et renvoie l'objet message. *fp*
      doit prendre en charge les méthodes "readline()" et "read()".

      Les octets contenus dans *fp* doivent être formatés comme un
      bloc d'en-têtes de style conforme à la **RFC 5322** (ou, si
      "utf8" est "True", à la **RFC 6532**), éventuellement précédés
      d'un en-tête d'enveloppe. Le bloc d'en-têtes se termine soit par
      la fin des données, soit par une ligne blanche. Après le bloc d
      'en-têtes se trouve le corps du message (qui peut contenir des
      sous-parties codées MIME, y compris des sous-parties avec un
      *Content-Transfer-Encoding* de "8bit").

      *headersonly* est un indicateur facultatif spécifiant s'il faut
      arrêter l'analyse après avoir lu les en-têtes ou non. La valeur
      par défaut est "False", ce qui signifie qu'il analyse tout le
      contenu du fichier.

   parsebytes(bytes, headersonly=False)

      Semblable à la méthode "parse()", sauf qu'elle prend un *objet
      octets-compatible* au lieu d'un objet de type fichier. Appeler
      cette méthode sur un *objet octets-compatible* équivaut à
      envelopper *bytes* dans une instance "BytesIO" d'abord et à
      appeler "parse()".

      L'utilisation de l'option *headersonly* est identique à son
      utilisation dans la méthode "parse()".

   Nouveau dans la version 3.2.

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

   Exactement comme "BytesParser", sauf que *headersonly* par défaut
   est "True".

   Nouveau dans la version 3.3.

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

   Cette classe est semblable à "BytesParser", mais elle accepte une
   chaîne en entrée.

   Modifié dans la version 3.3: suppression de l'argument *strict*.
   Ajout de l'argument nommé *policy*.

   Modifié dans la version 3.6: *_class* utilise par défaut la
   politique "message_factory".

   parse(fp, headersonly=False)

      Lit toutes les données de l'objet de type fichier en mode texte
      *fp*, analyse le texte résultant et renvoie l'objet message
      racine. *fp* doit prendre en charge les méthodes "readline()" et
      "read()" sur les objets de type fichier.

      Outre l'exigence du mode texte, cette méthode fonctionne comme
      "BytesParser.parse()".

   parsestr(text, headersonly=False)

      Similaire à la méthode "parse()", sauf qu'elle prend un objet
      chaîne au lieu d'un objet de type fichier. Appeler cette méthode
      sur une chaîne équivaut à envelopper *text* dans une instance
      "StringIO" d'abord et à appeler "parse()".

      L'utilisation de l'option *headersonly* est identique à son
      utilisation dans la méthode "parse()".

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

   Exactement comme "Parser", sauf que *headersonly* par défaut est
   "True".

Étant donné que la création d'une structure d'objet message à partir
d'une chaîne ou d'un objet fichier est une tâche très courante, quatre
fonctions sont fournies par commodité. Elles sont disponibles dans
l'espace de noms de paquet de niveau supérieur "email".

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

   Renvoie une structure d'objet message à partir d'un *objet octets-
   compatible*. C'est équivalent à "BytesParser().parsebytes(s)".
   *_class* et *policy* (facultatifs) sont interprétés comme pour le
   constructeur de classe "BytesParser".

   Nouveau dans la version 3.2.

   Modifié dans la version 3.3: suppression de l'argument *strict*.
   Ajout de l'argument nommé *policy*.

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

   Renvoie une arborescence d'objets message à partir d'un *objet
   fichier* binaire ouvert. C'est équivalent à
   "BytesParser().parse(fp)". *_class* et *policy* sont interprétés
   comme pour le constructeur de classe "BytesParser".

   Nouveau dans la version 3.2.

   Modifié dans la version 3.3: suppression de l'argument *strict*.
   Ajout de l'argument nommé *policy*.

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

   Renvoie une structure d'objet message à partir d'une chaîne. C'est
   équivalent à "Parser().parsestr(s)". *_class* et *policy* sont
   interprétés comme avec le constructeur de classe "Parser".

   Modifié dans la version 3.3: suppression de l'argument *strict*.
   Ajout de l'argument nommé *policy*.

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

   Renvoie une arborescence de structures d'objets messages à partir
   d'un *objet fichier* ouvert. C'est équivalent à
   "Parser().parse(fp)". *_class* et *policy* sont interprétés comme
   avec le constructeur de classe "Parser".

   Modifié dans la version 3.3: suppression de l'argument *strict*.
   Ajout de l'argument nommé *policy*.

   Modifié dans la version 3.6: *_class* utilise par défaut la
   politique "message_factory".

Voici un exemple d'utilisation "message_from_bytes()" dans une invite
Python interactive :

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


Notes complémentaires
=====================

Voici des remarques sur la sémantique d'analyse :

* La plupart des messages de type non-*multipart* sont analysés comme
  un seul objet de message avec une charge utile de type chaîne. Ces
  objets renvoient "False" pour "is_multipart()" et "iter_parts()"
  donne une liste vide.

* Tous les messages de type *multipart* sont analysés comme un objet
  de message conteneur avec une liste d'objets de sous-messages pour
  leur charge utile. Le message du conteneur externe renvoie "True"
  pour "is_multipart()" et "iter_parts()" donne une liste de sous-
  parties.

* La plupart des messages avec un type de contenu de *message/** (tels
  que *message/delivery-status* et *message/rfc822*) sont également
  analysés en tant qu'objet conteneur contenant une charge utile de
  type « liste de longueur 1 ». Leur méthode "is_multipart()" renvoie
  "True". L'élément unique généré par "iter_parts()" est un objet
  sous-message.

* Certains messages non conformes aux normes peuvent ne pas être
  cohérents en interne quant à *multipart*. De tels messages peuvent
  avoir un en-tête *Content-Type* de type *multipart*, mais leur
  méthode "is_multipart()" peut renvoyer "False". Si de tels messages
  ont été analysés avec la "FeedParser", ils auront une instance de la
  classe "MultipartInvariantViolationDefect" dans leur liste
  d'attributs *defects*. Voir "email.errors" pour plus de détails.
