Python網路程式設計:E-mail服務(五)深入理解email模組的message和MIME類
阿新 • • 發佈:2019-02-13
簡介
本文主要介紹Python標準庫email的message和MIME類,並分析了相關的實現,能夠是讀者更好的使用email模組。核心類Message
Message類是email的核心類,它是email物件模型中基類,提供了設定和查詢郵件頭部,訪問訊息體的核心方法。從概念上講,Message物件構成了郵件頭部(Headers)和訊息體(payloads)。頭部格式在RFC 2822中進行了定義,每個頭部由該項名字和值組成,並由冒號分割。訊息體可以是簡單訊息物件的字串或多個MIME容器的Message物件組成的多部分郵件。Message類在email.message模組中定義。 Message基類與MIME類的繼承關係如下圖所示:MIMEBase基類
MIMEBase作為MIME相關物件基類繼承了Message,擁有擁有Message操作郵件頭部和郵件體的所有函式。MIME在郵件頭部增加了Content-Type和MIME-Version兩個頭部資訊,從下面MIMEBase的實現中可以清楚的看到這一點:class MIMEBase(message.Message): """Base class for MIME specializations.""" def __init__(self, _maintype, _subtype, **_params): """This constructor adds a Content-Type: and a MIME-Version: header. The Content-Type: header is taken from the _maintype and _subtype arguments. Additional parameters for this header are taken from the keyword arguments. """ message.Message.__init__(self) ctype = '%s/%s' % (_maintype, _subtype) self.add_header('Content-Type', ctype, **_params) self['MIME-Version'] = '1.0'
多部分郵件類MIMEMultipart類
MIMEMultipart類用於實現多部分郵件的功能,預設情況下它會建立Content-Type型別為mulitpart/mixed郵件。在類初始化時,會將_payload初始化為空的列表,因為在Message超類中is_multipart方法假設_payload是一個列表,並用來存放多部分郵件內容,利用attach()方法可以將多部分郵件新增到列表中。這裡來看一下超類Message中的相關實現:class MIMEMultipart(MIMEBase): """Base class for MIME multipart/* type messages.""" def __init__(self, _subtype='mixed', boundary=None, _subparts=None, **_params): """Creates a multipart/* type message. By default, creates a multipart/mixed message, with proper Content-Type and MIME-Version headers. _subtype is the subtype of the multipart content type, defaulting to `mixed'. boundary is the multipart boundary string. By default it is calculated as needed. _subparts is a sequence of initial subparts for the payload. It must be an iterable object, such as a list. You can always attach new subparts to the message by using the attach() method. Additional parameters for the Content-Type header are taken from the keyword arguments (or passed into the _params argument). """ MIMEBase.__init__(self, 'multipart', _subtype, **_params) # Initialise _payload to an empty list as the Message superclass's # implementation of is_multipart assumes that _payload is a list for # multipart messages. self._payload = [] if _subparts: for p in _subparts: self.attach(p) if boundary: self.set_boundary(boundary)
class Message:
......
def is_multipart(self):
"""Return True if the message consists of multiple parts."""
return isinstance(self._payload, list)
#
# Payload manipulation.
#
def attach(self, payload):
"""Add the given payload to the current payload.
The current payload will always be a list of objects after this method
is called. If you want to set the payload to a scalar object, use
set_payload() instead.
"""
if self._payload is None:
self._payload = [payload]
else:
self._payload.append(payload)
......
非多部分郵件類MIMENonMultipart類
MIMENonMultipart類與MIMEMultipart類一樣,繼承自MIMEBase基類,其實現了自定義attach()方法,由於其是非多部分郵件型別實現,使用者呼叫此方法,會丟擲MutlipartConversionError異常。class MIMENonMultipart(MIMEBase):
"""Base class for MIME non-multipart type messages."""
def attach(self, payload):
# The public API prohibits attaching multiple subparts to MIMEBase
# derived subtypes since none of them are, by definition, of content
# type multipart/*
raise errors.MultipartConversionError(
'Cannot attach additional subparts to non-multipart/*')
MIMENonMultipart類是其它具體MIMEApplication, MIMEText,MIMEImage等其它類的基類,也就是說它們不執行使用者使用attach()方法。它們是通過set_payload()方法來實現設定郵件payload功能的。
class Message:
......
def set_payload(self, payload, charset=None):
"""Set the payload to the given value.
Optional charset sets the message's default character set. See
set_charset() for details.
"""
self._payload = payload
if charset is not None:
self.set_charset(charset)
......
具體類實現
MIME模組提供了5個MIME具體類,各個具體類都提供了與名稱對應的主訊息型別的物件的支援,它們都繼承了MIMENonMultipart類;關於MIME主型別的知識,可以參考Python網路程式設計:E-mail服務(三)MIME詳解。這裡簡單看一下MIMEText的實現:class MIMEText(MIMENonMultipart):
"""Class for generating text/* type MIME documents."""
def __init__(self, _text, _subtype='plain', _charset='us-ascii'):
"""Create a text/* type MIME document.
_text is the string for this message object.
_subtype is the MIME sub content type, defaulting to "plain".
_charset is the character set parameter added to the Content-Type
header. This defaults to "us-ascii". Note that as a side-effect, the
Content-Transfer-Encoding header will also be set.
"""
MIMENonMultipart.__init__(self, 'text', _subtype,
**{'charset': _charset})
self.set_payload(_text, _charset)
MIMEText在初始化時,將主型別設定為text型別,並通過set_payload()函式設定郵件體內容。