email.headerregistry: Custom Header Objects

Code source : Lib/email/headerregistry.py


Ajouté dans la version 3.6: [1]

Les en-têtes sont représentés par des sous-classes personnalisées de str. La classe particulière utilisée pour représenter un en-tête donné est déterminée par header_factory de la policy en vigueur lorsque les en-têtes sont créés. Cette section documente la header_factory particulière implémentée par le paquet de messagerie pour la gestion des messages électroniques conformes à la RFC 5322, qui fournit non seulement des objets d'en-tête personnalisés pour différents types d'en-tête, mais fournit également un mécanisme d'extension permettant aux applications d'ajouter leurs propres types d'en-tête personnalisés.

Lors de l'utilisation de l'un des objets de définition de politique dérivés de EmailPolicy, tous les en-têtes sont produits par HeaderRegistry et ont BaseHeader comme dernière classe mère. Chaque classe d'en-tête a une classe mère supplémentaire qui est déterminée par le type de l'en-tête. Par exemple, de nombreux en-têtes ont la classe UnstructuredHeader comme autre classe mère. La deuxième classe spécialisée pour un en-tête est déterminée par le nom de l'en-tête, en utilisant un tableau de recherche stocké dans HeaderRegistry. Tout cela est géré de manière transparente pour le programme d'application typique, mais des interfaces sont fournies pour modifier le comportement par défaut pour une utilisation par des applications plus complexes.

Les sections ci-dessous documentent d'abord les classes mères d'en-tête et leurs attributs, suivies de l'API pour modifier le comportement de HeaderRegistry, et enfin les classes de gestion utilisées pour représenter les données analysées à partir d'en-têtes structurés.

class email.headerregistry.BaseHeader(name, value)

name et value sont passés à BaseHeader à partir de l'appel header_factory. La valeur de chaîne de tout objet d'en-tête est la value entièrement décodée en Unicode.

Cette classe mère définit les propriétés en lecture seule suivantes :

name

Nom de l'en-tête (la partie du champ avant le :). C'est exactement la valeur passée dans l'appel header_factory pour name ; c'est-à-dire que la casse est préservée.

defects

n-uplet d'instances HeaderDefect signalant tout problème de conformité avec les RFC détecté lors de l'analyse. Le paquet d'e-mails tente d'être complet en ce qui concerne la détection des problèmes de conformité. Voir le module errors pour une discussion sur les types de défauts qui peuvent être signalés.

max_count

Nombre maximum d'en-têtes de ce type pouvant avoir le même name. Une valeur de None signifie illimité. La valeur BaseHeader pour cet attribut est None ; les classes d'en-tête spécialisées sont censées remplacer cette valeur si nécessaire.

BaseHeader fournit également la méthode suivante, qui est appelée par le code de la bibliothèque de messagerie et ne doit généralement pas être appelée par les programmes d'application :

fold(*, policy)

Renvoie une chaîne contenant les caractères linesep nécessaires pour remettre en forme correctement l'en-tête conformément à policy. Un cte_type de 8bit est traité comme s'il s'agissait de 7bit, car les en-têtes ne peuvent pas contenir de données binaires arbitraires. Si utf8 est False, les données non-ASCII seront encodées selon la RFC 2047.

BaseHeader seule ne peut pas être utilisée pour créer un objet d'en-tête. Elle définit un protocole avec lequel chaque en-tête spécialisé coopère afin de produire l'objet d'en-tête. Plus précisément, BaseHeader nécessite que la classe spécialisée fournisse une classmethod() nommée parse. Cette méthode s'appelle comme suit :

parse(string, kwds)

kwds est un dictionnaire contenant une clé pré-initialisée : defects. defects est une liste vide. La méthode d'analyse doit ajouter tous les défauts détectés à cette liste. Au retour, le dictionnaire kwds doit contenir des valeurs pour au moins les clés decoded et defects. decoded doit être la valeur de la chaîne pour l'en-tête (c'est-à-dire la valeur de l'en-tête entièrement décodée en Unicode). La méthode d'analyse doit supposer que string peut contenir des parties codées par transfert de contenu, mais doit également gérer correctement tous les caractères Unicode valides afin de pouvoir analyser les valeurs d'en-tête non codées.

