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.