Python学习之旅(三十六)
Python基础知识(35):电子邮件(Ⅱ)
收取邮件就是编写一个MUA作为客户端,从MDA把邮件获取到用户的电脑或者手机上
收取邮件最常用的协议是POP协议,目前版本号是3,俗称POP3
Python内置一个poplib
模块,实现了POP3协议,可以直接用来收邮件
1、通过POP3协议下载邮件
获取最新的一封邮件内容
- import poplib
- from email.parser import Parser
- #输入邮件地址,口令和POP3服务器地址
- email = input('Email: ')
- password = input('Password: ')
- pop3_server = input('POP3 server: ')
- #连接到POP3服务器
- server = poplib.POP3(pop3_server)
- #可以打开或关闭调试信息
- server.set_debuglevel(1)
- #可选:打印POP3服务器的欢迎文字
- print(server.getwelcome().decode('utf-8'))
- #身份认证
- server.user(email)
- server.pass_(password)
- #start()返回邮件数量和占用空间
- print('Messages: %s. Size: %s' % server.stat())
- #list()返回所有邮件编号
- resp, mails, octets = server.list()
- #可以查看返回的列表类似[b'1 82923', b'2 2184', ...]
- print(mails)
- #获取最新一封邮件,注意索引号从1开始
- index = len(mails)
- resp, lines, octets = server.retr(index)
- #lines存储了邮件的1原始文本的每一行
- #可以获得整个邮件的原始文本
- msg_content = b'\r\n'.join(lines).decode('utf-8')
- #稍后解析出邮件
- msg = Parser().parsestr(msg_content)
- #可以根据邮件索引号直接从服务器删除邮件
- #server.dele(index)
- #关闭连接
- server.close()
要获取所有邮件,只需要循环使用retr()
把每一封邮件内容拿到即可。真正麻烦的是把邮件的原始内容解析为可以阅读的邮件对象
运行结果如下
- Email: xxx@163.com
- Password: xxxxx(这里填的是授权码)
- POP3 server: pop.163.com
- +OK Welcome to coremail Mail Pop3 Server (163coms[b62aaa251425b4be4eaec4ab4744cf47s])
- *cmd* 'USER xxx@163.com'
- *cmd* 'PASS xxxxx'
- *cmd* 'STAT'
- *stat* [b'+OK', b'', b'']
- Messages: 1. Size: 2375
- *cmd* 'LIST'
- [b'1 2375']
- *cmd* 'RETR 1'
2、解析邮件
解析邮件的过程和SMTP协议构造邮件正好相反,因此,先导入必要的模块
- from email.parser import Parser
- from email.header import decode_header
- from email.utils import parseaddr
- import poplib
把邮件内容解析为Message
对象
- msg = Parser().parsestr(msg_content)
但是这个Message
对象本身可能是一个MIMEMultipart
对象,即包含嵌套的其他MIMEBase
对象,嵌套可能还不止一层。
所以我们要递归地打印出Message
对象的层次结构
- #indent用于缩进显示
- def print_info(msg, indent=0):
- if indent == 0:
- for header in ['From', 'To', 'Subject']:
- value = msg.get(header, '')
- if value:
- if header == 'Subject':
- value = decode_str(value)
- else:
- hdr, addr = parseaddr(value)
- name = decode_str(hdr)
- value = u'%s <%s>' % (name,addr)
- print('%s%s: %s' % (' ' * indent, header, value))
- if (msg.is_multipart()):
- parts = msg.get_payload()
- for n, part in enumerate(parts):
- print('%spart %s' % (' ' * indent, n))
- print('%s--------------------' % (' ' * indent))
- print_info(part, indent+1)
- else:
- content_type = msg.get_content_type()
- if content_type == 'text/plain' or content_type == 'text/html':
- content = msg.get_payload(decode=True)
- charset = guess_charset(msg)
- if charset:
- content = content.decode(charset)
- print('%sText: %s' % (' ' * indent, content + '...'))
- else:
- print('%sAttachemnt: %s' % (' ' * indent, content_type))
邮件的Subject或者Email中包含的名字都是经过编码后的str,要正常显示,就必须decode
- def decode_str(s):
- value, charset = decode_header(s)[0]
- if charset:
- value = value.decode(charset)
- return value
文本邮件的内容也是str,还需要检测编码,否则,非UTF-8编码的邮件都无法正常显示
- def guess_charset(msg):
- charset = msg.get_charset()
- if charset is None:
- content_type = msg.get('Cnotne-Type', '').lower()
- pos = content_type.find('charset=')
- if pos >= 0:
- charset = content_type[pos + 8:].strip()
- return charset
完整代码如下:
- from email.parser import Parser
- from email.header import decode_header
- from email.utils import parseaddr
- import poplib
- #输入邮件地址,口令和POP3服务器地址
- email = input('Email: ')
- password = input('Password: ')
- pop3_server = input('POP3 server: ')
- def decode_str(s):
- value, charset = decode_header(s)[0]
- if charset:
- value = value.decode(charset)
- return value
- def guess_charset(msg):
- charset = msg.get_charset()
- if charset is None:
- content_type = msg.get('Content-Type', '').lower()
- pos = content_type.find('charset=')
- if pos >= 0:
- charset = content_type[pos + 8:].strip()
- return charset
- # indent用于缩进显示:
- def print_info(msg, indent=0):
- if indent == 0:
- for header in ['From', 'To', 'Subject']:
- value = msg.get(header, '')
- if value:
- if header=='Subject':
- value = decode_str(value)
- else:
- hdr, addr = parseaddr(value)
- name = decode_str(hdr)
- value = u'%s <%s>' % (name, addr)
- print('%s%s: %s' % (' ' * indent, header, value))
- if (msg.is_multipart()):
- parts = msg.get_payload()
- for n, part in enumerate(parts):
- print('%spart %s' % (' ' * indent, n))
- print('%s--------------------' % (' ' * indent))
- print_info(part, indent + 1)
- else:
- content_type = msg.get_content_type()
- if content_type=='text/plain' or content_type=='text/html':
- content = msg.get_payload(decode=True)
- charset = guess_charset(msg)
- if charset:
- content = content.decode(charset)
- print('%sText: %s' % (' ' * indent, content + '...'))
- else:
- print('%sAttachment: %s' % (' ' * indent, content_type))
- #连接到POP3服务器
- server = poplib.POP3(pop3_server)
- #可以打开或关闭调试信息
- server.set_debuglevel(1)
- #可选:打印POP3服务器的欢迎文字
- print(server.getwelcome().decode('utf-8'))
- #身份认证
- server.user(email)
- server.pass_(password)
- #start()返回邮件数量和占用空间
- print('Messages: %s. Size: %s' % server.stat())
- #list()返回所有邮件编号
- resp, mails, octets = server.list()
- #可以查看返回的列表类似[b'1 82923', b'2 2184', ...]
- print(mails)
- #获取最新一封邮件,注意索引号从1开始
- index = len(mails)
- resp, lines, octets = server.retr(index)
- #lines存储了邮件的1原始文本的每一行
- #可以获得整个邮件的原始文本
- msg_content = b'\r\n'.join(lines).decode('utf-8')
- #稍后解析出邮件
- msg = Parser().parsestr(msg_content)
- print_info(msg)
- #关闭连接
- server.close()
运行结果如下:
- Email: xxx@163.com
- Password: xxxxx
- POP3 server: pop.163.com
- +OK Welcome to coremail Mail Pop3 Server (163coms[b62aaa251425b4be4eaec4ab4744cf47s])
- *cmd* 'USER xxx@163.com'
- *cmd* 'PASS xxxxx'
- *cmd* 'STAT'
- *stat* [b'+OK', b'', b'']
- Messages: 1. Size: 2375
- *cmd* 'LIST'
- [b'1 2375']
- *cmd* 'RETR 1'
- From: xxxx<xxxx@qq.com>
- To: xxx <xxx@163.com>
- Subject: Hello, world!
- part 0
- --------------------
- Text: ...
- part 1
- --------------------
- Text: <div><br></div><div> </div>...
资料来源:
1、廖雪峰学习官网
2、kornberg_fresnel的博文:https://blog.csdn.net/kornberg_fresnel/article/details/51227761
Python学习之旅(三十六)的更多相关文章
- python学习之旅(十六)
Python基础知识(15):模块 1.可以把模块想象成导入Python以增强其功能的扩展 2.任何程序都可以作为模块导入 3.导入模块并不意味着在导入的时候执行某些操作,它们主要用于定义变量.函数和 ...
- Python之路(第三十六篇)并发编程:进程、同步异步、阻塞非阻塞
一.理论基础 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所有内容都是围绕进程的概念展开的. 即使可以利用的cpu只有一个(早期的 ...
- Python学习之旅(十二)
Python基础知识(11):高级特性 一.分片(切片) 通过索引来获取一定范围内的元素 #字符串 s="Alice" s[0:4:2] 结果: 'Ai' #列表 l=[1,2,3 ...
- python接口自动化(三十六)-封装与调用--流程类接口关联续集(详解)
简介 上一篇已经给大家都介绍过了流程类接口关联,但是由于博客的登录机制改变,所以没有办法给小伙伴们实战演练一下,那么这篇就按照上一篇计划的用jenkins来给小伙伴们演示一下流程类接口的封装和调用,其 ...
- 流畅python学习笔记:第十六章:协程
通常在python进行编程一般都是使用多线程或者多进程来实现.这里介绍另外一种并发的方式,就是协程,但和多线程以及多进程不一样的是,协程是运行在单线程当中的并发.来看下具体的例子: def simpl ...
- 【WPF学习】第三十六章 样式基础
前面三章介绍了WPF资源系统,使用资源可在一个地方定义对象而在整个标记中重用他们.尽管可使用资源存储各种对象,但使用资源最常见的原因之一是通过他们的保存样式. 样式是可应用于元素的属性值集合.WPF样 ...
- [转] Linux学习之CentOS(三十六)--FTP服务原理及vsfptd的安装、配置
本篇随笔将讲解FTP服务的原理以及vsfptd这个最常用的FTP服务程序的安装与配置... 一.FTP服务原理 FTP(File Transfer Protocol)是一个非常古老并且应用十分广泛的文 ...
- [ExtJS5学习笔记]第三十六节 报表组件mzPivotGrid
mzPivotGrid 是一个报表组件,采用这个组件之后,可以令你的应用体现更多的价值. 什么是pivot grid 什么是mzPivotGrid 学习资源 与图表组件的融合 什么是pivot gri ...
- Python学习之旅(十九)
Python基础知识(18):面向对象高级编程(Ⅰ) 使用__slots__:限制实例的属性,只允许实例对类添加某些属性 (1)实例可以随意添加属性 (2)某个实例绑定的方法对另一个实例不起作用 (3 ...
- Python学习之旅(十八)
Python基础知识(17):面向对象编程(Ⅱ) 获取对象信息 在不知道对象信息的情况下,我们想要去获取对象信息,可以使用以下方法 1.type (1)判断对象类型 >>> type ...
随机推荐
- Redis接口的调用
1.hiredis是redis数据库的C接口,目录为/redis-3.2.6/deps/hiredis 2.示例代码如下: #include <stdio.h> #include < ...
- python接口自动化测试(七)-unittest-批量用例管理
我们日常项目中的接口测试案例肯定不止一个,当案例越来越多时我们如何管理这些批量案例?如何保证案例不重复?如果案例非常多(成百上千,甚至更多)时如何保证案例执行的效率?如何做(批量)测试数据的管理?如何 ...
- 如何卸载EXCEL中的插件?
1.问题:每一次启动,excel都会弹出一个提示框,是因为将treeplan给删除了.找不到. 2.解决办法: 1)在加载项界面,点击转到.就进入自己加载的工具界面 2)将相应项前面的勾取消--但某插 ...
- 如何永久激活(破解) IntelliJ IDEA 2018.2
1.去官网下载并安装 idea 地址:https://www.jetbrains.com/idea/download 文件有点大,耐心等待一会儿. 2.下载破解(crack) jar 包 地址 htt ...
- 内核中的锁机制--RCU
一. 引言 众所周知,为了保护共享数据,需要一些同步机制,如自旋锁(spinlock),读写锁(rwlock),它们使用起来非常简单,而且是一种很有效的同步机制,在UNIX系统和Linux系统中得到了 ...
- Java 连接MongoDB集群的几种方式
先决条件 先运行mongodb肯定是必须的,然后导入以下包: import com.mongodb.MongoClient; import com.mongodb.MongoClientURI; im ...
- 【PHP】PHP的安装和配置
PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言.语法吸收了C语言.Java和Perl的特点,利于学习,使用广泛,主要适用于W ...
- 存货控制中的ABC分类释义
存货控制的ABC制度是根据存货的重要程度把存货归为A.B.C三类,最重要的是A类,最不重要的是C类. A类产品就是指在产品销售进程中,销量比较多,在库存管理方面需要大量备货的产品; B类则是销量适中, ...
- CentOS5.5上安装Python2.7及ez_setup和pip包
CentOS5.5上安装Python2.7及ez_setup和pip包 下载 首先从Python官方下载源代码包下载 编译安装 这里将python安装到/opt/python27文件夹下 tar xv ...
- 9-11-Trie树/字典树/前缀树-查找-第9章-《数据结构》课本源码-严蔚敏吴伟民版
课本源码部分 第9章 查找 - Trie树/字典树/前缀树(键树) ——<数据结构>-严蔚敏.吴伟民版 源码使用说明 链接☛☛☛ <数据结构-C语言版>(严蔚 ...