6、使用poplib模块收取邮件
1)poplib 模块:
- poplib 模块提供了 poplib.POP3 和 poplib.POP3_SSL 两个类,分别用于连接普通的 POP 服务器和基于 SSL 的 POP 服务器
- 使用 poplib.POP3 或 poplib.POP3_SSL 连接到服务器后,按照 POP3 协议与服务器交互
2)POP3协议:
- POP3 协议简介
- POP3 的命令和响应都是基于 ASCII 文本的,并以 CR 和 LF(/r/n)作为行结束符
- 响应包括一个表示返回状态的符号(+/-)和描述信息
- POP3协议的请求和响应格式
- 请求标准格式:命令[参数]CRLF
- 响应标准格式:+OK/[-ERR] description CRLF
- POP3 协议支持的命令
- user name :向 POP 服务器发送登录的用户名
- pass string:向 POP 服务器发送登录的用户名密码
- quit:退出 POP 服务器
- stat:统计邮件服务器状态,包括邮件数和总大小
- list[msg_no]:列出全部邮件或指定邮件,返回邮件编号和对应大小
- retr msg_no:获取指定邮件的内容(根据邮件序号来获取,序号从1开始)
3)Python根据POP3协议调用poplib模块读取邮件内容
步骤:
-
创建邮件服务器连接
import poplib import email.parser, email.policy conn = poplib.POP3_SSL('pop.qq.com', 995) print(conn.getwelcome().decode('UTF-8')) # 打印欢迎信息,输出成功,表示服务端响应正确
+OK QQMail POP3 Server v1.0 Service Ready(QQMail v2.0)
-
登陆邮件服务器
conn.user('wk_helloworld@qq.com') # 相当于使用 user 命令 conn.pass_('kvspaeowbthhbehi') # 相当于使用 pass 命令
b'+OK'
-
统计邮件信息(可无)
num, totalsize = conn.stat() # 相当于 stat 命令 print('邮件数量:', num) print('邮件大小:', totalsize)
邮件数量: 1041 邮件大小: 188610392
-
获取邮件列表
resp, maillist, r = conn.list() # 相当于list命令 print('响应:', resp) print('邮件列表:', maillist[:5]) # 打印前5封邮件的序号和大小
响应: b'+OK' 邮件列表: [b'1 8757', b'2 8677', b'3 8798', b'4 3777', b'5 3739']
-
获取最后一封邮件
resp, maildata, r = conn.retr(len(maillist)) print('响应:', resp) print('邮件数据', maildata[:3]) data = b'\r\n'.join(maildata)
响应: b'+OK' 邮件数据 [b'Date: Wed, 10 Jul 2019 23:54:04 +0800', b'X-QQ-mid: esmtp3t1562774043t0z5c87u9', b'Received: from [10.161.194.102] (unknown [111.53.198.3])']
-
将邮件恢复成为EmailMessage对象
msg = email.parser.BytesParser(policy=email.policy.default).parsebytes(data) print(type(msg)) print('发件人', msg['from']) print('收件人', msg['to']) print('主题', msg['subject']) print('第一个收件人用户名', msg['to'].addresses[0].username) print('第一个发件人用户名', msg['from'].addresses[0].username)
<class 'email.message.EmailMessage'> 发件人 wk <wk_helloworld@qq.com> 收件人 k <929667257@qq.com> 主题 HTML邮件 第一个收件人用户名 929667257 第一个发件人用户名 wk_helloworld
-
遍历邮件内容并输出
# 邮件每个部分都是一个part for part in msg.walk(): # 'multipart'代表邮件内容的容器,无需处理 if part.get_content_type().split("/", 1)[0] == 'multipart': continue # text代表邮件的正文 elif part.get_content_type().split("/", 1)[0] == 'text': print(part.get_content()) # 剩下的为邮件的附件 else: filename = part.get_filename() # 得到附件的文件名 print(filename) # 将附件下载(写入)本地磁盘文件 with open(filename, 'wb') as f: f.write(part.get_payload(decode=True))
<h2>HTML邮件<h2><div style="border:1px:solid red">html邮件内容</div><img src="cid:156277397009.6936.18046803540011509692@DESKTOP-Q042I1B"> test1.jpg test2.jpg
-
退出服务器
conn.quit() # 相当于quit命令
b'+OK Bye'
-
在该python文件的路径下可看到下载好的邮件附件: