# `email.generator`: Generating MIME documents

Code source : Lib/email/igenerator.py

One of the most common tasks is to generate the flat (serialized) version of the email message represented by a message object structure. You will need to do this if you want to send your message via `smtplib.SMTP.sendmail()`, or print the message on the console. Taking a message object structure and producing a serialized representation is the job of the generator classes.

Comme avec le module `email.parser`, vous n'êtes pas limité aux fonctionnalités du générateur fourni ; vous pourriez en écrire un à partir de zéro vous-même. Cependant, le générateur fourni sait comment générer la plupart des e-mails d'une manière conforme aux normes, est conçu pour gérer correctement les e-mails MIME et non MIME, et pour que les opérations (sur des suites d'octets) d'analyse et de génération soient inverses, en supposant que la même `policy` est utilisée pour les deux. Autrement dit, l'analyse du flux d'octets sérialisé via la classe `BytesParser` puis la régénération du flux d'octets sérialisé à l'aide de `BytesGenerator` devrait produire une sortie identique à l'entrée [1] (d'un autre côté, l'utilisation du générateur sur un `EmailMessage` construit par programme peut entraîner des modifications de l'objet `EmailMessage` car les valeurs par défaut sont renseignées).

La classe `Generator` peut être utilisée pour aplatir un message dans une représentation sérialisée textuelle (par opposition à binaire), mais comme Unicode ne peut pas représenter directement des données binaires, le message est nécessairement transformé en quelque chose qui ne contient que des caractères ASCII, en utilisant les techniques standard de codage de transfert de contenu RFC pour le codage des messages électroniques pour le transport sur des canaux qui ne sont pas « complétement 8 bits ».

Pour s'adapter au traitement reproductible des messages signés SMIME `Generator` ne raccourcit pas les en-têtes pour les parties de message de type `multipart/signed` et toutes les sous-parties.

class email.generator.BytesGenerator(outfp, mangle_from_=None, maxheaderlen=None, *, policy=None)

  Renvoie un objet `BytesGenerator` qui écrit tout message fourni à la méthode `flatten()`, ou tout texte encodé par surrogateescape fourni à la méthode `write()`, dans le objet simili-fichier outfp. outfp doit disposer d'une méthode `write` qui accepte les données binaires.

  Si l'option mangle_from_ est `True`, place un caractère `>` devant toute ligne du corps commençant par la chaîne exacte `"From "`, c'est-à-dire une ligne commençant par `From` suivi par une espace. mangle_from_ prend par défaut la valeur du paramètre `mangle_from_` de la policy (qui est `True` pour la politique `compat32` et `False` pour tous les autres). mangle_from_ est destiné à être utilisé lorsque les messages sont stockés au format Unix mbox (voir `mailbox` et WHY THE CONTENT-LENGTH FORMAT IS BAD).

  Si maxheaderlen n'est pas `None`, raccourcit toutes les lignes d'en-tête qui sont plus longues que maxheaderlen, ou si `0`, ne raccourcit aucun en-tête. Si manheaderlen est `None` (valeur par défaut), formate les en-têtes et autres lignes de message en fonction des paramètres de policy.

  Si policy est spécifiée, utilise cette politique pour contrôler la génération des messages. Si policy est `None` (par défaut), utilise la politique associée à l'objet `Message` ou `EmailMessage` passée à `flatten` pour contrôler la génération des messages. Voir `email.policy` pour plus de détails sur ce que policy contrôle.

  Ajouté dans la version 3.2.

  Modifié dans la version 3.3: ajout du mot-clé policy.

  Modifié dans la version 3.6: le comportement par défaut des paramètres mangle_from_ et maxheaderlen est de suivre la politique.

  flatten(msg, unixfrom=False, linesep=None)

    Affiche la représentation textuelle de la structure de l'objet message dont la racine est msg dans le fichier de sortie spécifié lors de la création de l'instance `BytesGenerator`.

    Si l'option `cte_type` de `policy` est `8bit` (valeur par défaut), copie tous les en-têtes du message analysé d'origine qui n'ont pas été modifiés en sortie avec tous les octets dont le bit de poids fort identique à l'original, et conserve le Content-Transfer-Encoding non-ASCII de toutes les parties du corps qui en ont. Si `cte_type` est `7bit`, convertit les octets avec le bit de poids fort défini selon les besoins en utilisant un Content-Transfer-Encoding compatible ASCII. Autrement dit, transforme les parties non ASCII Content-Transfer-Encoding (Content-Transfer-Encoding: 8bit) en un Content-Transfer-Encoding compatible ASCII, et encode les octets non ASCII non valides de la RFC dans les en-têtes utilisant le jeu de caractères MIME `unknown-8bit`, les rendant ainsi conformes à la RFC.

    Si unixfrom est `True`, affiche le délimiteur d'en-tête d'enveloppe utilisé par le format de boîte aux lettres Unix (voir `mailbox`) avant le premier des en-têtes RFC 5322 de l'objet message racine. Si l'objet racine n'a pas d'en-tête d'enveloppe, en crée un standard. La valeur par défaut est `False`. Notez que pour les sous-parties, aucun en-tête d'enveloppe n'est jamais imprimé.

    Si linesep n'est pas `None`, l'utilise comme caractère de séparation entre toutes les lignes du message aplati. Si linesep est `None` (valeur par défaut), utilise la valeur spécifiée dans la policy.

  clone(fp)

    Renvoie un clone indépendant de cette instance `BytesGenerator` avec exactement les mêmes paramètres d'option, et fp comme nouveau outfp.

  write(s)

    Encode s en utilisant le codec `ASCII` et le gestionnaire d'erreurs `surrogateescape`, et le passe à la méthode write du outfp passé au constructeur de `BytesGenerator`.

