# `email.headerregistry` : objets d'en-tête personnalisés

Code source : Lib/email/headerregistry.py

Nouveau 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)

  C'est la fabrique utilisée par `EmailPolicy` par défaut. `HeaderRegistry` construit la classe utilisée pour créer dynamiquement une instance d'en-tête, en utilisant base_class et une classe spécialisée récupérée à partir d'un registre qu'il contient. Lorsqu'un nom d'en-tête donné n'apparaît pas dans le registre, la classe spécifiée par default_class est utilisée comme classe spécialisée. Lorsque use_default_map est `True` (valeur par défaut), la correspondance standard des noms d'en-tête aux classes est copiée dans le registre lors de l'initialisation. base_class est toujours la dernière classe dans la liste `__bases__` de la classe générée.

  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

[1]

Ajouté à l'origine dans 3.3 en tant que paquet provisoire