email.headerregistry: Benutzerdefinierte Header-Objekte

Quellcode: Lib/email/headerregistry.py


Hinzugefügt in Version 3.6: [1]

Header werden durch angepasste Unterklassen von str dargestellt. Die spezifische Klasse, die zur Darstellung eines bestimmten Headers verwendet wird, wird durch die header_factory der wirksamen policy bestimmt, wenn die Header erstellt werden. Dieser Abschnitt dokumentiert die spezifische header_factory, die vom email-Paket zur Verarbeitung von RFC 5322-konformen E-Mail-Nachrichten implementiert wird. Diese stellt nicht nur angepasste Header-Objekte für verschiedene Header-Typen bereit, sondern auch einen Erweiterungsmechanismus, damit Anwendungen ihre eigenen benutzerdefinierten Header-Typen hinzufügen können.

Bei Verwendung von Policy-Objekten, die von EmailPolicy abgeleitet sind, werden alle Header von HeaderRegistry erstellt und haben BaseHeader als ihre letzte Basisklasse. Jede Header-Klasse hat eine zusätzliche Basisklasse, die vom Typ des Headers bestimmt wird. Zum Beispiel haben viele Header die Klasse UnstructuredHeader als ihre andere Basisklasse. Die spezialisierte zweite Klasse für einen Header wird durch den Namen des Headers bestimmt, wobei eine Nachschlagetabelle in der HeaderRegistry gespeichert ist. All dies wird für das typische Anwendungsprogramm transparent verwaltet, aber Schnittstellen werden bereitgestellt, um das Standardverhalten für komplexere Anwendungen zu ändern.

Die folgenden Abschnitte dokumentieren zunächst die Basisklassen von Headern und ihre Attribute, gefolgt von der API zur Änderung des Verhaltens von HeaderRegistry und schließlich den unterstützenden Klassen, die zur Darstellung von Daten aus strukturierten Headern verwendet werden.

class email.headerregistry.BaseHeader(name, value)

name und value werden vom header_factory-Aufruf an BaseHeader übergeben. Der String-Wert jedes Header-Objekts ist der value, der vollständig in Unicode dekodiert wurde.

Diese Basisklasse definiert die folgenden schreibgeschützten Eigenschaften

name

Der Name des Headers (der Teil des Feldes vor dem „:“). Dies ist exakt der Wert, der im Aufruf von header_factory für name übergeben wird; das heißt, die Groß- und Kleinschreibung wird beibehalten.

defects

Ein Tupel von HeaderDefect-Instanzen, die alle bei der Analyse gefundenen RFC-Konformitätsprobleme melden. Das email-Paket versucht, die Konformitätsfragen vollständig zu erkennen. Siehe das Modul errors für eine Diskussion der Arten von Defekten, die gemeldet werden können.

max_count

Die maximale Anzahl von Headern dieses Typs, die denselben name haben können. Ein Wert von None bedeutet unbegrenzt. Der BaseHeader-Wert für dieses Attribut ist None; es wird erwartet, dass spezialisierte Header-Klassen diesen Wert bei Bedarf überschreiben.

BaseHeader bietet auch die folgende Methode, die vom email-Bibliotheks-Code aufgerufen wird und im Allgemeinen nicht von Anwendungsprogrammen aufgerufen werden sollte.

fold(*, policy)

Gibt einen String zurück, der linesep-Zeichen enthält, wie sie erforderlich sind, um den Header gemäß policy korrekt umzubrechen. Ein cte_type von 8bit wird so behandelt, als wäre er 7bit, da Header keine beliebigen Binärdaten enthalten dürfen. Wenn utf8 False ist, werden Nicht-ASCII-Daten gemäß RFC 2047 kodiert.

BaseHeader allein kann nicht zur Erstellung eines Header-Objekts verwendet werden. Es definiert ein Protokoll, mit dem jede spezialisierte Klasse zusammenarbeitet, um das Header-Objekt zu erzeugen. Insbesondere verlangt BaseHeader, dass die spezialisierte Klasse eine classmethod() namens parse bereitstellt. Diese Methode wird wie folgt aufgerufen:

parse(string, kwds)

kwds ist ein Wörterbuch, das einen vorinitialisierten Schlüssel, defects, enthält. defects ist eine leere Liste. Die Parse-Methode sollte alle erkannten Defekte zu dieser Liste hinzufügen. Nach der Rückgabe muss das Wörterbuch kwds mindestens die Schlüssel decoded und defects enthalten. decoded sollte der String-Wert für den Header sein (d. h. der Header-Wert, der vollständig in Unicode dekodiert wurde). Die Parse-Methode sollte davon ausgehen, dass string Content-Transfer-Encoding-Teile enthalten kann, aber alle gültigen Unicode-Zeichen korrekt behandeln, damit sie nicht kodierte Header-Werte parsen kann.

BaseHeader's __new__ erstellt dann die Header-Instanz und ruft ihre init-Methode auf. Die spezialisierte Klasse muss nur eine init-Methode bereitstellen, wenn sie zusätzliche Attribute über die von BaseHeader selbst bereitgestellten hinaus festlegen möchte. Eine solche init-Methode sollte wie folgt aussehen:

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

Das heißt, alles zusätzliche, das die spezialisierte Klasse in das Wörterbuch kwds einfügt, sollte entfernt und verarbeitet werden, und der verbleibende Inhalt von kw (und args) sollte an die BaseHeader init-Methode übergeben werden.

class email.headerregistry.UnstructuredHeader

Ein „unstrukturierter“ Header ist der Standardtyp des Headers in RFC 5322. Jeder Header, der keine spezifizierte Syntax hat, wird als unstrukturiert behandelt. Das klassische Beispiel für einen unstrukturierten Header ist der Subject-Header.

In RFC 5322 ist ein unstrukturierter Header eine Aneinanderreihung von beliebigen Texten im ASCII-Zeichensatz. RFC 2047 hat jedoch einen mit RFC 5322 kompatiblen Mechanismus zur Kodierung von Nicht-ASCII-Text als ASCII-Zeichen innerhalb eines Header-Werts. Wenn ein value, das kodierte Wörter enthält, an den Konstruktor übergeben wird, konvertiert der UnstructuredHeader-Parser solche kodierten Wörter in Unicode, wobei die Regeln von RFC 2047 für unstrukturierte Texte befolgt werden. Der Parser verwendet Heuristiken, um zu versuchen, bestimmte nicht konforme kodierte Wörter zu dekodieren. In solchen Fällen werden Defekte registriert, ebenso wie Defekte für Probleme wie ungültige Zeichen innerhalb der kodierten Wörter oder des nicht kodierten Textes.

Dieser Header-Typ bietet keine zusätzlichen Attribute.

class email.headerregistry.DateHeader

RFC 5322 gibt ein sehr spezifisches Format für Daten in E-Mail-Headern vor. Der DateHeader-Parser erkennt dieses Datumsformat und auch eine Reihe von alternativen Formen, die manchmal „in freier Wildbahn“ gefunden werden.

Dieser Header-Typ bietet die folgenden zusätzlichen Attribute

datetime

Wenn der Header-Wert als gültiges Datum einer oder anderer Form erkannt werden kann, enthält dieses Attribut eine datetime-Instanz, die dieses Datum repräsentiert. Wenn die Zeitzone des Eingabedatums als -0000 angegeben ist (was bedeutet, dass es in UTC ist, aber keine Informationen über die Quellzeitzone enthält), dann ist datetime ein naives datetime. Wenn ein spezifischer Zeitzonen-Offset gefunden wird (einschließlich +0000), dann enthält datetime ein aware datetime, das datetime.timezone verwendet, um den Zeitzonen-Offset zu speichern.

Der decoded-Wert des Headers wird durch Formatieren des datetime gemäß den Regeln von RFC 5322 bestimmt; das heißt, er wird gesetzt auf

email.utils.format_datetime(self.datetime)

Beim Erstellen eines DateHeader kann value eine datetime-Instanz sein. Dies bedeutet beispielsweise, dass der folgende Code gültig ist und das tut, was man erwarten würde.

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

Da dies ein naives datetime ist, wird es als UTC-Zeitstempel interpretiert und der resultierende Wert hat eine Zeitzone von -0000. Viel nützlicher ist die Verwendung der Funktion localtime() aus dem Modul utils.

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

Dieses Beispiel setzt den Datums-Header auf die aktuelle Zeit und das aktuelle Datum unter Verwendung des aktuellen Zeitzonen-Offsets.

class email.headerregistry.AddressHeader

Adress-Header sind einer der komplexesten strukturierten Header-Typen. Die Klasse AddressHeader bietet eine generische Schnittstelle zu jedem Adress-Header.

Dieser Header-Typ bietet die folgenden zusätzlichen Attribute

