email.headerregistry: اشیاء سرآیند سفارشی¶
کد منبع: Lib/email/headerregistry.py
اضافه شده در نسخهی 3.6: [1]
سرآیندها با زیرکلاسهای سفارشی از str نمایش داده میشوند. کلاس خاصی که برای نمایش یک سرآیند مشخص به کار میرود، توسط header_factory از policy که در زمان ایجاد سرآیندها معتبر است، تعیین میشود. این بخش header_factory خاصی را مستند میکند که توسط بسته email برای مدیریت پیامهای ایمیل منطبق با RFC 5322 پیادهسازی شده است و نهتنها اشیای سرآیند سفارشی برای انواع مختلف سرآیند فراهم میکند، بلکه سازوکار توسعهای برای برنامهها فراهم میکند تا انواع سرآیند سفارشی خود را اضافه کنند.
هنگام استفاده از هر یک از اشیاء سیاست مشتقشده از EmailPolicy، تمام سرآیندها توسط HeaderRegistry تولید میشوند و BaseHeader را بهعنوان آخرین کلاس پایه خود دارند. هر کلاس سرآیند یک کلاس پایه اضافی دارد که بر اساس نوع سرآیند تعیین میشود. برای مثال، بسیاری از سرآیندها کلاس UnstructuredHeader را بهعنوان کلاس پایه دیگر خود دارند. کلاس دوم تخصصی برای یک سرآیند، با استفاده از جدول جستجویی که در HeaderRegistry ذخیرهشده است، بر اساس نام سرآیند تعیین میشود. همه این موارد برای برنامه کاربردی معمول بهصورت شفاف مدیریت میشوند، اما رابطهایی برای تغییر رفتار پیشفرض جهت استفاده در برنامههای پیچیدهتر فراهم شدهاند.
بخشهای زیر ابتدا کلاسهای پایهی سرآیند و ویژگیهای آنها را مستند میکنند، سپس به API برای تغییر رفتار HeaderRegistry میپردازند، و در نهایت کلاسهای پشتیبانی مورد استفاده برای بازنمایی دادههای تجزیهشده از سرآیندهای ساختاریافته را پوشش میدهند.
- class email.headerregistry.BaseHeader(name, value)¶
name و value از فراخوانی
header_factoryبهBaseHeaderپاس داده میشوند. مقدار رشتهی هر شیء سرآیند، value بهصورت کامل کدگشاییشده به یک رشته است.این کلاس پایه، ویژگیهای فقطخواندنی زیر را تعریف میکند:
- name¶
نام سرآیند (بخش فیلد پیش از ':'). این دقیقاً همان مقداری است که بهعنوان name در فراخوانی
header_factoryارسال شده است؛ یعنی بزرگی و کوچکی حروف حفظ میشود.
- defects¶
یک تاپل از نمونههای
HeaderDefectکه هر مشکل انطباق با RFC را که در حین تجزیه یافت میشود، گزارش میکنند. بستهی email تلاش میکند در تشخیص مسائل انطباق کامل باشد. برای بحثی در مورد انواع نقصهایی که ممکن است گزارش شوند، ماژولerrorsرا ببینید.
- max_count¶
حداکثر تعداد سرآیندهای این نوع که میتوانند
nameیکسانی داشته باشند. مقدارNoneبه معنای نامحدود است. مقدار این ویژگی درBaseHeaderبرابرNoneاست؛ انتظار میرود کلاسهای سرآیند تخصصی این مقدار را در صورت نیاز بازنویسی کنند.
BaseHeaderهمچنین متد زیر را ارائه میدهد، که توسط کد کتابخانه ایمیل فراخوانی میشود و بهطور کلی نباید توسط برنامههای کاربردی فراخوانی شود:- fold(*, policy)¶
رشتهای حاوی نویسههای
linesepبهمیزان لازم برای تا کردن صحیح سرآیند مطابق policy برمیگرداند.cte_typeبا مقدار8bitبهصورت7bitدر نظر گرفته میشود، زیرا سرآیندها نمیتوانند حاوی دادههای دودویی دلخواه باشند. اگرutf8برابرFalseباشد، دادههای غیر ASCII طبق RFC 2047 کدگذاری میشوند.
BaseHeaderبهتنهایی نمیتواند برای ایجاد یک شیء سرآیند به کار رود. این کلاس پروتکلی را تعریف میکند که هر سرآیند تخصصی برای ایجاد شیء سرآیند با آن همکاری میکند. بهطور مشخص،BaseHeaderالزام میکند که کلاس تخصصی یکclassmethod()به نامparseفراهم کند. این متد بهصورت زیر فراخوانی میشود:parse(string, kwds)
kwdsیک دیکشنری است که حاوی یک کلید از پیش مقداردهیشده،defectsمیباشد.defectsیک فهرست خالی است. متد parse باید هر عیب شناساییشده را به این فهرست اضافه کند. در بازگشت، دیکشنریkwdsباید حاوی مقادیر برای حداقل کلیدهایdecoded،defectsوparse_treeباشد.decodedباید مقدار رشته برای سرآیند باشد (یعنی مقدار سرآیند بهصورت کامل کدگشاییشده به یک رشته).parse_treeبه درخت تجزیه حاصل از تجزیه سرآیند تنظیم میشود. متد parse باید فرض کند که string ممکن است حاوی بخشهای کدگذاریشده content-transfer باشد، اما باید نویسههای معتبر یونیکد را نیز بهدرستی مدیریت کند تا بتواند مقادیر سرآیند بدون کدگذاری را تجزیه کند.سپس
__new__BaseHeaderنمونهی سرآیند را ایجاد میکند و متدinitآن را فراخوانی میکند. کلاس تخصصی تنها در صورتی لازم است یک متدinitارائه کند که بخواهد ویژگیهای اضافی، فراتر از آنچه خودBaseHeaderفراهم میکند، تنظیم کند. چنین متدinitباید به این صورت باشد:def init(self, /, *args, **kw): self._myattr = kw.pop('myattr') super().init(*args, **kw)
یعنی هر چیز اضافی که کلاس تخصصی در دیکشنری
kwdsقرار میدهد باید حذف و مدیریت شود، و محتوای باقیماندهیkw(وargs) به متدinitازBaseHeaderارسال شود.
- class email.headerregistry.UnstructuredHeader¶
یک سرآیند «بدون ساختار»، نوع پیشفرض سرآیند در RFC 5322 است. هر سرآیندی که سینتکس مشخصی نداشته باشد، بدون ساختار تلقی میشود. یک نمونه کلاسیک از سرآیند بدون ساختار، سرآیند Subject است.
در RFC 5322، یک سرآیند بدون ساختار، یک دنباله از متن دلخواه در مجموعه نویسههای اسکی است. اما RFC 2047 یک مکانیزم سازگار با RFC 5322 برای کدگذاری متن غیر اسکی به عنوان نویسههای اسکی در یک مقدار سرآیند دارد. وقتی یک value حاوی واژههای کدگذاریشده به سازنده پاس داده میشود، پارسر
UnstructuredHeaderچنین واژههای کدگذاریشده را به یک رشته تبدیل میکند، با دنبالهی قوانین RFC 2047 برای متن بدون ساختار. پارسر از ابتکارها برای تلاش در کدگشایی واژههای کدگذاریشده ناسازگار استفاده میکند. عیوب در چنین مواردی ثبت میشوند، همانند عیوب برای مواردی مانند نویسههای نامعتبر در واژههای کدگذاریشده یا متن بدون کدگذاری.این نوع سرآیند، هیچ ویژگی اضافهای ارائه نمیدهد.
- class email.headerregistry.DateHeader¶
RFC 5322 قالب بسیار مشخصی را برای تاریخها در سرآیندهای ایمیل تعیین میکند. پارسر
DateHeaderآن قالب تاریخ و همچنین تعدادی از صورتهای متفاوت را که گاهی «در عمل» یافت میشوند، تشخیص میدهد.این نوع سرآیند، ویژگیهای اضافی زیر را فراهم میکند:
- datetime¶
اگر مقدار سرآیند بتواند بهعنوان یک تاریخ معتبر در یکی از قالبها تشخیص داده شود، این ویژگی شامل یک نمونه
datetimeخواهد بود که نشاندهنده آن تاریخ است. اگر منطقه زمانی تاریخ ورودی بهصورت-0000مشخص شده باشد (که نشان میدهد در UTC است اما حاوی اطلاعاتی درباره منطقه زمانی منبع نیست)، آنگاهdatetimeیکdatetimeساده خواهد بود. اگر یک آفست منطقه زمانی مشخص یافت شود (از جمله+0000)، آنگاهdatetimeشامل یکdatetimeآگاه خواهد بود که ازdatetime.timezoneبرای ثبت آفست منطقه زمانی استفاده میکند.
مقدار
decodedسرآیند با قالببندیdatetimeمطابق قواعد RFC 5322 تعیین میشود؛ یعنی، بهصورت زیر تنظیم میشود:email.utils.format_datetime(self.datetime)
هنگام ایجاد یک
DateHeader، value میتواند نمونهای ازdatetimeباشد. این بدان معناست که، برای مثال، کد زیر معتبر است و همان کاری را که انتظار میرود انجام میدهد:msg['Date'] = datetime(2011, 7, 15, 21)
از آنجا که این یک
datetimeساده (naive) است، بهعنوان یک مهر زمانی UTC تفسیر میشود و مقدار حاصل دارای منطقه زمانی-0000خواهد بود. بسیار مفیدتر آن است که از تابعlocaltime()در ماژولutilsاستفاده کنید:msg['Date'] = utils.localtime()
این مثال سرآیند تاریخ را با استفاده از آفست منطقهی زمانی (timezone offset) فعلی، روی زمان و تاریخ فعلی تنظیم میکند.
- class email.headerregistry.AddressHeader¶
سرآیندهای نشانی یکی از پیچیدهترین انواع سرآیندهای ساختاریافته هستند. کلاس
AddressHeaderیک رابط عام برای هر سرآیند نشانی ارائه میدهد.این نوع سرآیند، ویژگیهای اضافی زیر را فراهم میکند:
- groups¶
یک تاپل از اشیای
Groupکه نشانیها و گروههای یافتشده در مقدار سرآیند را کدگذاری میکنند. نشانیهایی که بخشی از یک گروه نیستند، در این فهرست بهصورتGroupsهای تکنشانی بازنمایی میشوند کهdisplay_nameآنهاNoneاست.
- addresses¶
تاپلی از اشیای
Addressکه همهی نشانیهای منفردِ موجود در مقدار سرایند را کدگذاری میکنند. اگر مقدار سرایند شامل گروهی باشد، نشانیهای منفردِ آن گروه در نقطهای که گروه در مقدار ظاهر میشود، در فهرست گنجانده میشوند (یعنی فهرست نشانیها به یک فهرست یکبعدی «تختشده» تبدیل میشود).
مقدار
decodedسرآیند تمام واژههای کدگذاریشده را به یک رشته کدگشایی شده خواهد داشت. نامهای دامنه کدگذاریشدهidnaنیز به یک رشته کدگشایی میشوند. مقدارdecodedبا الحاق مقدارstrالمانهای ویژگیgroupsبا', 'تنظیم میشود.میتوان از فهرستی از اشیاء
AddressوGroupدر هر ترکیبی برای تنظیم مقدار یک سرآیند نشانی استفاده کرد. اشیاءGroupکهdisplay_nameآنهاNoneاست، بهعنوان نشانیهای منفرد تعبیر میشوند؛ این امر امکان میدهد یک فهرست نشانی با حفظ گروهها، با استفاده از فهرستی که از ویژگیgroupsسرآیند مبدأ به دست میآید، کپی شود.
- class email.headerregistry.SingleAddressHeader¶
زیرکلاسی از
AddressHeaderکه یک ویژگی اضافی میافزاید:- address¶
تنها نشانی کدگذاریشده توسط مقدار سرآیند. اگر مقدار سرآیند در واقع شامل بیش از یک نشانی باشد (که تحت
policyپیشفرض، نقض RFC خواهد بود)، دسترسی به این ویژگی منجر بهValueErrorخواهد شد.
بسیاری از کلاسهای فوق همچنین دارای یک گونهی Unique هستند (برای مثال، UniqueUnstructuredHeader). تنها تفاوت این است که در گونهی Unique، max_count روی ۱ تنظیم شده است.
- class email.headerregistry.MIMEVersionHeader¶
در واقع تنها یک مقدار معتبر برای سرآیند MIME-Version وجود دارد، و آن
1.0است. برای سازگاری با آینده، این کلاس سرآیند از سایر شمارههای نسخه معتبر نیز پشتیبانی میکند. اگر یک شماره نسخه مقدار معتبری مطابق RFC 2045 داشته باشد، شیء سرآیند برای ویژگیهای زیر مقادیر غیرNoneخواهد داشت:- version¶
شماره نسخه بهصورت یک رشته، با حذف هرگونه فضای سفید و/یا کامنت.
- major¶
شماره نسخه اصلی بهصورت عدد صحیح
- minor¶
شماره نسخه فرعی بهصورت عدد صحیح
- class email.headerregistry.ParameterizedMIMEHeader¶
همه سرآیندهای MIME با پیشوند 'Content-' شروع میشوند. هر سرآیند خاص، مقدار معینی دارد که در ذیل کلاس مربوط به آن سرآیند توضیح داده شده است. برخی نیز میتوانند فهرستی از پارامترهای تکمیلی را بپذیرند که قالب مشترکی دارند. این کلاس بهعنوان پایهای برای همه سرآیندهای MIME که پارامتر میپذیرند، عمل میکند.
- params¶
یک دیکشنری که نامهای پارامتر را به مقادیر پارامتر نگاشت میکند.
تغییر یافته در نسخهی 3.15: It is now a
frozendictinstead of atypes.MappingProxyType.
- class email.headerregistry.ContentTypeHeader¶
یک کلاس
ParameterizedMIMEHeaderکه سرآیند Content-Type را مدیریت میکند.- content_type¶
رشتهی نوع محتوا، در قالب
maintype/subtype.
- maintype¶
- subtype¶
- class email.headerregistry.ContentDispositionHeader¶
یک کلاس
ParameterizedMIMEHeaderکه سرآیند Content-Disposition را مدیریت میکند.- content_disposition¶
تنها مقادیر معتبرِ رایج،
inlineوattachmentهستند.
- class email.headerregistry.ContentTransferEncodingHeader¶
سرآیند Content-Transfer-Encoding را مدیریت میکند.
- class email.headerregistry.HeaderRegistry(base_class=BaseHeader, default_class=UnstructuredHeader, use_default_map=True)¶
این کارخانهای است که
EmailPolicyبهطور پیشفرض از آن استفاده میکند.HeaderRegistryبا استفاده از base_class و یک کلاس تخصصی بازیابیشده از رجیستری که در اختیار دارد، بهصورت پویا کلاسی را میسازد که برای ایجاد یک نمونه سرآیند استفاده میشود. هنگامی که یک نام سرآیند معین در رجیستری وجود نداشته باشد، کلاس مشخصشده توسط default_class بهعنوان کلاس تخصصی استفاده میشود. هنگامی که use_default_map برابرTrueباشد (مقدار پیشفرض)، نگاشت استاندارد نامهای سرآیند به کلاسها در حین مقداردهی اولیه به رجیستری کپی میشود. base_class همیشه آخرین کلاس در فهرست__bases__کلاس ساختهشده است.نگاشتهای پیشفرض عبارتند از:
- 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متدهای زیر را دارد:- map_to_type(self, name, cls)¶
name نام سرآیندی است که باید نگاشت شود. این نام در رجیستری به حروف کوچک تبدیل میشود. cls کلاس تخصصی است که به همراه base_class، برای ایجاد کلاسی به کار میرود که سرآیندهای منطبق با name را نمونهسازی میکند.
- __getitem__(name)¶
یک کلاس را برای مدیریت ایجاد سرآیند name بسازید و برگردانید.
- __call__(name, value)¶
سرآیند اختصاصی مرتبط با name را از رجیستری بازیابی میکند (اگر name در رجیستری وجود نداشته باشد، از default_class استفاده میشود) و آن را با base_class ترکیب میکند تا کلاسی تولید شود، سازندهی کلاس ساختهشده را با همان فهرست آرگومانها فراخوانی میکند و در نهایت نمونهی کلاس ایجادشده از این طریق را برمیگرداند.
کلاسهای زیر کلاسهایی هستند که برای نمایش دادههای تجزیهشده از سرآیندهای ساختیافته استفاده میشوند و بهطور کلی یک برنامه کاربردی میتواند از آنها برای ساخت مقادیر ساختیافته جهت انتساب به سرآیندهای مشخص استفاده کند.
- class email.headerregistry.Address(display_name='', username='', domain='', addr_spec=None)¶
کلاسی که برای نمایش یک نشانی ایمیل استفاده میشود. شکل کلی یک نشانی به این صورت است:
[display_name] <username@domain>
یا:
username@domain
که هر بخش باید با قواعد سینتکسی خاصی که در RFC 5322 تشریح شده است مطابقت داشته باشد.
به عنوان یک راحتی، addr_spec میتواند به جای username و domain مشخص شود، در این صورت username و domain از addr_spec تجزیه خواهند شد. یک addr_spec باید یک رشته نقلقولشده RFC مناسب باشد؛ اگر نباشد
Addressخطا خواهد داد. نویسههای یونیکد مجاز هستند و هنگام سریالسازی بهصورت مناسب کدگذاری میشوند. با این حال، طبق RFCها، یونیکد در بخش نامکاربری آدرس مجاز نیست.- display_name¶
بخش نام نمایشی نشانی، در صورت وجود، با حذف تمام علامتهای نقلقول. اگر نشانی نام نمایشی نداشته باشد، این ویژگی یک رشته خالی خواهد بود.
- username¶
بخش
usernameاز نشانی، با حذف تمام علامتهای نقلقول.
- domain¶
بخش
domainاز نشانی.
- addr_spec¶
بخش
username@domainاز نشانی، که بهدرستی در علامت نقلقول قرار گرفته است تا بهعنوان یک نشانی ساده (دومین شکل نشاندادهشده در بالا) استفاده شود. این ویژگی تغییرپذیر نیست.
- __str__()¶
مقدار
strشیء، نشانی نقلقولشده مطابق قواعد RFC 5322 است، اما بدون کدگذاری انتقال محتوا (Content Transfer Encoding) برای هیچیک از نویسههای غیر ASCII.
برای پشتیبانی از SMTP (RFC 5321)،
Addressیک حالت خاص را مدیریت میکند: اگرusernameوdomainهر دو رشته خالی (یاNone) باشند، مقدار رشتهایAddressبرابر<>است.
- class email.headerregistry.Group(display_name=None, addresses=None)¶
کلاسی که برای بازنمایی یک گروه نشانی استفاده میشود. شکل کلی یک گروه نشانی به این صورت است:
display_name: [address-list];
برای سهولت در پردازش فهرستهایی از نشانیها که شامل ترکیبی از گروهها و نشانیهای تکی هستند، میتوان از
Groupهمچنین برای نمایش نشانیهای تکی که بخشی از یک گروه نیستند استفاده کرد؛ برای این کار display_name را رویNoneتنظیم کنید و فهرستی از نشانی تکی را بهعنوان addresses ارائه دهید.- display_name¶
display_nameگروه. اگر این مقدارNoneباشد و دقیقاً یکAddressدرaddressesوجود داشته باشد، آنگاهGroupنشاندهندهی یک نشانی واحد است که در گروهی نیست.
- __str__()¶
مقدار
strیکGroupمطابق RFC 5322 قالببندی میشود، اما بدون اعمال کدگذاری انتقال محتوا (Content Transfer Encoding) بر هیچیک از نویسههای غیر ASCII. اگرdisplay_nameوجود نداشته باشد و تنها یکAddressدر فهرستaddressesوجود داشته باشد، مقدارstrبرابر باstrهمانAddressتنها خواهد بود.
پانویسها