__new__ de BaseHeader crée ensuite l'instance d'en-tête et appelle sa méthode init. La classe spécialisée n'a besoin de fournir une méthode init que si elle souhaite définir des attributs supplémentaires au-delà de ceux fournis par BaseHeader lui-même. Une telle méthode init devrait ressembler à ceci :

def init(self, /, *args, **kw):
    self._myattr = kw.pop('myattr')
    super().init(*args, **kw)

Autrement dit, tout ce que la classe spécialisée ajoute au dictionnaire kwds doit être supprimé et géré, et le contenu restant de kw (et args) est passé à la méthode init de BaseHeader.

class email.headerregistry.UnstructuredHeader

Un en-tête « non structuré » est le type d'en-tête par défaut dans la RFC 5322. Tout en-tête qui n'a pas de syntaxe spécifiée est traité comme non structuré. L'exemple classique d'en-tête non structuré est l'en-tête Subject.

Dans la RFC 5322, un en-tête non structuré est une séquence de texte arbitraire dans le jeu de caractères ASCII. RFC 2047, cependant, possède un mécanisme compatible RFC 5322 pour encoder du texte non-ASCII en tant que caractères ASCII dans une valeur d'en-tête. Lorsqu'une value contenant des mots encodés est passée au constructeur, l'analyseur UnstructuredHeader convertit ces mots encodés en Unicode, en suivant les règles de la RFC 2047 pour le texte non structuré. L'analyseur utilise des heuristiques pour tenter de décoder certains mots codés non conformes. Des défauts sont enregistrés dans de tels cas, ainsi que des défauts pour des problèmes tels que des caractères non valides dans les mots codés ou le texte non codé.

Ce type d'en-tête ne fournit aucun attribut supplémentaire.

class email.headerregistry.DateHeader

La RFC 5322 spécifie un format très spécifique pour les dates dans les en-têtes de courrier électronique. L'analyseur DateHeader reconnaît ce format de date, ainsi qu'un certain nombre de formes variantes que l'on trouve parfois « dans la nature ».

Ce type d'en-tête fournit les attributs supplémentaires suivants :

datetime

