视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Python使用email模块对邮件进行编码和解码
2020-11-27 14:21:55 责编:小采
文档


本文给大家介绍的是Python使用email模块对邮件进行编码和解码,非常的详细,有相同需求的小伙伴可以参考下

解码邮件
python自带的email模块是个很有意思的东西,它可以对邮件编码解码,用来处理邮件非常好用。
处理邮件是一个很细致的工作,尤其是解码邮件,因为它的格式变化太多了,下面先看看一个邮件的源文件:

Received: from 192.168.208.56 ( 192.168.208.56 [192.168.208.56] ) by
ajax-webmail-wmsvr37 (Coremail) ; Thu, 12 Apr 2007 12:07:48 +0800 (CST)
Date: Thu, 12 Apr 2007 12:07:48 +0800 (CST)
From: user1 <xxxxxxxx@163.com>
To: zhaowei <zhaoweikid@163.com>
Message-ID: <31571419.200911176350868321.JavaMail.root@bj163app37.163.com>
Subject: =?gbk?B?u+nJtA==?=
MIME-Version: 1.0
Content-Type: multipart/Alternative; 
 boundary="----=_Part_21696_28113972.1176350868319"

------=_Part_21696_28113972.1176350868319
Content-Type: text/plain; charset=gbk
Content-Transfer-Encoding: base

ztLS0b+qyrzS1M6qysfSu7j20MfG2ru70ru0zqOs1K3AtMrH0ru49tTCtffSu7TOztLDx8/W1NrT
prjDysew67XjssXE3MjI1ebC6bezICAg
------=_Part_21696_28113972.1176350868319
Content-Type: text/html; charset=gbk
Content-Transfer-Encoding: quoted-printable

<p>=CE=D2=D2=D1=BF=AA=CA=BC=D2=D4=CE=AA=CA=C7=D2=BB=B8=F6=D0=C7=C6=DA=BB=
=BB=D2=BB=B4=CE=A3=AC=D4=AD=C0=B4=CA=C7=D2=BB=B8=F6=D4=C2=B5=F7=D2=BB=B4=CE=
</p>
<p>=CE=D2=C3=C7=CF=D6=D4=DA=D3=A6=B8=C3=CA=C7=B0=EB=B5=E3=B2=C5=C4=DC=C8=
=C8</p>
<p>=D5=E6=C2=E9=B7=B3</p>
------=_Part_21696_28113972.1176350868319--

上面的就是以封邮件的源文件,从第一行到第一个空行之间的为信件头,后面的就是信件体了。把上面的信息复制下来存到一个叫xxx.eml的文件里,用鼠标双击就可以看到内容,当然看到的是解码后的,是outlook帮你解码了。
看看email模块怎么处理这个邮件,假设信件已经存为xxx.eml。

#-*- encoding: gb2312 -*-
import email

fp = open("xxx.eml", "r")
msg = email.message_from_file(fp) # 直接文件创建message对象,这个时候也会做初步的解码
subject = msg.get("subject") # 取信件头里的subject, 也就是主题
# 下面的三行代码只是为了解码象=?gbk?Q?=CF=E0=C6=AC?=这样的subject
h = email.Header.Header(subject)
dh = email.Header.decode_header(h)
subject = dh[0][0]
print "subject:", subject
print "from: ", email.utils.parseaddr(msg.get("from"))[1] # 取from
print "to: ", email.utils.parseaddr(msg.get("to"))[1] # 取to

fp.close()

这段代码可以把一封邮件中的主题、发件人、收件人解析出来。email.utils.parseaddr是用来专门解析邮件地址的,原因是邮件地址很多时候在原文里是这样写的:user1 <xxxxxxxx@163.com>, email.utils.parseaddr就可以把它解析为一个列表,第一项是user1, 第二项是xxxxxxxx@163.com, 这里只显示了后面以部分。
前面那段代码只是解析了信件头,接着解析信件体吧。信体里可能有纯文本的plain和html两部分,也可能有附件。这里需要mime的知识,详细介绍可以从网上搜搜。我这里就不说了,下面看看怎么解析的:

#-*- encoding: gb2312 -*-
import email

fp = open("xxx.eml", "r")
msg = email.message_from_file(fp)

# 循环信件中的每一个mime的数据块
for par in msg.walk():
 if not par.is_multipart(): # 这里要判断是否是multipart,是的话,里面的数据是无用的,至于为什么可以了解mime相关知识。
 name = par.get_param("name") #如果是附件,这里就会取出附件的文件名
 if name:
 #有附件
 # 下面的三行代码只是为了解码象=?gbk?Q?=CF=E0=C6=AC.rar?=这样的文件名
 h = email.Header.Header(name)
 dh = email.Header.decode_header(h)
 fname = dh[0][0]
 print '附件名:', fname
 data = par.get_payload(decode=True) # 解码出附件数据,然后存储到文件中
 
 try:
 f = open(fname, 'wb') #注意一定要用wb来打开文件,因为附件一般都是二进制文件
 except:
 print '附件名有非法字符,自动换一个'
 f = open('aaaa', 'wb')
 f.write(data)
 f.close()
 else:
 #不是附件,是文本内容
 print par.get_payload(decode=True) # 解码出文本内容,直接