Par commodité, `EmailMessage` fournit les méthodes `as_bytes()` et `bytes(aMessage)` (alias `__bytes__()`), qui simplifient la génération d'une représentation binaire sérialisée d'un objet message. Pour plus de détails, voir `email.message`.

Comme les chaînes ne peuvent pas représenter des données binaires, la classe `Generator` doit convertir toutes les données binaires de tout message qu'elle aplatit en un format compatible ASCII, en les convertissant en un Content-Transfer_Encoding compatible ASCII. En utilisant la terminologie des RFC des e-mails, vous pouvez considérer cela comme un `Generator` sérialisant vers un flux d'entrées-sorties qui n'est pas « complètement 8 bits ». En d'autres termes, la plupart des applications voudront utiliser `BytesGenerator` et pas `Generator`.

class email.generator.Generator(outfp, mangle_from_=None, maxheaderlen=None, *, policy=None)

  Renvoie un objet `Generator` qui écrit tout message fourni à la méthode `flatten()`, ou tout texte fourni à la méthode `write()`, dans l'objet simili-fichier outfp. outfp doit prendre en charge une méthode `write` qui accepte les données de type chaîne.

  Si l'option mangle_from_ est `True`, place un caractère `>` devant toute ligne du corps commençant par la chaîne exacte `"From "`, c'est-à-dire une ligne commençant par `From` suivi par une espace. mangle_from_ prend par défaut la valeur du paramètre `mangle_from_` de la policy (qui est `True` pour la politique `compat32` et `False` pour tous les autres). mangle_from_ est destiné à être utilisé lorsque les messages sont stockés au format Unix mbox (voir `mailbox` et WHY THE CONTENT-LENGTH FORMAT IS BAD).

  Si maxheaderlen n'est pas `None`, raccourcit toutes les lignes d'en-tête qui sont plus longues que maxheaderlen, ou si `0`, ne raccourcit aucun en-tête. Si manheaderlen est `None` (valeur par défaut), formate les en-têtes et autres lignes de message en fonction des paramètres de policy.

  Si policy est spécifiée, utilise cette politique pour contrôler la génération des messages. Si policy est `None` (par défaut), utilise la politique associée à l'objet `Message` ou `EmailMessage` passée à `flatten` pour contrôler la génération des messages. Voir `email.policy` pour plus de détails sur ce que policy contrôle.

  Modifié dans la version 3.3: ajout du mot-clé policy.

  Modifié dans la version 3.6: le comportement par défaut des paramètres mangle_from_ et maxheaderlen est de suivre la politique.

  flatten(msg, unixfrom=False, linesep=None)

    Affiche la représentation textuelle de la structure de l'objet message dont la racine est msg dans le fichier de sortie spécifié lors de la création de l'instance `Generator`.

    Si l'option `policy` `cte_type` est `8bit`, génère le message comme si l'option était définie sur `7bit` (c'est nécessaire car les chaînes ne peuvent pas représenter des octets non ASCII). Convertit tous les octets avec le bit de poids fort défini selon les besoins à l'aide d'un Content-Transfer-Encoding compatible ASCII. Autrement dit, transforme les parties non ASCII Content-Transfer-Encoding (Content-Transfer-Encoding: 8bit) en un Content-Transfer-Encoding compatible ASCII, et encode les octets non ASCII non valides RFC dans les en-têtes utilisant le jeu de caractères MIME `unknown-8bit`, les rendant ainsi conformes à la RFC.

    Si unixfrom est `True`, affiche le délimiteur d'en-tête d'enveloppe utilisé par le format de boîte aux lettres Unix (voir `mailbox`) avant le premier des en-têtes RFC 5322 de l'objet message racine. Si l'objet racine n'a pas d'en-tête d'enveloppe, en crée un standard. La valeur par défaut est `False`. Notez que pour les sous-parties, aucun en-tête d'enveloppe n'est jamais imprimé.

    Si linesep n'est pas `None`, l'utilise comme caractère de séparation entre toutes les lignes du message aplati. Si linesep est `None` (valeur par défaut), utilise la valeur spécifiée dans la policy.

    Modifié dans la version 3.2: ajout de la prise en charge du ré-encodage des corps de message `8bit` et de l'argument linesep.

  clone(fp)

    Renvoie un clone indépendant de cette instance `Generator` avec exactement les mêmes options, et avec fp comme nouveau outfp.

  write(s)

    Écrit s dans la méthode write de outfp passé au constructeur de `Generator`. Cela fournit une API ressemblant suffisamment au type fichier pour les instances de `Generator` utilisées dans la fonction `print()`.

Par commodité, `EmailMessage` fournit les méthodes `as_string()` et `str(aMessage)` (alias `__str__()`), qui simplifient la génération d'une représentation sous forme de chaîne formatée d'un objet message. Pour plus de détails, voir `email.message`.

Le module `email.generator` fournit également une classe dérivée, `DecodedGenerator`, qui ressemble à la classe de base `Generator`, sauf que les parties non-text ne sont pas sérialisées, mais sont plutôt représentées dans le flux de sortie par une chaîne dérivée d'un modèle rempli d'informations sur la partie concernée.

class email.generator.DecodedGenerator(outfp, mangle_from_=None, maxheaderlen=None, fmt=None, *, policy=None)

  Agit comme `Generator`, sauf que pour toute sous-partie du message transmise à `Generator.flatten()`, si la sous-partie est de type principal text, affiche la charge utile décodée de la sous-partie, et si le type principal n'est pas text, au lieu de l'afficher, remplit la chaîne fmt en utilisant les informations de la partie et affiche la chaîne remplie résultante.

  Pour remplir fmt, exécute `fmt % part_info`, où `part_info` est un dictionnaire composé des clés et valeurs suivantes :

  - `type` – Type MIME complet de la partie non-text

  - `maintype` – Type MIME principal de la partie non-text

  - `subtype` – Sous-type MIME de la partie non-text

  - `filename` – Nom de fichier de la partie non-text

  - `description` – Description associée à la partie non-text

  - `encoding` – Encodage du contenu de la partie non-text

  Si fmt est `None`, utilise le fmt par défaut suivant :

  > "[Non-text (%(type)s) part of message omitted, filename %(filename)s]"

  _mangle_from_ et maxheaderlen sont optionnels et fonctionnent comme avec la classe mère `Generator`.

Notes

[1]

This statement assumes that you use the appropriate setting for `unixfrom`, and that there are no `email.policy` settings calling for automatic adjustments (for example, `refold_source` must be `none`, which is not the default). It is also not 100% true, since if the message does not conform to the RFC standards occasionally information about the exact original text is lost during parsing error recovery. It is a goal to fix these latter edge cases when possible.