python email模块
email模块
电子邮件包是一个用于管理电子邮件消息的库。它的特殊设计不用于向SMTP (RFC 2821)、NNTP或其他服务器发送任何电子邮件消息;这些是模块的函数,如smtplib和nntplib。电子邮件包尝试尽可能符合RFC,支持RFC 5233和RFC 6532,以及与mime相关的RFC 2045、RFC 2046、RFC 2047、RFC 2183和RFC 2231。
电子邮件包的总体结构可以分为三个主要组件,以及控制其他组件行为的第四个组件。
包的核心组件是表示电子邮件消息的“对象模型”。应用程序主要通过消息子模块中定义的对象模型接口与包进行交互。应用程序可以使用这个API询问关于现有电子邮件的问题,构造新的电子邮件,或者添加或删除本身使用相同对象模型接口的电子邮件子组件。也就是说,根据电子邮件消息及其MIME子组件的性质,电子邮件对象模型是所有提供EmailMessage API的对象的树结构。
包的另外两个主要组件是解析器和生成器。解析器获取电子邮件消息的序列化版本(字节流),并将其转换为EmailMessage对象树。生成器接收电子邮件消息并将其转换回序列化的字节流。(解析器和生成器也处理文本字符流,但不建议使用这种用法,因为很容易出现以某种方式无效的消息。)
控制组件是策略模块。每个电子邮件消息、每个生成器和每个解析器都有一个关联的策略对象来控制其行为。通常,应用程序只需要在创建EmailMessage时指定策略,方法是直接实例化EmailMessage来创建新电子邮件,或者使用解析器解析输入流。但是,当使用生成器序列化消息时,策略可以更改。例如,这允许从磁盘解析一般的电子邮件消息,但是在将其发送到电子邮件服务器时,可以使用标准SMTP设置对其进行序列化。
电子邮件包尽力向应用程序隐藏各种治理rfc的详细信息。从概念上讲,应用程序应该能够将电子邮件消息视为unicode文本和二进制附件的结构化树,而不必担心这些附件在序列化时是如何表示的。然而,在实践中,经常需要了解至少一些管理MIME消息及其结构的规则,特别是MIME“内容类型”的名称和性质,以及它们如何标识多部分文档。在大多数情况下,这些知识只应该在更复杂的应用程序中使用,即使在这种情况下,也应该只是高级结构,而不是那些结构如何表示的细节。由于MIME内容类型在现代互联网软件中被广泛使用(不仅仅是电子邮件),这对许多程序员来说将是一个熟悉的概念。
以下部分描述了电子邮件包的功能。我们从消息对象模型开始,它是应用程序将使用的主要接口,然后是解析器和生成器组件。然后介绍策略控制,它完成了对库的主要组件的处理。
接下来的三个部分将讨论包可能引发的异常和解析器可能检测到的缺陷(不符合rfc)。然后,我们将介绍headerregistry和contentmanager子组件,它们分别为更详细地操作头部和有效负载提供了工具。这两个组件都包含与消费和生成非平凡消息相关的特性,而且还记录了它们的可扩展性api,这将是高级应用程序感兴趣的。
下面是一组使用前面几节中介绍的api的基本部分的示例。
上面所示的是电子邮件包的现代(unicode友好)API。余下的部分,从Message类开始,将介绍遗留的compat32 API,它更直接地处理如何表示电子邮件消息的细节。compat32 API不会向应用程序隐藏rfc的细节,但是对于需要在该级别上操作的应用程序,它们可能是有用的工具。由于向后兼容性的原因,本文档还适用于仍然使用compat32 API的应用程序。
在3.6版更改:文档重组和重写,促进新的EmailMessage / EmailPolicy API。
Contents of the email
package documentation:
Legacy API:
电子邮件包文档内容:
电子邮件。消息:表示电子邮件消息
电子邮件。解析器:解析电子邮件消息
实现FeedParser API
解析器API
额外的笔记
电子邮件。生成器:生成MIME文档
电子邮件。策略:策略对象
电子邮件。错误:异常和缺陷类
电子邮件。headerregistry:自定义头对象
电子邮件。contentmanager:管理MIME内容
Content Manager实例
电子邮件:示例
遗留API:
email.message。消息:使用compat32 API表示电子邮件消息
电子邮件。mime:从零开始创建电子邮件和mime对象
电子邮件。标题:国际化头
电子邮件。字符集:表示字符集
电子邮件。编码器:编码器
电子邮件。跑龙套:其他工具
电子邮件。迭代器:迭代器
Email模块
如果想在邮件中携带附件、使用html书写邮件,附带图片等等,就需要使用email模块及其子模块。下面来看看email包,email包是用来管理email信息的,它包括MIME和其他基于RFC 2822的消息格式。email包的主要特征是在它内部解析和生成email信息是分开的模块来实现的。
MIME消息由消息头和消息体两大部分组成,在邮件里就是邮件头和邮件体。邮件头与邮件体之间以空行进行分隔。
邮件头包含了发件人、收件人、主题、时间、MIME版本、邮件内容的类型等重要信息。每条信息称为一个域,由域名后加“: ”和信息内容构成,可以是一行,较长的也可以占用多行。域的首行必须“顶头”写,即左边不能有空白字符(空格和制表符);续行则必须以空白字符打头,且第一个空白字符不是信息本身固有的。
邮件体包含邮件的内容,它的类型由邮件头的“Content-Type”域指出。最常见的类型有text/plain(纯文本)和text/html(超文本)。邮件体被分为多个段,每个段又包含段头和段体两部分,这两部分之间也以空行分隔。常见的multipart类型有三种:multipart/mixed, multipart/related和multipart/alternative。
在email的包里面包含了很多模块:
email.message
email.parser
email.generator
email.mime 创建email和MIME对象
email.header
email.charset
email.encoders
email.ereors
email.utils
email.iterators
主要来看看email.mime,在邮件中携带附件、图片、音频时,主要使用的是该模块。一般情况下,你通过解析一个文件或者一段text来生成一个消息对象结构,你也可以从头开始建立一个消息结构,实际上,你可以给一个已经存在的消息结构追加一个新的消息对象。你可以通过创建message实例来创建一个对象结构,然后给该结构追加附件和头部信息。email包提供了一些子类使得该操作变得很容易。
模拟在邮件内容中携带图片,如下:
邮件内容中携带图片
from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.image import MIMEImage import smtplib from_mail = 'froooooooom@gmail.com' to_mail = 'toooooooooo@qq.com' msg = MIMEMultipart() msg['From'] = from_mail msg['To'] = to_mail msg['Subject'] = 'python mail test' body = 'test img send' con = MIMEText('<b>%s</b> <img alt="" src="cid:D:\10535-102.jpg" /> ' % body,'html') msg.attach(con) img = MIMEImage(file('D:\10535-102.jpg','rb').read()) img.add_header('Content-ID','D:\10535-102.jpg') msg.attach(img) server = smtplib.SMTP('smtp.gmail.com') server.docmd('ehol','tooooooo@gmail.com') server.starttls() server.login('username@gmail.com','password') server.sendmail(from_mail,to_mail,msg.as_string()) server.quit()
邮件中携带附件
发送带附件的邮件,首先要创建MIMEMultipart()实例,然后构造附件,如果有多个附件,可依次构造,最后利用smtplib.smtp发送
模拟在 邮件中携带附件 ,如下:
from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart import smtplib #创建一个带附件的实例 msg = MIMEMultipart() txt = MIMEText("这是中文的邮件内容哦",'plain','gb2312') msg.attach(txt) #构造附件1 att1 = MIMEText(open('d:\drcom.rar', 'rb').read(), 'base64', 'gb2312') att1["Content-Type"] = 'application/octet-stream' att1["Content-Disposition"] = 'attachment; filename="drcom.rar"'#这里的filename可以任意写,写什么名字,邮件中显示什么名字 msg.attach(att1) #构造附件2 att2 = MIMEText(open('d:\123.txt', 'rb').read(), 'base64', 'gb2312') att2["Content-Type"] = 'application/octet-stream' att2["Content-Disposition"] = 'attachment; filename="123.txt"' msg.attach(att2) #加邮件头 msg['to'] = 'tooooooo@qq.com' msg['from'] = 'frommmmmmm@gmail.com' msg['subject'] = 'hello world' #发送邮件 try: server = smtplib.SMTP() server.connect('smtp.gmail.com') server.starttls() server.login('xxxxx@gmail.com','xxxxxxxxx')#XXX为用户名,XXXXX为密码 server.sendmail(msg['from'], msg['to'],msg.as_string()) server.quit() print '发送成功' except Exception, e: print str(e)
SMTP
smtp实例封装一个smtp连接,它支持所有的SMTP和ESMTP操作指令,如果host和port参数被定义,则smtp会在初始化期间自动调用connect()方法,如果connect()方法失败,则会触发SMTPConnectError异常,timeout参数设置了超时时间。
SMTP模块的方法:
SMTP.set_debuglevel(level)
设置输出debug调试信息,默认不输出调试信息。
SMTP.docmd(cmd[, argstring])
发送一个command到smtp服务器,
SMTP.connect([host[, port]])
连接到指定的smtp服务器,默认是本机的25端口。也可以写成hostname:port的形式。
SMTP.helo([hostname])
使用helo指令向smtp服务器确认你的身份。
SMTP.ehlo([hostname])
使用ehlo指令向esmtp服务器确认你的身份。
SMTP.ehlo_or_helo_if_needed()
如果在以前的会话连接中没有提供ehlo或者helo指令,这个方法调用ehlo()或者helo()。
SMTP.has_extn(name)
判断指定的名称是否在smtp服务器上。
SMTP.verify(address)
判断邮件地址是否在smtp服务器上存在。
SMTP.login(user, password)
登陆需要验证的smtp服务器,如果之前没有提供ehlo或者helo指令,则会先尝试ESMTP的ehlo指令。
SMTP.starttls([keyfile[, certfile]])
使smtp连接运行在TLS模式,所有的smtp指令都会被加密。
SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options])
发送邮件,该方法需要一些邮件地址和消息。
SMTP.quit()
终止smtp会话并且关闭连接。
1.注意:本人测试使用新浪邮箱:
# 新浪免费邮箱发信(smtp) # 服务器的地址为:smtp.sina.com # 默认端口是25 # # 新浪免费邮箱收信(pop3) # 服务器的地址为:pop.sina.com # 默认端口是110
2.如果你们使新浪邮箱一定要开启POP3/SMTP服务:
3.另外注意:本人登陆使用的是用户名密码,但是如网易邮箱,登陆需要授权码!
使用sendmail发送邮件得测试代码
#coding: utf-8 import smtplib from email.mime.text import MIMEText from email.header import Header #收件人和发件人 receiver = '188xxxx7275@163.com' sender = '83xxxx202@qq.com' #发件人邮箱的SMTP服务器(即sender的SMTP服务器) smtpserver = 'smtp.qq.com' #发件人邮箱的用户名和授权码(不是登陆邮箱的密码) username = '83xxxx202@qq.com' password = 'moxxxxxxxxxxxfcd' #(83xxxx202@qq.com邮箱的授权码或者密码) mail_title = '有陌生人来访!' mail_body = '请查看附件图片' #创建一个实例 message = MIMEText( mail_body, 'plain', 'utf-8' ) #邮件正文 # (plain表示mail_body的内容直接显示,也可以用text,则mail_body的内容在正文中以文本的形式显示,需要下载) message ['From'] = sender #邮件上显示的发件人 message['To'] = receiver #邮件上显示的收件人 message['Subject'] = Header( mail_title, 'utf-8' ) #邮件主题 smtp = smtplib.SMTP() #创建一个连接 smtp.connect( smtpserver ) #连接发送邮件的服务器 smtp.login( username, password ) #登录服务器 smtp.sendmail( sender, receiver, message.as_string() ) #填入邮件的相关信息并发送 smtp.quit()
爬取天气预报并发到指定人的QQ邮箱(使用新浪邮箱)
天气预报: https://tianqi.so.com/weather/
# coding: utf-8 import smtplib from email.mime.text import MIMEText from email.header import Header import requests from bs4 import BeautifulSoup import prettytable as pt def get_Data(url): data_list = [] response = requests.get(url) html_doc = response.text soup = BeautifulSoup(html_doc, 'lxml') # 将html代码自动补全,并按html代码格式返回 wendu = soup.find('div', class_='temperature').get_text() tianqi = soup.find('div', class_='weather-icon-wrap').get_text() data_list.append("现在的温度:%s 现在天气情况:%s" % (wendu, tianqi)) list = soup.find_all('ul', class_='weather-columns') for item in list: data_list.append(item.get_text()) print("列表数据:",data_list) a = 1 tb = pt.PrettyTable() #创建PrettyTable对象 tb.field_names = ["日期","天气","详情"] for item in data_list: # print(a) if a != 1: # print(item.strip()) # print(item.strip().split()[0]+item.strip().split()[1],item.strip().split()[2],item.strip().split()[3]) tb.add_row([item.strip().split()[0]+item.strip().split()[1],item.strip().split()[2],item.strip().split()[3]]) else: print(item.strip()) a+=1 print(tb) return tb def send_mail(msg,receiver): # 收件人 receiver = receiver mail_title = '天气预报' mail_body = str(msg) # 创建一个实例 message = MIMEText(mail_body, 'plain', 'utf-8') # 邮件正文 # (plain表示mail_body的内容直接显示,也可以用text,则mail_body的内容在正文中以文本的形式显示,需要下载) message['From'] = sender # 邮件上显示的发件人 message['To'] = receiver # 邮件上显示的收件人 message['Subject'] = Header(mail_title, 'utf-8') # 邮件主题 smtp = smtplib.SMTP() # 创建一个连接 smtp.connect(smtpserver) # 连接发送邮件的服务器 smtp.login(username, password) # 登录服务器 smtp.sendmail(sender, receiver, message.as_string()) # 填入邮件的相关信息并发送 smtp.quit() if __name__ == '__main__': sender = '发送者邮箱' # 发件人邮箱的SMTP服务器(即sender的SMTP服务器) smtpserver = 'smtp.sina.com' # 发件人邮箱的用户名和授权码(不是登陆邮箱的密码) username = '发送者登陆邮箱' password = '密码' # (83xxxx202@qq.com邮箱的授权码或者密码) url_list = ['url1','url2'] receiver_list =['接收者邮箱1','接收者邮箱2'] for i in range(len(url_list)): tb = get_Data(url_list[i]) #获得每一个用户的数据 send_mail(tb,receiver_list[i]) #发送邮件
运行结果:
列表数据: ['现在的温度:19 现在天气情况:晴', '今天 (05-13) 多云 16/24℃轻度北风 3-5级', '明天 (05-14) 小雨转中雨 18/24℃良东南风 微风', '周三 (05-15) 小雨转多云 19/26℃优北风 微风', '周四 (05-16) 多云 20/30℃优东北风 微风', '周五 (05-17) 多云 20/29℃良东风 微风', '周六 (05-18) 小雨 19/31℃优东风 微风', '周日 (05-19) 小雨转多云 12/27℃优北风 5-6级'] 现在的温度:19 现在天气情况:晴 +-------------+------------+----------------+ | 日期 | 天气 | 详情 | +-------------+------------+----------------+ | 今天(05-13) | 多云 | 16/24℃轻度北风 | | 明天(05-14) | 小雨转中雨 | 18/24℃良东南风 | | 周三(05-15) | 小雨转多云 | 19/26℃优北风 | | 周四(05-16) | 多云 | 20/30℃优东北风 | | 周五(05-17) | 多云 | 20/29℃良东风 | | 周六(05-18) | 小雨 | 19/31℃优东风 | | 周日(05-19) | 小雨转多云 | 12/27℃优北风 | +-------------+------------+----------------+ 列表数据: ['现在的温度:21 现在天气情况:多云', '今天 (05-13) 晴转小雨 17/25℃持续无风向 微风', '明天 (05-14) 多云转小雨 17/25℃持续无风向 微风', '周三 (05-15) 小雨转晴 19/28℃持续无风向 微风', '周四 (05-16) 晴转小雨 20/28℃持续无风向 微风', '周五 (05-17) 多云转阴 21/28℃持续无风向 微风', '周六 (05-18) 阵雨 18/28℃持续无风向 微风', '周日 (05-19) 多云 17/27℃持续无风向 微风'] 现在的温度:21 现在天气情况:多云 +-------------+------------+------------------+ | 日期 | 天气 | 详情 | +-------------+------------+------------------+ | 今天(05-13) | 晴转小雨 | 17/25℃持续无风向 | | 明天(05-14) | 多云转小雨 | 17/25℃持续无风向 | | 周三(05-15) | 小雨转晴 | 19/28℃持续无风向 | | 周四(05-16) | 晴转小雨 | 20/28℃持续无风向 | | 周五(05-17) | 多云转阴 | 21/28℃持续无风向 | | 周六(05-18) | 阵雨 | 18/28℃持续无风向 | | 周日(05-19) | 多云 | 17/27℃持续无风向 | +-------------+------------+------------------+