groups

Ein Tupel von Group-Objekten, die die im Header-Wert gefundenen Adressen und Gruppen kodieren. Adressen, die nicht Teil einer Gruppe sind, werden in dieser Liste als einzelne Adress-Groups dargestellt, deren display_name None ist.

addresses

Ein Tupel von Address-Objekten, die alle einzelnen Adressen aus dem Header-Wert kodieren. Wenn der Header-Wert Gruppen enthält, werden die einzelnen Adressen aus der Gruppe an der Stelle, an der die Gruppe im Wert vorkommt, in die Liste aufgenommen (d. h. die Liste der Adressen wird zu einer eindimensionalen Liste „abgeflacht“).

Der decoded-Wert des Headers enthält alle dekodierten kodierten Wörter in Unicode. idna-kodierte Domain-Namen werden ebenfalls in Unicode dekodiert. Der decoded-Wert wird durch Verknüpfen des str-Werts der Elemente des groups-Attributs mit ', ' gesetzt.

Eine Liste von Address- und Group-Objekten in beliebiger Kombination kann verwendet werden, um den Wert eines Adress-Headers festzulegen. Group-Objekte, deren display_name None ist, werden als einzelne Adressen interpretiert, was es ermöglicht, eine Adressliste mit intakten Gruppen zu kopieren, indem die aus dem groups-Attribut des Quell-Headers erhaltene Liste verwendet wird.

class email.headerregistry.SingleAddressHeader

Eine Unterklasse von AddressHeader, die ein zusätzliches Attribut hinzufügt

address

Die einzelne Adresse, die vom Header-Wert kodiert wird. Wenn der Header-Wert tatsächlich mehr als eine Adresse enthält (was unter der Standard- policy eine Verletzung der RFC wäre), führt der Zugriff auf dieses Attribut zu einem ValueError.

Viele der oben genannten Klassen haben auch eine Unique-Variante (zum Beispiel UniqueUnstructuredHeader). Der einzige Unterschied ist, dass in der Unique-Variante max_count auf 1 gesetzt ist.

class email.headerregistry.MIMEVersionHeader

Es gibt eigentlich nur einen gültigen Wert für den MIME-Version-Header, und das ist 1.0. Zur Zukunftssicherheit unterstützt diese Header-Klasse andere gültige Versionsnummern. Wenn eine Versionsnummer einen gültigen Wert gemäß RFC 2045 hat, dann hat das Header-Objekt nicht-None-Werte für die folgenden Attribute:

version

Die Versionsnummer als String, wobei etwaige Leerzeichen und/oder Kommentare entfernt wurden.

major

Die Hauptversionsnummer als Integer

minor

Die Nebenversionsnummer als Integer

class email.headerregistry.ParameterizedMIMEHeader

MIME-Header beginnen alle mit dem Präfix „Content-“. Jeder spezifische Header hat einen bestimmten Wert, der unter der Klasse für diesen Header beschrieben wird. Einige können auch eine Liste von ergänzenden Parametern annehmen, die ein gängiges Format haben. Diese Klasse dient als Basis für alle MIME-Header, die Parameter akzeptieren.

params

Ein Wörterbuch, das Parameternamen auf Parameterwerte abbildet.

class email.headerregistry.ContentTypeHeader

Eine Klasse vom Typ ParameterizedMIMEHeader, die den Header Content-Type verarbeitet.

content_type

Der Content-Type-String im Format maintype/subtype.

maintype
subtype
class email.headerregistry.ContentDispositionHeader

Eine Klasse vom Typ ParameterizedMIMEHeader, die den Header Content-Disposition verarbeitet.

content_disposition

inline und attachment sind die einzigen gebräuchlichen gültigen Werte.

class email.headerregistry.ContentTransferEncoding

Verarbeitet den Header Content-Transfer-Encoding.

cte

Gültige Werte sind 7bit, 8bit, base64 und quoted-printable. Siehe RFC 2045 für weitere Informationen.

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

Dies ist die Factory, die standardmäßig von EmailPolicy verwendet wird. HeaderRegistry erstellt dynamisch die Klasse, die zur Erstellung einer Header-Instanz verwendet wird, indem base_class und eine spezialisierte Klasse aus einem von ihr gehaltenen Registry verwendet werden. Wenn ein gegebener Header-Name nicht im Registry erscheint, wird die von default_class angegebene Klasse als spezialisierte Klasse verwendet. Wenn use_default_map True (Standard) ist, wird die Standardzuordnung von Header-Namen zu Klassen bei der Initialisierung in das Registry kopiert. base_class ist immer die letzte Klasse in der Liste __bases__ der generierten Klasse.

