email.parser: تجزیه پیامهای ایمیل¶
کد منبع: Lib/email/parser.py
ساختارهای شیء پیام را میتوان به یکی از دو روش ایجاد کرد: میتوان آنها را از پایه با ایجاد یک شیء EmailMessage، افزودن سرآیندها با استفاده از رابط دیکشنری، و افزودن بار(ها) با استفاده از set_content() و متدهای مرتبط ایجاد کرد، یا میتوان آنها را با تجزیهی یک نمایش سریالشده از پیام ایمیل ایجاد کرد.
بستهی email یک پارسر استاندارد ارائه میکند که بیشتر ساختارهای اسناد ایمیل، از جمله اسناد MIME را درک میکند. شما میتوانید یک شیء بایتی، رشته یا پرونده را به پارسر بدهید و پارسر نمونهی ریشهی EmailMessage از ساختار شیء را به شما بازمیگرداند. برای پیامهای ساده و غیر MIME، بار این شیء ریشه به احتمال زیاد یک رشته حاوی متن پیام خواهد بود. برای پیامهای MIME، شیء ریشه از متد is_multipart() خود مقدار True را بازمیگرداند و میتوان به زیربخشها از طریق متدهای دستکاری بار، مانند get_body()، iter_parts() و walk() دسترسی یافت.
در واقع دو رابط پارسر برای استفاده در دسترس هستند: API Parser و API افزایشی FeedParser. API Parser زمانی بیشترین کاربرد را دارد که کل متن پیام را در حافظه داشته باشید، یا اینکه کل پیام در پروندهای روی سیستم پرونده قرار داشته باشد. FeedParser زمانی مناسبتر است که پیام را از جریانی میخوانید که ممکن است در انتظار ورودی بیشتر مسدود شود (مانند خواندن یک پیام ایمیل از یک سوکت). FeedParser میتواند پیام را بهصورت افزایشی مصرف و تجزیه کند، و تنها زمانی که پارسر را ببندید، شیء ریشه را برمیگرداند.
توجه داشته باشید که پارسر را میتوان به روشهای محدودی گسترش داد و البته میتوانید پارسرٔ خودتان را کاملاً از صفر پیادهسازی کنید. تمام منطقی که پارسرٔ همراه با بستهی email و کلاس EmailMessage را به هم متصل میکند، در کلاس Policy نهفته است، بنابراین یک پارسرٔ سفارشی میتواند با پیادهسازی نسخههای سفارشی متدهای مناسب Policy، درختهای شیء پیام را به هر روشی که لازم بداند ایجاد کند.
API مربوط به FeedParser¶
BytesFeedParser، که از ماژول email.feedparser ایمپورت میشود، یک API فراهم میکند که برای تجزیه تدریجی پیامهای ایمیل مناسب است، مانند حالتی که لازم باشد متن یک پیام ایمیل از منبعی که ممکن است مسدودکننده باشد (مانند سوکت) خوانده شود. البته میتوان از BytesFeedParser برای تجزیه پیام ایمیلی که بهطور کامل در یک bytes-like object، رشته یا پرونده قرار دارد استفاده کرد، اما ممکن است API BytesParser برای چنین موارد استفادهای مناسبتر باشد. معناشناسی و نتایج این دو API پارسر یکسان است.
API مربوط به BytesFeedParser ساده است؛ شما یک نمونه ایجاد میکنید، تعدادی بایت به آن میدهید تا زمانی که دیگر بایتی برای دادن به آن باقی نمانده باشد، سپس پارسر را میبندید تا شیء پیام ریشه را دریافت کنید. BytesFeedParser هنگام تجزیهی پیامهای مطابق با استاندارد بسیار دقیق است و در تجزیهی پیامهای غیرمطابق با استاندارد نیز بسیار خوب عمل میکند و اطلاعاتی دربارهی چگونگی معیوب تشخیص داده شدن یک پیام ارائه میدهد. این پارسر ویژگی defects یک شیء پیام را با فهرستی از هرگونه مشکلی که در یک پیام پیدا کرده است، پر میکند. برای فهرست نقصهایی که میتواند پیدا کند، ماژول email.errors را ببینید.
در اینجا API مربوط به BytesFeedParser آمده است:
- class email.parser.BytesFeedParser(_factory=None, *, policy=policy.compat32)¶
نمونهای از
BytesFeedParserایجاد کنید. _factory اختیاری، یک شیء فراخوانیپذیر بدون آرگومان است؛ اگر مشخص نشده باشد، ازmessage_factoryاز policy استفاده میشود. هرگاه به یک شیء پیام جدید نیاز باشد، _factory فراخوانی میشود.اگر policy مشخص شده باشد، برای بهروزرسانی بازنمایی پیام از قواعدی که مشخص میکند استفاده میشود. اگر policy تنظیم نشده باشد، از سیاست
compat32استفاده میشود، که سازگاری با نسخهی Python 3.2 بستهی email را حفظ میکند وMessageرا بهعنوان کارخانهی پیشفرض فراهم میکند. تمام سیاستهای دیگرEmailMessageرا بهعنوان _factory پیشفرض فراهم میکنند. برای اطلاعات بیشتر دربارهی سایر مواردی که policy کنترل میکند، به مستنداتpolicyمراجعه کنید.توجه: کلیدواژهی policy همیشه باید تعیین شود؛ مقدار پیشفرض در نسخهی آیندهی پایتون به
email.policy.defaultتغییر خواهد کرد.اضافه شده در نسخهی 3.2.
تغییر یافته در نسخهی 3.3: کلیدواژهی policy افزوده شد.
تغییر یافته در نسخهی 3.6: _factory بهصورت پیشفرض برابر با
message_factoryسیاست است.- feed(data)¶
دادههای بیشتری به پارسر بدهید. data باید یک bytes-like object حاوی یک یا چند خط باشد. سطرهای میتوانند ناقص باشند و پارسر چنین سطرهای ناقصی را بهدرستی به یکدیگر متصل خواهد کرد. سطرهای میتوانند دارای هر یک از سه پایانخط رایج باشند: بازگشت به ابتدای سطر، خط جدید، یا بازگشت به ابتدای سطر و خط جدید (حتی میتوانند بهصورت ترکیبی باشند).
- class email.parser.FeedParser(_factory=None, *, policy=policy.compat32)¶
مانند
BytesFeedParserعمل میکند، بهجز اینکه ورودی متدfeed()باید یک رشته باشد. این کاربرد محدودی دارد، زیرا تنها راه برای معتبر بودن چنین پیامی این است که فقط شامل متن ASCII باشد یا، اگرutf8برابرTrueباشد، هیچ پیوست دودوییای نداشته باشد.تغییر یافته در نسخهی 3.3: کلیدواژهی policy افزوده شد.
API پارسر¶
کلاس BytesParser، که از ماژول email.parser ایمپورت میشود، یک API فراهم میکند که میتوان از آن برای تجزیهی یک پیام استفاده کرد، هنگامی که محتوای کامل پیام در یک bytes-like object یا پرونده در دسترس باشد. ماژول email.parser همچنین Parser را برای تجزیهی رشتهها، و نیز پارسرهای فقط سرآیند، BytesHeaderParser و HeaderParser، فراهم میکند؛ از این پارسرها میتوان در صورتی استفاده کرد که فقط به سرآیندهای پیام علاقهمند باشید. BytesHeaderParser و HeaderParser میتوانند در این شرایط بسیار سریعتر باشند، زیرا تلاش نمیکنند بدنه پیام را تجزیه کنند، بلکه در عوض بار را به بدنه خام تنظیم میکنند.
- class email.parser.BytesParser(_class=None, *, policy=policy.compat32)¶
یک نمونه از
BytesParserایجاد کنید. آرگومانهای _class و policy همان معنا و معناشناسی آرگومانهای _factory و policy درBytesFeedParserرا دارند.توجه: کلیدواژهی policy همیشه باید تعیین شود؛ مقدار پیشفرض در نسخهی آیندهی پایتون به
email.policy.defaultتغییر خواهد کرد.تغییر یافته در نسخهی 3.3: آرگومان strict که در 2.4 منسوخ شده بود، حذف شد. کلیدواژهی policy افزوده شد.
تغییر یافته در نسخهی 3.6: _class بهطور پیشفرض برابر با سیاست
message_factoryاست.- parse(fp, headersonly=False)¶
تمام دادهها را از شیء شبهپرونده دودویی fp میخواند، بایتهای حاصل را تجزیه میکند و شیء پیام را برمیگرداند. fp باید از هر دو متد
readline()وread()پشتیبانی کند.بایتهای موجود در fp باید بهصورت بلوکی از سرآیندها و سطرهای ادامهی سرآیند به سبک RFC 5322 (یا اگر
utf8برابرTrueباشد، RFC 6532) قالببندی شده باشند؛ بهصورت اختیاری ممکن است یک سرآیندی پاکت (envelope header) پیش از آنها بیاید. بلوک سرآیند یا با پایان دادهها یا با یک خط خالی پایان مییابد. پس از بلوک سرآیند، بدنهی پیام قرار دارد (که ممکن است شامل زیربخشهای کدگذاریشده با MIME باشد، از جمله زیربخشهایی که Content-Transfer-Encoding آنها8bitاست).headersonly اختیاری، پرچمی است که مشخص میکند آیا پس از خواندن سرآیندها تجزیه متوقف شود یا خیر. مقدار پیشفرض
Falseاست، به این معنا که کل محتویات پرونده تجزیه میشود.
- parsebytes(bytes, headersonly=False)¶
مانند متد
parse()است، با این تفاوت که بهجای یک شیء شبهپرونده، یک bytes-like object دریافت میکند. فراخوانی این متد بر روی یک bytes-like object معادل آن است که ابتدا bytes را در یک نمونه ازBytesIOقرار دهید و سپسparse()را فراخوانی کنید.آرگومان اختیاری headersonly مانند متد
parse()است.
اضافه شده در نسخهی 3.2.
- class email.parser.BytesHeaderParser(_class=None, *, policy=policy.compat32)¶
دقیقاً مانند
BytesParser، با این تفاوت که headersonly بهطور پیشفرضTrueاست.اضافه شده در نسخهی 3.3.
- class email.parser.Parser(_class=None, *, policy=policy.compat32)¶
این کلاس مشابه
BytesParserاست، اما ورودی رشتهای را پردازش میکند.تغییر یافته در نسخهی 3.3: آرگومان strict حذف شد. کلیدواژه policy افزوده شد.
تغییر یافته در نسخهی 3.6: _class بهطور پیشفرض برابر با سیاست
message_factoryاست.- parse(fp, headersonly=False)¶
تمام دادهها را از شیء شبهپرونده در حالت متنی fp میخواند، متن حاصل را تجزیه میکند و شیء پیام ریشه را برمیگرداند. fp باید از هر دو متد
readline()وread()در اشیاء شبهپرونده پشتیبانی کند.غیر از الزام حالت متنی، این متد مانند
BytesParser.parse()عمل میکند.
- parsestr(text, headersonly=False)¶
مشابه متد
parse()، با این تفاوت که بهجای یک شیء شبهپرونده، یک شیء رشته دریافت میکند. فراخوانی این متد روی یک رشته، معادل آن است که ابتدا text را درون یک نمونه ازStringIOقرار دهید و سپسparse()را فراخوانی کنید.آرگومان اختیاری headersonly مانند متد
parse()است.
- class email.parser.HeaderParser(_class=None, *, policy=policy.compat32)¶
دقیقاً مانند
Parser، با این تفاوت که headersonly بهطور پیشفرضTrueاست.
از آنجا که ایجاد ساختار شیء پیام از یک رشته یا شیء پرونده کاری بسیار رایج است، چهار تابع برای سهولت ارائه شدهاند. این توابع در فضای نام سطح بالای بستهی email در دسترس هستند.
- email.message_from_bytes(s, _class=None, *, policy=policy.compat32)¶
ساختار شیء پیام را از یک شیء شبهبایت (bytes-like object) برمیگرداند. این معادل
BytesParser().parsebytes(s)است. آرگومانهای اختیاری _class و policy همانگونه تفسیر میشوند که در سازنده کلاسBytesParserتفسیر میشوند.اضافه شده در نسخهی 3.2.
تغییر یافته در نسخهی 3.3: آرگومان strict حذف شد. کلیدواژه policy افزوده شد.
- email.message_from_binary_file(fp, _class=None, *, policy=policy.compat32)¶
یک درخت ساختار شیء پیام را از یک file object دودویی باز برمیگرداند. این معادل
BytesParser().parse(fp)است. _class و policy همانند سازنده کلاسBytesParserتفسیر میشوند.اضافه شده در نسخهی 3.2.
تغییر یافته در نسخهی 3.3: آرگومان strict حذف شد. کلیدواژه policy افزوده شد.
- email.message_from_string(s, _class=None, *, policy=policy.compat32)¶
یک ساختار شیء پیام را از یک رشته برمیگرداند. این معادل
Parser().parsestr(s)است. _class و policy همانگونه تفسیر میشوند که در سازندهی کلاسParserتفسیر میشوند.تغییر یافته در نسخهی 3.3: آرگومان strict حذف شد. کلیدواژه policy افزوده شد.
- email.message_from_file(fp, _class=None, *, policy=policy.compat32)¶
یک درخت ساختار شیء پیام را از یک file object باز برمیگرداند. این معادل
Parser().parse(fp)است. _class و policy همانند سازنده کلاسParserتفسیر میشوند.تغییر یافته در نسخهی 3.3: آرگومان strict حذف شد. کلیدواژه policy افزوده شد.
تغییر یافته در نسخهی 3.6: _class بهطور پیشفرض برابر با سیاست
message_factoryاست.
در اینجا نمونهای از چگونگی استفاده از message_from_bytes() در یک خط فرمان تعاملی پایتون آورده شده است:
>>> import email
>>> msg = email.message_from_bytes(myBytes)
نکات تکمیلی¶
در اینجا چند نکته دربارهی معناشناسی تجزیه آمده است:
بیشتر پیامهایی که نوع آنها غیر multipart است، بهعنوان یک شیء پیام واحد با بار رشتهای تجزیه میشوند. این شیءها برای
is_multipart()مقدارFalseرا برمیگردانند، وiter_parts()یک فهرست خالی تولید میکند.همهی پیامهای نوع multipart بهصورت یک شیء پیام ظرف تجزیه میشوند که بارٔ آن فهرستی از اشیاء زیرپیام است. پیام ظرف بیرونی برای
is_multipart()مقدارTrueرا برمیگرداند، وiter_parts()فهرستی از زیربخشها را تولید میکند.بیشتر پیامهایی که نوع محتوای آنها message/* است (مانند message/delivery-status و message/rfc822) نیز بهصورت یک شیء ظرف حاوی یک بار از نوع فهرست به طول ۱ تجزیه میشوند. متد
is_multipart()این پیامها مقدارTrueرا برمیگرداند. تنها عنصری که توسطiter_parts()تولید میشود، یک شیء زیرپیام خواهد بود.ممکن است برخی پیامهای ناسازگار با استاندارد، از نظر درونی با چندبخشی بودن (multipart-edness) خود سازگار نباشند. چنین پیامهایی ممکن است سرآیند Content-Type از نوع multipart داشته باشند، اما متد
is_multipart()آنها ممکن استFalseبرگرداند. اگر چنین پیامهایی باFeedParserتجزیه شده باشند، در فهرست ویژگی defects خود نمونهای از کلاسMultipartInvariantViolationDefectخواهند داشت. برای جزئیات،email.errorsرا ببینید.