email.parser: Parsen von E-Mail-Nachrichten

Quellcode: Lib/email/parser.py


Nachrichtenobjektstrukturen können auf zwei Arten erstellt werden: sie können von Grund auf neu erstellt werden, indem ein EmailMessage-Objekt erstellt, Header über die Dictionary-Schnittstelle hinzugefügt und Nutzdaten mit set_content() und verwandten Methoden hinzugefügt werden, oder sie können durch Parsen einer serialisierten Darstellung der E-Mail-Nachricht erstellt werden.

Das Paket email stellt einen Standard-Parser bereit, der die meisten E-Mail-Dokumentstrukturen, einschließlich MIME-Dokumente, versteht. Sie können dem Parser ein Bytes-, String- oder Dateiobjekt übergeben, und der Parser gibt Ihnen die Wurzel EmailMessage-Instanz der Objektstruktur zurück. Bei einfachen, nicht-MIME-Nachrichten ist die Nutzlast dieses Wurzelobjekts wahrscheinlich ein String, der den Text der Nachricht enthält. Bei MIME-Nachrichten gibt das Wurzelobjekt True von seiner Methode is_multipart() zurück, und die Unterteile können über die Methoden zur Nutzlastmanipulation, wie get_body(), iter_parts() und walk() abgerufen werden.

Es gibt tatsächlich zwei Parser-Schnittstellen zur Verfügung: die Parser API und die inkrementelle FeedParser API. Die Parser API ist am nützlichsten, wenn Sie den gesamten Text der Nachricht im Speicher haben oder wenn die gesamte Nachricht in einer Datei auf dem Dateisystem liegt. FeedParser ist besser geeignet, wenn Sie die Nachricht aus einem Stream lesen, der möglicherweise auf weitere Eingaben wartet (z. B. beim Lesen einer E-Mail-Nachricht von einem Socket). Der FeedParser kann die Nachricht inkrementell verarbeiten und parsen und gibt das Wurzelobjekt erst zurück, wenn Sie den Parser schließen.

Beachten Sie, dass der Parser in begrenztem Umfang erweitert werden kann und Sie natürlich Ihren eigenen Parser von Grund auf neu implementieren können. Die gesamte Logik, die den gebündelten Parser des Pakets email und die Klasse EmailMessage verbindet, ist in der Klasse Policy verkörpert. Daher kann ein benutzerdefinierter Parser Nachrichtsobjektbäume nach Bedarf erstellen, indem er benutzerdefinierte Versionen der entsprechenden Policy-Methoden implementiert.

FeedParser API

Der BytesFeedParser, importiert aus dem Modul email.feedparser, bietet eine API, die für das inkrementelle Parsen von E-Mail-Nachrichten geeignet ist, wie es beim Lesen des Textes einer E-Mail-Nachricht aus einer blockierenden Quelle (z. B. einem Socket) erforderlich wäre. Der BytesFeedParser kann natürlich verwendet werden, um eine E-Mail-Nachricht zu parsen, die vollständig in einem bytes-ähnlichen Objekt, einem String oder einer Datei enthalten ist, aber die BytesParser API ist für solche Anwendungsfälle möglicherweise praktischer. Die Semantik und die Ergebnisse der beiden Parser-APIs sind identisch.

Die API des BytesFeedParser ist einfach: Sie erstellen eine Instanz, füttern sie mit einer Reihe von Bytes, bis keine mehr vorhanden sind, und schließen dann den Parser, um das Wurzelnachrichtenobjekt abzurufen. Der BytesFeedParser ist bei der Verarbeitung von standardkonformen Nachrichten äußerst präzise und leistet sehr gute Arbeit beim Parsen nicht-konformer Nachrichten und liefert Informationen darüber, wie eine Nachricht als fehlerhaft eingestuft wurde. Er füllt das Attribut defects eines Nachrichtenobjekts mit einer Liste aller gefundenen Probleme. Die Liste der Defekte, die er finden kann, finden Sie im Modul email.errors.

Hier ist die API für BytesFeedParser

class email.parser.BytesFeedParser(_factory=None, *, policy=policy.compat32)

Erstellt eine Instanz von BytesFeedParser. Das optionale _factory ist ein aufrufbares Objekt ohne Argumente; wenn es nicht angegeben wird, wird die message_factory der policy verwendet. _factory wird aufgerufen, wenn ein neues Nachrichtenobjekt benötigt wird.

Wenn policy angegeben ist, werden die von ihr festgelegten Regeln verwendet, um die Darstellung der Nachricht zu aktualisieren. Wenn policy nicht gesetzt ist, wird die compat32-Policy verwendet, die die Abwärtskompatibilität mit der Python 3.2-Version des E-Mail-Pakets aufrechterhält und Message als Standard-Factory bereitstellt. Alle anderen Policies stellen EmailMessage als Standard-_factory bereit. Weitere Informationen darüber, was policy sonst noch steuert, finden Sie in der Dokumentation zu policy.