Die Standardzuordnungen sind:

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 hat die folgenden Methoden:

map_to_type(self, name, cls)

name ist der Name des Headers, der zugeordnet werden soll. Er wird im Registry in Kleinbuchstaben umgewandelt. cls ist die spezialisierte Klasse, die zusammen mit base_class verwendet wird, um die Klasse zur Instanziierung von Headern zu erstellen, die name entsprechen.

__getitem__(name)

Konstruiert und gibt eine Klasse zurück, die zur Erstellung eines name-Headers verwendet wird.

__call__(name, value)

Ruft den spezialisierten Header, der name zugeordnet ist, aus dem Registry ab (verwendet default_class, wenn name nicht im Registry vorkommt) und kombiniert ihn mit base_class, um eine Klasse zu erstellen. Ruft den Konstruktor der erstellten Klasse auf und übergibt ihr dieselbe Argumentenliste. Gibt schließlich die dadurch erstellte Klasseninstanz zurück.

Die folgenden Klassen sind die Klassen, die zur Darstellung von Daten aus strukturierten Headern verwendet werden und im Allgemeinen von einem Anwendungsprogramm zum Erstellen von strukturierten Werten zur Zuweisung an bestimmte Header verwendet werden können.

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

Die Klasse, die zur Darstellung einer E-Mail-Adresse verwendet wird. Die allgemeine Form einer Adresse lautet

[display_name] <username@domain>

oder

username@domain

wobei jeder Teil spezifischen Syntaxregeln entsprechen muss, die in RFC 5322 festgelegt sind.

Als Komfortfunktion kann addr_spec anstelle von username und domain angegeben werden. In diesem Fall werden username und domain aus addr_spec extrahiert. Eine addr_spec muss ein ordnungsgemäß RFC-kodierter String sein; wenn dies nicht der Fall ist, löst Address einen Fehler aus. Unicode-Zeichen sind zulässig und werden beim Serialisieren ordnungsgemäß kodiert. Gemäß den RFCs ist Unicode jedoch NICHT im Benutzernamen (username) der Adresse zulässig.

display_name

Der Anzeigeteil (display name) der Adresse, falls vorhanden, ohne jegliche Kodierung. Wenn die Adresse keinen Anzeigeteil hat, ist dieses Attribut ein leerer String.

username

Der username-Teil der Adresse, ohne jegliche Kodierung.

domain

Der domain-Teil der Adresse.

addr_spec

Der username@domain-Teil der Adresse, korrekt für die Verwendung als reine Adresse kodiert (die zweite oben gezeigte Form). Dieses Attribut ist nicht veränderbar.

__str__()

Der str-Wert des Objekts ist die Adresse, die gemäß den Regeln von RFC 5322 kodiert ist, jedoch ohne Content Transfer Encoding von Nicht-ASCII-Zeichen.

Zur Unterstützung von SMTP (RFC 5321) behandelt Address einen Sonderfall: Wenn username und domain beide leer sind (oder None), dann ist der String-Wert von Address <>.

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

Die Klasse, die zur Darstellung einer Adressgruppe verwendet wird. Die allgemeine Form einer Adressgruppe lautet

display_name: [address-list];

Um die Verarbeitung von Adresslisten zu erleichtern, die eine Mischung aus Gruppen und einzelnen Adressen enthalten, kann eine Group auch verwendet werden, um einzelne Adressen darzustellen, die keiner Gruppe angehören, indem display_name auf None gesetzt und eine Liste der einzelnen Adresse als addresses bereitgestellt wird.

display_name

Der display_name der Gruppe. Wenn er None ist und genau eine Address in addresses vorhanden ist, repräsentiert die Group eine einzelne Adresse, die keiner Gruppe angehört.

addresses

Ein möglicherweise leeres Tupel von Address-Objekten, die die Adressen in der Gruppe repräsentieren.

__str__()

Der str-Wert einer Group wird gemäß RFC 5322 formatiert, jedoch ohne Content Transfer Encoding von Nicht-ASCII-Zeichen. Wenn display_name null ist und sich eine einzelne Address in der addresses-Liste befindet, ist der str-Wert derselbe wie der str dieser einzelnen Address.

Fußnoten