email.headerregistry: Anpassade rubrikobjekt

Källkod: Lib/email/headerregistry.py


Tillagd i version 3.6: [1]

Headers representeras av anpassade subklasser av str. Den särskilda klass som används för att representera ett visst huvud bestäms av header_factory i policy som gäller när huvudena skapas. Det här avsnittet dokumenterar den särskilda header_factory som implementerats av e-postpaketet för hantering av e-postmeddelanden som uppfyller kraven i RFC 5322, som inte bara tillhandahåller anpassade rubrikobjekt för olika rubriktyper, utan också tillhandahåller en tilläggsmekanism för program att lägga till sina egna anpassade rubriktyper.

När du använder något av de policyobjekt som härrör från EmailPolicy, produceras alla rubriker av HeaderRegistry och har BaseHeader som sista basklass. Varje header-klass har ytterligare en basklass som bestäms av typen av header. Många headers har t.ex. klassen UnstructuredHeader som sin andra basklass. Den specialiserade andra klassen för en header bestäms av namnet på headern med hjälp av en uppslagstabell som lagras i HeaderRegistry. Allt detta hanteras transparent för det typiska applikationsprogrammet, men gränssnitt tillhandahålls för att ändra standardbeteendet för användning av mer komplexa applikationer.

I avsnitten nedan dokumenteras först headerbasklasserna och deras attribut, därefter API:et för att ändra beteendet hos HeaderRegistry och slutligen de stödklasser som används för att representera data som analyseras från strukturerade headers.

class email.headerregistry.BaseHeader(name, value)

name och value skickas till BaseHeader från anropet header_factory. Strängvärdet för ett header-objekt är värdet fullt avkodat till unicode.

Denna basklass definierar följande skrivskyddade egenskaper:

name

Namnet på rubriken (den del av fältet som ligger före ’:’). Detta är exakt det värde som skickades i header_factory-anropet för name; dvs. skiftlägesskillnaden bevaras.

defects

En tupel av HeaderDefect-instanser som rapporterar eventuella RFC-överensstämmelseproblem som upptäckts under parsningen. E-postpaketet försöker vara komplett när det gäller att upptäcka problem med efterlevnad. Se modulen errors för en diskussion om vilka typer av defekter som kan rapporteras.

max_count

Det maximala antalet rubriker av denna typ som kan ha samma namn. Ett värde av None betyder obegränsat. Värdet för BaseHeader för detta attribut är None; det förväntas att specialiserade header-klasser åsidosätter detta värde efter behov.

BaseHeader tillhandahåller också följande metod, som anropas av e-postbibliotekskoden och i allmänhet inte bör anropas av applikationsprogram:

fold(*, policy)

Returnerar en sträng som innehåller linesep tecken som krävs för att vika headern korrekt enligt policy. En cte_type8bit kommer att behandlas som om den vore 7bit, eftersom rubriker inte får innehålla godtyckliga binära data. Om utf8 är False, kommer icke-ASCII-data att kodas enligt RFC 2047.