Hinweis: **Das Policy-Schlüsselwort sollte immer angegeben werden**; der Standardwert wird in einer zukünftigen Python-Version zu email.policy.default geändert.

Hinzugefügt in Version 3.2.

Geändert in Version 3.3: Das Schlüsselwort policy wurde hinzugefügt.

Geändert in Version 3.6: _factory hat standardmäßig die message_factory der Policy.

feed(data)

Füttert den Parser mit weiteren Daten. data sollte ein bytes-ähnliches Objekt sein, das eine oder mehrere Zeilen enthält. Die Zeilen können teilweise sein, und der Parser wird solche unvollständigen Zeilen ordnungsgemäß zusammenfügen. Die Zeilen können alle drei gängigen Zeilenenden aufweisen: Wagenrücklauf, Zeilenvorschub oder Wagenrücklauf und Zeilenvorschub (sie können sogar gemischt sein).

close()

Schließt das Parsen aller zuvor zugeführten Daten ab und gibt das Wurzelnachrichtenobjekt zurück. Was passiert, wenn feed() nach dem Aufruf dieser Methode aufgerufen wird, ist undefiniert.

class email.parser.FeedParser(_factory=None, *, policy=policy.compat32)

Funktioniert wie BytesFeedParser, aber die Eingabe für die Methode feed() muss ein String sein. Dies ist von begrenztem Nutzen, da eine solche Nachricht nur gültig sein kann, wenn sie nur ASCII-Text enthält oder, wenn utf8 True ist, keine binären Anhänge enthält.

Geändert in Version 3.3: Das Schlüsselwort policy wurde hinzugefügt.

Parser API

Die Klasse BytesParser, importiert aus dem Modul email.parser, bietet eine API, die zum Parsen einer Nachricht verwendet werden kann, wenn der vollständige Inhalt der Nachricht in einem bytes-ähnlichen Objekt oder einer Datei verfügbar ist. Das Modul email.parser bietet auch Parser zum Parsen von Strings und reine Header-Parser, BytesHeaderParser und HeaderParser, die verwendet werden können, wenn Sie nur an den Headern der Nachricht interessiert sind. BytesHeaderParser und HeaderParser können in diesen Situationen viel schneller sein, da sie nicht versuchen, den Nachrichtenkörper zu parsen, sondern die Nutzlast auf den rohen Körper setzen.

class email.parser.BytesParser(_class=None, *, policy=policy.compat32)

Erstellt eine Instanz von BytesParser. Die Argumente _class und policy haben die gleiche Bedeutung und Semantik wie die Argumente _factory und policy des Konstruktors von BytesFeedParser.

Hinweis: **Das Policy-Schlüsselwort sollte immer angegeben werden**; der Standardwert wird in einer zukünftigen Python-Version zu email.policy.default geändert.

Geändert in Version 3.3: Das Argument strict, das in 2.4 als veraltet galt, wurde entfernt. Das Schlüsselwort policy wurde hinzugefügt.

Geändert in Version 3.6: _class hat standardmäßig die message_factory der Policy.

parse(fp, headersonly=False)

Liest alle Daten aus dem binären dateiähnlichen Objekt fp, parst die resultierenden Bytes und gibt das Nachrichtenobjekt zurück. fp muss sowohl die Methode readline() als auch die Methode read() unterstützen.

Die in fp enthaltenen Bytes müssen als Block von RFC 5322 (oder, wenn utf8 True ist, RFC 6532) formatiert sein, einschließlich Zeilenumbrüchen für fortlaufende Header, optional vorangestellt von einem Envelope-Header. Der Header-Block wird entweder durch das Ende der Daten oder durch eine Leerzeile beendet. Nach dem Header-Block folgt der Body der Nachricht (der MIME-kodierte Unterteile enthalten kann, einschließlich Unterteilen mit einer Content-Transfer-Encoding von 8bit).

Das optionale headersonly ist ein Flag, das angibt, ob das Parsen nach dem Lesen der Header gestoppt werden soll oder nicht. Der Standardwert ist False, was bedeutet, dass der gesamte Inhalt der Datei geparst wird.

parsebytes(bytes, headersonly=False)

Ähnlich wie die Methode parse(), nimmt sie jedoch ein bytes-ähnliches Objekt anstelle eines dateiähnlichen Objekts. Der Aufruf dieser Methode für ein bytes-ähnliches Objekt ist gleichbedeutend mit dem Umwickeln von bytes in eine BytesIO-Instanz und dem Aufrufen von parse().

Das optionale headersonly ist dasselbe wie bei der Methode parse().

Hinzugefügt in Version 3.2.

class email.parser.BytesHeaderParser(_class=None, *, policy=policy.compat32)

Exakt wie BytesParser, aber headersonly hat standardmäßig den Wert True.

Hinzugefügt in Version 3.3.

class email.parser.Parser(_class=None, *, policy=policy.compat32)

Diese Klasse ist parallel zu BytesParser, behandelt aber String-Eingaben.

Geändert in Version 3.3: Das Argument strict wurde entfernt. Das Schlüsselwort policy wurde hinzugefügt.

