Python网络编程:E-mail服务(四) 编写传统邮件

简介
本文通过标准Python库的email模块提供MIMEText类,进行传统email的编写,从而对email模块有一个初步的认识。

邮件编写

RFC 822定义了邮件的标准格式,在前面的文章对此也进行了相关介绍,这里我们通过MIMEText类,来编写一个传统邮件。
'''
Created on Apr 18, 2015


@author: jliu
'''


from email.Utils import formatdate, make_msgid
from email.mime.text import MIMEText


if __name__ == '__main__':
    message = '''Hello,\n   this is an autotest email.\n---Jinguang Liu.\n'''
    
    msg = MIMEText(message)
    msg['To'] = 'jinguang.liu@qq.com'
    msg['From'] = 'jliu@163.com'
    msg['Subject'] = 'This is a test email'
    msg['Date'] = formatdate(localtime=1)
    msg['Message-ID'] = make_msgid() 
    
    print msg.as_string()
查看一下程序运行的结果:
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
To: jinguang.liu@qq.com
From: jliu@163.com
Subject: This is a test email
Date: Sat, 25 Apr 2015 17:50:12 +0800
Message-ID: <20150425095012.3420.48931@bob-PC>

Hello,
   this is an autotest email.
---Jinguang Liu.

代码解析

MIMEText类是用来创建文本类型的MIME对象,其类的实现如下:
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继承MIMENonMultipart类,实现单非多部分邮件的编写。_text参数是作为负载的字符串,_subtype是子类型,缺省设置为plain类型的纯文本文件。_charset是字符编码。除非显示的讲_charset设置为None, 否则MIMEText对象会创建Content-Type和Content-Transfer-Encoding的头部。从上面的运行结果中可以看出这点。
添加头部非常简单,按照msg['To'] = 'jinguang.liu@qq.com'格式很容易的就可以添加。这部分的工作是在基类Message中实现的,通过list类模拟字典功能,下面列出了源码中的相关实现:
class Message:
    """Basic message object.

    A message object is defined as something that has a bunch of RFC 2822
    headers and a payload.  It may optionally have an envelope header
    (a.k.a. Unix-From or From_ header).  If the message is a container (i.e. a
    multipart or a message/rfc822), then the payload is a list of Message
    objects, otherwise it is a string.

    Message objects implement part of the `mapping' interface, which assumes
    there is exactly one occurrence of the header per message.  Some headers
    do in fact appear multiple times (e.g. Received) and for those headers,
    you must use the explicit API to set or get all the headers.  Not all of
    the mapping methods are implemented.
    """
    def __init__(self):
        self._headers = []
        self._unixfrom = None
        self._payload = None
        self._charset = None
        # Defaults for multipart messages
        self.preamble = self.epilogue = None
        self.defects = []
        # Default content type
        self._default_type = 'text/plain'

    #
    # MAPPING INTERFACE (partial)
    #
    def __len__(self):
        """Return the total number of headers, including duplicates."""
        return len(self._headers)

    def __getitem__(self, name):
        """Get a header value.

        Return None if the header is missing instead of raising an exception.

        Note that if the header appeared multiple times, exactly which
        occurrence gets returned is undefined.  Use get_all() to get all
        the values matching a header field name.
        """
        return self.get(name)

    def __setitem__(self, name, val):
        """Set the value of a header.

        Note: this does not overwrite an existing header with the same field
        name.  Use __delitem__() first to delete any existing headers.
        """
        self._headers.append((name, val))

    def __delitem__(self, name):
        """Delete all occurrences of a header, if present.

        Does not raise an exception if the header is missing.
        """
        name = name.lower()
        newheaders = []
        for k, v in self._headers:
            if k.lower() != name:
                newheaders.append((k, v))
        self._headers = newheaders

    def __contains__(self, name):
        return name.lower() in [k.lower() for k, v in self._headers]

    def has_key(self, name):
        """Return true if the message contains the header."""
        missing = object()
        return self.get(name, missing) is not missing

    def keys(self):
        """Return a list of all the message's header field names.

        These will be sorted in the order they appeared in the original
        message, or were added to the message, and may contain duplicates.
        Any fields deleted and re-inserted are always appended to the header
        list.
        """
        return [k for k, v in self._headers]

    def values(self):
        """Return a list of all the message's header values.

        These will be sorted in the order they appeared in the original
        message, or were added to the message, and may contain duplicates.
        Any fields deleted and re-inserted are always appended to the header
        list.
        """
        return [v for k, v in self._headers]

    def items(self):
        """Get all the message's header fields and values.

        These will be sorted in the order they appeared in the original
        message, or were added to the message, and may contain duplicates.
        Any fields deleted and re-inserted are always appended to the header
        list.
        """
        return self._headers[:]

    def get(self, name, failobj=None):
        """Get a header value.

        Like __getitem__() but return failobj instead of None when the field
        is missing.
        """
        name = name.lower()
        for k, v in self._headers:
            if k.lower() == name:
                return v
        return failobj

在这个传统邮件编写的例子中,还使用了email.utils提供了两个方法来增加Date和Message-ID两个头部:

formatdate([timeval[, localtime][, usegmt]]) :返回RFC 28822(替代RFC 822)定义的日期字符串,格式:Fri, 09 Nov 2001 01:08:47 -0000

make_msgid([idstring]):返回与RFC 2822兼容的Message-ID字符串

最后,通过as_string()方法,可以获取邮件的字符串。

总结

通过email模块的MIMEText类来实现传统邮件的编写,并介绍了email相关类、接口的实现和使用。通过本文的介绍,读者应该比较容易的写出纯文本格式的邮件。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值