BaseHeader kan i sig inte användas för att skapa ett rubrikobjekt. Den definierar ett protokoll som varje specialiserad header samarbetar med för att producera header-objektet. Specifikt kräver BaseHeader att den specialiserade klassen tillhandahåller en classmethod`() med namnet parse. Denna metod anropas på följande sätt:

parse(string, kwds)

kwds är en ordbok som innehåller en förinitialiserad nyckel, defects. defects är en tom lista. Parse-metoden bör lägga till alla upptäckta defekter till denna lista. Vid återlämnandet måste ordlistan kwds innehålla värden för åtminstone nycklarna decoded och defects. decoded bör vara strängvärdet för rubriken (det vill säga rubrikvärdet helt avkodat till unicode). Parse-metoden bör anta att sträng kan innehålla innehållsöverföringskodade delar, men bör korrekt hantera alla giltiga Unicode-tecken också så att den kan parsa okodade rubrikvärden.

BaseHeader’s __new__ skapar sedan header-instansen och anropar dess init metod. Den specialiserade klassen behöver bara tillhandahålla en init-metod om den vill ställa in ytterligare attribut utöver de som tillhandahålls av BaseHeader själv. En sådan init-metod bör se ut så här:

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

Det vill säga, allt extra som den specialiserade klassen lägger till i kwds-ordlistan ska tas bort och hanteras, och det återstående innehållet i kw (och args) skickas till BaseHeader init-metoden.

class email.headerregistry.UnstructuredHeader

En ”ostrukturerad” header är standardtypen av header i RFC 5322. Alla rubriker som inte har en specificerad syntax behandlas som ostrukturerade. Det klassiska exemplet på ett ostrukturerat huvud är Subject-huvudet.

I RFC 5322, är en ostrukturerad header en körning av godtycklig text i ASCII teckenuppsättning. RFC 2047, har dock en RFC 5322 kompatibel mekanism för kodning av icke-ASCII text som ASCII tecken inom en header värde. När ett värde som innehåller kodade ord skickas till konstruktören, konverterar UnstructuredHeader parser sådana kodade ord till unicode, enligt RFC 2047 regler för ostrukturerad text. Parsern använder heuristik för att försöka avkoda vissa icke-kompatibla kodade ord. Defekter registreras i sådana fall, liksom defekter för problem som ogiltiga tecken inom de kodade orden eller den icke-kodade texten.

Denna rubriktyp innehåller inga ytterligare attribut.

class email.headerregistry.DateHeader

RFC 5322 specificerar ett mycket specifikt format för datum i e-postrubriker. Parsern DateHeader känner igen det datumformatet, samt känner igen ett antal varianter som ibland finns ”i naturen”.

Denna rubriktyp innehåller följande ytterligare attribut:

datetime

Om rubrikvärdet kan identifieras som ett giltigt datum i en eller annan form, kommer detta attribut att innehålla en datetime-instans som representerar detta datum. Om tidszonen för indatadatumet anges som -0000 (vilket indikerar att det är i UTC men inte innehåller någon information om källans tidszon), kommer datetime att vara en naiv datetime. Om en specifik tidszonförskjutning hittas (inklusive +0000), kommer datetime att innehålla en medveten datetime som använder datetime.timezone för att registrera tidszonförskjutningen.

Det avkodade värdet på rubriken bestäms genom att formatera datatiden enligt reglerna i RFC 5322, dvs. det sätts till:

email.utils.format_datetime(self.datetime)

När du skapar en DateHeader, kan värde vara datetime instans. Detta innebär t.ex. att följande kod är giltig och gör vad man förväntar sig:

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

Eftersom detta är en naiv datetime kommer den att tolkas som en UTC-tidsstämpel, och det resulterande värdet kommer att ha tidszonen -0000. Mycket mer användbart är att använda funktionen localtime() från modulen utils:

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

I det här exemplet ställs datumrubriken in på aktuell tid och aktuellt datum med aktuell tidszonsförskjutning.

class email.headerregistry.AddressHeader

Adressrubriker är en av de mest komplexa strukturerade rubriktyperna. Klassen AddressHeader tillhandahåller ett generiskt gränssnitt för alla adressrubriker.

Denna rubriktyp innehåller följande ytterligare attribut:

groups

En tupel av Group-objekt som kodar de adresser och grupper som finns i rubrikvärdet. Adresser som inte är en del av en grupp representeras i denna lista som enstaka adresser Groups vars display_name är None.

addresses

En tupel av Address-objekt som kodar alla individuella adresser från rubrikvärdet. Om rubrikvärdet innehåller några grupper, inkluderas de enskilda adresserna från gruppen i listan vid den punkt där gruppen förekommer i värdet (dvs. adresslistan ”plattas till” till en endimensionell lista).

Det decoded-värdet i rubriken kommer att ha alla kodade ord avkodade till unicode. idna-kodade domännamn avkodas också till unicode. Det decoded-värdet ställs in genom att joining str-värdet för elementen i attributet groups med ', '.

En lista med objekten Address och Group i valfri kombination kan användas för att ange värdet på ett adresshuvud. Group-objekt vars display_name är None tolkas som enskilda adresser, vilket gör att en adresslista kan kopieras med grupperna intakta genom att använda den lista som erhålls från groups-attributet i källhuvudet.

class email.headerregistry.SingleAddressHeader

En subklass av AddressHeader som lägger till ytterligare ett attribut:

address

Den enskilda adress som kodas av rubrikvärdet. Om rubrikvärdet faktiskt innehåller mer än en adress (vilket skulle vara ett brott mot RFC enligt standard policy), kommer åtkomst till detta attribut att resultera i ett ValueError.

Många av ovanstående klasser har också en Unique variant (t.ex. UniqueUnstructuredHeader). Den enda skillnaden är att i Unique-varianten är max_count satt till 1.

class email.headerregistry.MIMEVersionHeader

Det finns egentligen bara ett giltigt värde för rubriken MIME-Version, och det är 1.0. För att vara framtidssäker stöder denna rubrikklass andra giltiga versionsnummer. Om ett versionsnummer har ett giltigt värde enligt RFC 2045, så kommer rubrikobjektet att ha värden som inte är None för följande attribut:

version

Versionsnumret som en sträng, med eventuella blanksteg och/eller kommentarer borttagna.

major

Huvudversionsnumret som ett heltal

minor

Det mindre versionsnumret som ett heltal

class email.headerregistry.ParameterizedMIMEHeader

MIME-rubriker börjar alla med prefixet ”Content-”. Varje specifik header har ett visst värde, som beskrivs under klassen för den headern. Vissa kan också ta en lista med kompletterande parametrar, som har ett gemensamt format. Denna klass fungerar som en bas för alla MIME-rubriker som tar parametrar.

params

En ordlista som mappar parameternamn till parametervärden.

class email.headerregistry.ContentTypeHeader

En ParameterizedMIMEHeader-klass som hanterar Content-Type-huvudet.

content_type

Strängen för innehållstypen, i formatet maintype/subtype.

maintype
subtype
class email.headerregistry.ContentDispositionHeader

En ParameterizedMIMEHeader-klass som hanterar Content-Disposition-huvudet.

content_disposition

inline och attachment är de enda giltiga värdena som används i allmänhet.

class email.headerregistry.ContentTransferEncoding

Hanterar rubriken Content-Transfer-Encoding.

cte

Giltiga värden är 7bit, 8bit, base64 och quoted-printable. Se RFC 2045 för mer information.

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

Detta är den fabrik som används av EmailPolicy som standard. HeaderRegistry bygger den klass som används för att skapa en header-instans dynamiskt, med hjälp av base_class och en specialiserad klass som hämtas från ett register som den innehar. När ett visst headernamn inte finns i registret används den klass som anges av default_class som specialiserad klass. När use_default_map är True (standard) kopieras standardmappningen av headernamn till klasser in i registret under initialiseringen. base_class är alltid den sista klassen i den genererade klassens __bases__-lista.

Standardmappningarna är:

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 har följande metoder:

map_to_type(self, name, cls)

name är namnet på den header som ska mappas. Det kommer att konverteras till gemener i registret. cls är den specialiserade klass som ska användas tillsammans med base_class för att skapa den klass som används för att instansiera rubriker som matchar name.

__getitem__(name)

Konstruera och returnera en klass som hanterar skapandet av en header med namn.

__call__(name, value)

Hämtar den specialiserade header som associeras med namn från registret (med hjälp av default_class om namn inte finns i registret) och sätter ihop den med base_class för att skapa en klass, anropar den konstruerade klassens konstruktor med samma argumentlista och returnerar slutligen den klassinstans som skapats på detta sätt.

Följande klasser är de klasser som används för att representera data som analyseras från strukturerade rubriker och kan i allmänhet användas av ett applikationsprogram för att konstruera strukturerade värden som ska tilldelas specifika rubriker.

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

Den klass som används för att representera en e-postadress. Den allmänna formen av en adress är:

[display_name] <användarnamn@domän>

eller:

användarnamn@domän

där varje del måste överensstämma med specifika syntaxregler som anges i RFC 5322.

Som en bekvämlighet kan addr_spec anges i stället för användarnamn och domän, i vilket fall användarnamn och domän kommer att tolkas från addr_spec. En addr_spec måste vara en korrekt RFC-citerad sträng; om den inte är det kommer Address att ge upphov till ett fel. Unicode-tecken är tillåtna och kommer att vara egenskapskodade när de serialiseras. Enligt RFC är dock unicode inte tillåtet i användarnamnsdelen av adressen.

display_name

Eventuellt visningsnamn för adressen, med alla citattecken borttagna. Om adressen inte har något visningsnamn kommer detta attribut att vara en tom sträng.

username

”Användarnamn”-delen av adressen, med alla citattecken borttagna.

domain

Den del av adressen som kallas ”domän”.

addr_spec

Delen användarnamn@domän i adressen, korrekt citerad för användning som en ren adress (den andra formen visas ovan). Detta attribut är inte muterbart.

__str__()

Objektets str-värde är adressen citerad enligt RFC 5322-reglerna, men utan Content Transfer Encoding av några icke-ASCII-tecken.

För att stödja SMTP (RFC 5321) hanterar Address ett specialfall: om username och domain båda är den tomma strängen (eller None), så är strängvärdet för Address <>.

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

Den klass som används för att representera en adressgrupp. Den allmänna formen för en adressgrupp är:

display_name: [address-list];

För att underlätta bearbetningen av adresslistor som består av en blandning av grupper och enskilda adresser kan en Group också användas för att representera enskilda adresser som inte ingår i en grupp genom att sätta display_name till None och tillhandahålla en lista över de enskilda adresserna som addresses.

display_name

Gruppens display_name. Om det är None och det finns exakt en Address i addresses, representerar Group en enskild adress som inte ingår i någon grupp.

addresses

En eventuellt tom tupel av Address-objekt som representerar adresserna i gruppen.

__str__()

Värdet str för en Group formateras enligt RFC 5322, men utan Content Transfer Encoding av icke-ASCII-tecken. Om display_name är none och det finns en enda Address i listan addresses, kommer värdet str att vara detsamma som str för den enda Address.

Fotnoter