Geändert in Version 3.6: _class hat standardmäßig die message_factory der Policy.

parse(fp, headersonly=False)

Liest alle Daten aus dem Text-Modus dateiähnlichen Objekt fp, parst den resultierenden Text und gibt das Wurzelnachrichtenobjekt zurück. fp muss sowohl die Methode readline() als auch die Methode read() für dateiähnliche Objekte unterstützen.

Abgesehen von der Textmodus-Anforderung funktioniert diese Methode wie BytesParser.parse().

parsestr(text, headersonly=False)

Ähnlich wie die Methode parse(), nimmt sie jedoch ein String-Objekt anstelle eines dateiähnlichen Objekts. Der Aufruf dieser Methode für einen String ist gleichbedeutend mit dem Umwickeln von text in eine StringIO-Instanz und dem Aufrufen von parse().

Das optionale headersonly ist dasselbe wie bei der Methode parse().

class email.parser.HeaderParser(_class=None, *, policy=policy.compat32)

Exakt wie Parser, aber headersonly hat standardmäßig den Wert True.

Da das Erstellen einer Nachrichtenobjektstruktur aus einem String oder einem Dateiobjekt eine sehr häufige Aufgabe ist, werden vier Funktionen als Bequemlichkeit bereitgestellt. Sie sind im Namensraum des Top-Level-Pakets email verfügbar.

email.message_from_bytes(s, _class=None, *, policy=policy.compat32)

Gibt eine Nachrichtenobjektstruktur aus einem bytes-ähnlichen Objekt zurück. Dies ist äquivalent zu BytesParser().parsebytes(s). Die optionalen Argumente _class und policy werden wie beim Konstruktor der Klasse BytesParser interpretiert.

Hinzugefügt in Version 3.2.

Geändert in Version 3.3: Das Argument strict wurde entfernt. Das Schlüsselwort policy wurde hinzugefügt.

email.message_from_binary_file(fp, _class=None, *, policy=policy.compat32)

Gibt eine Nachrichtenobjektstruktur aus einer geöffneten binären Datei zurück. Dies ist äquivalent zu BytesParser().parse(fp). _class und policy werden wie beim Konstruktor der Klasse BytesParser interpretiert.

Hinzugefügt in Version 3.2.

Geändert in Version 3.3: Das Argument strict wurde entfernt. Das Schlüsselwort policy wurde hinzugefügt.

email.message_from_string(s, _class=None, *, policy=policy.compat32)

Gibt eine Nachrichtenobjektstruktur aus einem String zurück. Dies ist äquivalent zu Parser().parsestr(s). _class und policy werden wie beim Konstruktor der Klasse Parser interpretiert.

Geändert in Version 3.3: Das Argument strict wurde entfernt. Das Schlüsselwort policy wurde hinzugefügt.

email.message_from_file(fp, _class=None, *, policy=policy.compat32)

Gibt eine Nachrichtenobjektstruktur aus einer geöffneten Datei zurück. Dies ist äquivalent zu Parser().parse(fp). _class und policy werden wie beim Konstruktor der Klasse Parser interpretiert.

Geändert in Version 3.3: Das Argument strict wurde entfernt. Das Schlüsselwort policy wurde hinzugefügt.

Geändert in Version 3.6: _class hat standardmäßig die message_factory der Policy.

Hier ist ein Beispiel, wie Sie message_from_bytes() in einer interaktiven Python-Sitzung verwenden könnten

>>> import email
>>> msg = email.message_from_bytes(myBytes)

Zusätzliche Hinweise

Hier sind einige Hinweise zu den Parsing-Semantiken

  • Die meisten nicht-multipart-Nachrichten werden als einzelnes Nachrichtenobjekt mit einer String-Nutzlast geparst. Diese Objekte geben False für is_multipart() zurück, und iter_parts() gibt eine leere Liste zurück.

  • Alle multipart-Nachrichten werden als Container-Nachrichtenobjekt mit einer Liste von Unter-Nachrichtenobjekten für ihre Nutzlast geparst. Die äußere Container-Nachricht gibt True für is_multipart() zurück, und iter_parts() gibt eine Liste von Unterteilen zurück.

  • Die meisten Nachrichten mit einem Content-Typ von message/* (wie message/delivery-status und message/rfc822) werden ebenfalls als Container-Objekte mit einer Listen-Nutzlast der Länge 1 geparst. Ihre Methode is_multipart() gibt True zurück. Das einzelne Element, das von iter_parts() geliefert wird, ist ein Unter-Nachrichtenobjekt.

  • Einige nicht-standardkonforme Nachrichten sind möglicherweise nicht intern konsistent bezüglich ihrer multipart-Eigenschaft. Solche Nachrichten haben möglicherweise einen Content-Type-Header vom Typ multipart, aber ihre Methode is_multipart() kann False zurückgeben. Wenn solche Nachrichten mit dem FeedParser geparst wurden, haben sie eine Instanz der Klasse MultipartInvariantViolationDefect in ihrer Attributliste defects. Weitere Details finden Sie in email.errors.