Si la valeur d'en-tête peut être reconnue comme une date valide d'une forme ou d'une autre, cet attribut contient une instance datetime représentant cette date. Si le fuseau horaire de la date d'entrée est spécifié comme -0000 (indiquant qu'il est en UTC mais ne contient aucune information sur le fuseau horaire source), alors datetime est une datetime naïve. Si un décalage de fuseau horaire spécifique est trouvé (y compris +0000), alors datetime contient un datetime avisé qui utilise datetime.timezone pour enregistrer le décalage lié au fuseau horaire.

La valeur decoded de l'en-tête est déterminée en formatant le datetime selon les règles de la RFC 5322 ; c'est-à-dire qu'elle est définie sur :

email.utils.format_datetime(self.datetime)

Lors de la création d'un DateHeader, value peut être une instance de datetime. Cela signifie, par exemple, que le code suivant est valide et fait ce à quoi on pourrait s'attendre :

msg['Date'] = datetime(2011, 7, 15, 21)

Comme il s'agit d'un datetime naïf, il est interprété comme un horodatage UTC et la valeur résultante a un fuseau horaire de -0000. Il est beaucoup plus utile d'utiliser la fonction localtime() du module utils :

msg['Date'] = utils.localtime()

Cet exemple définit l'en-tête de date sur l'heure et la date actuelles à l'aide du décalage horaire actuel.

class email.headerregistry.AddressHeader

Les en-têtes d'adresse sont l'un des types d'en-têtes structurés les plus complexes. La classe AddressHeader fournit une interface générique à n'importe quel en-tête d'adresse.

Ce type d'en-tête fournit les attributs supplémentaires suivants :

groups

n-uplet d'objets Group encodant les adresses et les groupes trouvés dans la valeur d'en-tête. Les adresses qui ne font pas partie d'un groupe sont représentées dans cette liste comme des Groups à adresse unique dont display_name est None.

addresses

n-uplet d'objets Address encodant toutes les adresses individuelles à partir de la valeur d'en-tête. Si la valeur d'en-tête contient des groupes, les adresses individuelles du groupe sont incluses dans la liste au point où le groupe apparaît dans la valeur (c'est-à-dire que la liste d'adresses est « aplatie » en une liste unidimensionnelle).

La valeur decoded de l'en-tête a tous les mots codés décodés en Unicode. Les noms de domaine encodés en idna sont également décodés en Unicode. La valeur decoded est définie en joignant la valeur str des éléments de l'attribut groups avec ', '.

Une liste d'objets Address et Group dans n'importe quelle combinaison peut être utilisée pour définir la valeur d'un en-tête d'adresse. Les objets Group dont le display_name est None sont interprétés comme des adresses uniques, ce qui permet de copier une liste d'adresses avec des groupes intacts en utilisant la liste obtenue à partir de l'attribut groups de l'en-tête source.

class email.headerregistry.SingleAddressHeader

Sous-classe de AddressHeader qui ajoute un attribut supplémentaire :

address

Adresse unique codée par la valeur d'en-tête. Si la valeur d'en-tête contient en fait plus d'une adresse (ce qui serait une violation de la RFC sous la valeur par défaut policy), l'accès à cet attribut lève une ValueError.

La plupart des classes ci-dessus ont également une variante Unique (par exemple, UniqueUnstructuredHeader). La seule différence est que dans la variante Unique, max_count est définie sur 1.

class email.headerregistry.MIMEVersionHeader

Il n'y a vraiment qu'une seule valeur valide pour l'en-tête MIME-Version, et c'est 1.0. Au cas où, cette classe d'en-tête prend en charge d'autres numéros de version valides. Si un numéro de version a une valeur valide selon la RFC 2045, alors l'objet d'en-tête a des valeurs autres que None pour les attributs suivants :

version

Numéro de version sous forme de chaîne, sans espaces ni commentaires.

major

Numéro de version majeure sous forme d'entier

minor

Numéro de version mineure sous forme d'entier

class email.headerregistry.ParameterizedMIMEHeader

Les en-têtes MIME commencent tous par le préfixe 'Content-'. Chaque en-tête spécifique a une certaine valeur, décrite par la classe de cet en-tête. Certains peuvent également prendre une liste de paramètres supplémentaires, qui ont un format commun. Cette classe sert de base à tous les en-têtes MIME qui prennent des paramètres.

params

Dictionnaire de correspondance entre les noms de paramètres et leurs valeurs.

class email.headerregistry.ContentTypeHeader

Classe ParameterizedMIMEHeader qui gère l'en-tête Content-Type.

content_type

Chaîne de type de contenu, sous la forme maintype/subtype.

maintype
subtype
class email.headerregistry.ContentDispositionHeader

Classe ParameterizedMIMEHeader qui gère l'en-tête Content-Disposition.

content_disposition

inline et attachment sont les seules valeurs valides couramment utilisées.

class email.headerregistry.ContentTransferEncoding

Gère l'en-tête Content-Transfer-Encoding.

cte

Les valeurs valides sont 7bit, 8bit, base64 et quoted-printable. Voir la RFC 2045 pour plus d'informations.

class email.headerregistry.HeaderRegistry(base_class=BaseHeader, default_class=UnstructuredHeader, use_default_map=True)

This is the factory used by EmailPolicy by default. HeaderRegistry builds the class used to create a header instance dynamically, using base_class and a specialized class retrieved from a registry that it holds. When a given header name does not appear in the registry, the class specified by default_class is used as the specialized class. When use_default_map is True (the default), the standard mapping of header names to classes is copied in to the registry during initialization. base_class is always the last class in the generated class's __bases__ list.

Les correspondances par défaut sont :

subject:

UniqueUnstructuredHeader

date:

UniqueDateHeader

resent-date:

DateHeader

orig-date:

UniqueDateHeader

sender:

UniqueSingleAddressHeader

resent-sender:

SingleAddressHeader

to:

UniqueAddressHeader

resent-to:

AddressHeader

cc:

UniqueAddressHeader

resent-cc:

AddressHeader

bcc:

UniqueAddressHeader

resent-bcc:

AddressHeader

from:

UniqueAddressHeader

resent-from:

AddressHeader

reply-to:

UniqueAddressHeader

mime-version:

MIMEVersionHeader

content-type:

ContentTypeHeader

content-disposition:

ContentDispositionHeader

content-transfer-encoding:

ContentTransferEncodingHeader

message-id:

MessageIDHeader

HeaderRegistry a les méthodes suivantes :

map_to_type(self, name, cls)

name est le nom de l'en-tête à faire correspondre. Il est converti en minuscules dans le registre. cls est la classe spécialisée à utiliser, avec base_class, pour créer la classe utilisée pour instancier les en-têtes qui correspondent à name.

__getitem__(name)

Construit et renvoie une classe pour gérer la création d'un en-tête name.

__call__(name, value)

Récupère l'en-tête spécialisé associé à name du registre (en utilisant default_class si name n'apparaît pas dans le registre) et le compose avec base_class pour produire une classe, appelle le constructeur de la classe construite, en lui passant la même liste d'arguments, et renvoie enfin l'instance de classe ainsi créée.