输出来就可以了。 print '+'*60 # 用来区别各个部分的输出

简单吧,并没有多少代码就可以实现复杂的解析邮件的功能!

编码邮件
用email模块来生成邮件也是很简单的,只是需要一些mime的基础知识。下面看看一点mime基础。
MIME消息由消息头和消息体两大部分组成,在邮件里就是邮件头和邮件体。邮件头与邮件体之间以空行进行分隔。这点可以用文本编辑器(比如记事本)查看一个邮件的源文件就可以清除看到。outlook和foxmail自己就有查看源文件的功能。
邮件头包含了发件人、收件人、主题、时间、MIME版本、邮件内容的类型等重要信息。每条信息称为一个域,由域名后加“: ”和信息内容构成,可以是一行,较长的也可以占用多行。域的首行必须“顶头”写,即左边不能有空白字符(空格和制表符);续行则必须以空白字符打头,且第一个空白字符不是信息本身固有的。
邮件体包含邮件的内容,它的类型由邮件头的“Content-Type”域指出。最常见的类型有text/plain(纯文本)和text/html(超文本)。邮件体被分为多个段,每个段又包含段头和段体两部分,这两部分之间也以空行分隔。常见的multipart类型有三种:multipart/mixed, multipart/related和multipart/alternative。从它们的名称,不难推知这些类型各自的含义和用处。
如果在邮件中要添加附件,必须定义multipart/mixed段;如果存在内嵌资源,至少要定义 multipart/related段;如果纯文本与超文本共存,至少要定义multipart/alternative段。生成邮件就是要生成这各个MIME部分。email模块对这些处理都是包装好的,看看生成方法:

#-*- encoding: gb2312 -*-
import email
import string, sys, os, email
import time

class MailCreator:
 def __init__(self):
 # 创建邮件的message对象
 self.msg = email.Message.Message()
 self.mail = "" 
 
 def create(self, mailheader, maildata, mailattachlist=[]):
 # mailheader 是dict类型,maildata是list, 且里面第一项为纯文本类型,第二项为html.
 # mailattachlist 是list, 里面为附件文件名
 if not mailheader or not maildata:
 return
 
 for k in mailheader.keys():
 # 对subject要作特殊处理,中文要转换一下。
 # 比如 "我的一个测试邮件" 就要转换为 =?gb2312?b?ztK1xNK7uPay4srU08q8/g==?=
 if k == 'subject':
 self.msg[k] = email.Header.Header(mailheader[k], 'gb2312') 
 else:
 self.msg[k] = mailheader[k]
 # 创建纯文本部分
 body_plain = email.MIMEText.MIMEText(maildata[0], _subtype='plain', _charset='gb2312')
 body_html = None
 # 创建html部分,这个是可选的
 if maildata[1]:
 body_html = email.MIMEText.MIMEText(maildata[1], _subtype='html', _charset='gb2312')
 
 
 # 创建一个multipart, 然后把前面的文本部分和html部分都附加到上面,至于为什么,可以看看mime相关内容
 attach=email.MIMEMultipart.MIMEMultipart()
 attach.attach(body_plain)
 if body_html:
 attach.attach(body_html)
 # 处理每一个附件
 for fname in mailattachlist:
 attachment=email.MIMEText.MIMEText(email.Encoders._bencode(open(fname,'rb').read()))
 # 这里设置文件类型,全部都设置为Application.当然也可以是Image,Audio什么的,这里不管那么多
 attachment.replace_header('Content-type','Application/octet-stream;name="'+os.path.basename(fname)+'"')
 # 一定要把传输编码设置为base,因为这里默认就是用的base
 attachment.replace_header('Content-Transfer-Encoding', 'base')
 attachment.add_header('Content-Disposition','attachment;filename="'+os.path.basename(fname)+'"')
 attach.attach(attachment)
 # 生成最终的邮件 
 self.mail = self.msg.as_string()[:-1] + attach.as_string()
 
 return self.mail

if __name__ == '__main__':
 mc = MailCreator()
 header = {'from': 'zhaowei@163.com', 'to':'weizhao@163.com', 'subject':'我的一个测试邮件'}
 data = ['plain text information', '<font color="red">html text information</font>']
 if sys.platform == 'win32':
 attach = ['c:/windows/clock.avi']
 else:
 attach = ['/bin/cp']
 
 mail = mc.create(header, data, attach)
 
 f = open("test.eml", "wb")
 f.write(mail)
 f.close()

这里我自己封装了一个类来做处理,大体的过程就是:
1. 先创建message对象: email.Message.Message()
2. 创建MIMEMultipart对象:email.MIMEMultipart.MIMEMultipart()
3. 创建各个MIMEText对象,并把他们attach到MIMEMultipart里,这里的MIMEText其实不仅仅是text, 也包括image, application, audio等等。
4. 生成最终邮件。

下载本文
显示全文
专题