Les classes suivantes sont les classes utilisées pour représenter les données analysées à partir d'en-têtes structurés et peuvent, en général, être utilisées par un programme d'application pour construire des valeurs structurées à affecter à des en-têtes spécifiques.

class email.headerregistry.Address(display_name='', username='', domain='', addr_spec=None)

Classe utilisée pour représenter une adresse e-mail. La forme générale d'une adresse est :

[display_name] <username@domain>

ou :

username@domain

où chaque partie doit se conformer à des règles de syntaxe spécifiques énoncées dans la RFC 5322.

Pour plus de commodité, addr_spec peut être spécifié à la place de username et domain, username et domain sont alors analysés à partir de addr_spec. Une addr_spec doit être une chaîne correctement entre guillemets RFC ; si ce n'est pas le cas, Address lève une erreur. Les caractères Unicode sont autorisés et sont encodés proprement lors de la sérialisation. Cependant, selon les RFC, l’Unicode n'est pas autorisé dans la partie nom d'utilisateur de l'adresse.

display_name

Partie du nom d'affichage de l'adresse, le cas échéant, avec toutes les citations supprimées. Si l'adresse n'a pas de nom d'affichage, cet attribut est une chaîne vide.

username

Partie username de l'adresse, sans guillemets.

domain

Partie domain de l'adresse.

addr_spec

Partie username@domain de l'adresse, correctement citée pour une utilisation en tant qu'adresse nue (la deuxième forme illustrée ci-dessus). Cet attribut n'est pas modifiable.

__str__()

La valeur str de l'objet est l'adresse entre guillemets selon les règles de la RFC 5322, mais sans encodage de contenu pour les caractères non-ASCII.

Pour prendre en charge SMTP (RFC 5321), Address gère un cas particulier : si username et domain sont tous deux la chaîne vide (ou None), alors la valeur de chaîne de Address est <>.

class email.headerregistry.Group(display_name=None, addresses=None)

Classe utilisée pour représenter un groupe d'adresses. La forme générale d'un groupe d'adresses est :

display_name: [address-list];

Pour faciliter le traitement des listes d'adresses composées d'un mélange de groupes et d'adresses uniques, un Group peut également être utilisé pour représenter des adresses uniques qui ne font pas partie d'un groupe en définissant display_name sur None et en fournissant une liste de l'adresse unique sous la forme adresses.

display_name

display_name du groupe. Si c'est None et qu'il y a exactement une Adress dans adresses, alors le Group représente une seule adresse qui n'est pas dans un groupe.

addresses

n-uplet éventuellement vide d'objets Address représentant les adresses du groupe.

__str__()

La valeur str d'un Group est formatée selon la RFC 5322, mais sans encodage de contenu pour les caractères non-ASCII. Si display_name est None et qu'il y a une seule Address dans la liste addresses, la valeur str est la même que la str de cette seule Adress.

Notes