Python使用poplib模块实现收取邮件

本篇文章为大家展示了Python使用 poplib模块实现收取邮件,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

成都创新互联公司是网站建设专家,致力于互联网品牌建设与网络营销,专业领域包括做网站、成都做网站、电商网站制作开发、重庆小程序开发、微信营销、系统平台开发,与其他网站设计及系统开发公司不同,我们的整合解决方案结合了恒基网络品牌建设经验和互联网整合营销的理念,并将策略和执行紧密结合,且不断评估并优化我们的方案,为客户提供全方位的互联网品牌整合方案!

使用 poplib 模块收取邮件也很简单,该模块提供了 poplib.POP3 和 poplib.POP3_SSL 两个类,分别用于连接普通的 POP 服务器和基于 SSL 的 POP 服务器。

一旦使用 poplib.POP3 或 poplib.POP3_SSL 连接到服务器之后,接下来基本就按照 POP3 协议与服务器进行交互。为了更好地理解 poplib 模块的运行机制,下面先简单介绍 POP3 协议内容。

POP3 协议也属于请求,响应式交互协议,当客户端连接到服务器之后,客户端向 POP 服务器发送请求,而 POP 服务器则对客户端生成响应数据,客户端可通过响应数据下载得到邮件内容。当下载完成后,邮件客户端可以删除或修改任意邮件,而无须与电子邮件服务器进行进一步交互。

POP3 的命令和响应数据都是基于 ASCII 文本的,并以 CR 和 LF(/r/n) 作为行结束符,响应数据包括一个表示返回状态的符号(+/)和描述信息。

请求和响应的标准格式如下:

请求标准格式:命令 [参数] CRLF
响应标准格式:+OK /[-ERR] description CRLF

POP3 协议客户端的命令和服务器端对应的响应数据如下:

user name:向 POP 服务器发送登录的用户名。

pass string:向 POP 服务器发送登录的密码。

quit:退出 POP 服务器。

stat:统计邮件服务器状态,包括邮件数和总大小。

list [msg_no]:列出全部邮件或指定邮件。返回邮件编号和对应大小。

retr msg_no:获取指定邮件的内容(根据邮件编号来获取,编号从 1 开始)。

dele msg_no:删除指定邮件(根据邮件编号来删除,编号从 1 开始)。

noop:空操作。仅用于与服务器保持连接。

rset:用于撤销 dele 命令。

poplib 模块完全模拟了上面命令,poplib.POP3 或 poplib.POP3_SSL 为上面命令提供了相应的方法,开发者只要依次使用上面命令即可从服务器端下载对应的邮件。

使用 poplib 收取邮件可分为两步:

使用 poplib.POP3 或 poplib.POP3_SSL 按 POP3 协议从服务器端下载邮件。

使用 email.parser.Parser 或 email.parser.BytesParser 解析邮件内容,得到 EmailMessage 对象,从 EmailMessage 对象中读取邮件内容。

下面程序示范了如何使用 poplib 模块来收取邮件:

import poplib, os.path, mimetypes
from email.parser import BytesParser, Parser
from email.policy import default

# 输入邮件地址, 口令和POP3服务器地址:
email = 'kongyeeku@qq.com'
password = '123456'
pop3_server = 'pop.qq.com'

# 连接到POP 3服务器:
#conn = poplib.POP3(pop3_server, 110)
conn = poplib.POP3_SSL(pop3_server, 995)
# 可以打开或关闭调试信息:
conn.set_debuglevel(1)
# 可选:打印POP 3服务器的欢迎文字:
print(conn.getwelcome().decode('utf-8'))
# 输入用户名、密码信息
# 相当于发送POP 3的user命令
conn.user(email)
# 相当于发送POP 3的pass命令
conn.pass_(password)
# 获取邮件统计信息,相当于发送POP 3的stat命令
message_num, total_size = conn.stat()
print('邮件数: %s. 总大小: %s' % (message_num, total_size))
# 获取服务器上的邮件列表,相当于发送POP 3的list命令
# resp保存服务器的响应码
# mails列表保存每封邮件的编号、大小
resp, mails, octets = conn.list()
print(resp, mails)
# 获取指定邮件的内容(此处传入总长度,也就是获取最后一封邮件)
# 相当于发送POP 3的retr命令
# resp保存服务器的响应码
# data保存该邮件的内容
resp, data, octets  = conn.retr(len(mails))
# 将data的所有数据(原本是一个字节列表)拼接在一起
msg_data = b'\r\n'.join(data)
# 将字符串内容解析成邮件,此处一定要指定policy=default
msg = BytesParser(policy=default).parsebytes(msg_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)
for part in msg.walk():
    counter = 1
    # 如果maintype是multipart,说明是容器(用于包含正文、附件等)
    if part.get_content_maintype() == 'multipart' :
        continue
    # 如果maintype是multipart,说明是邮件正文部分
    elif part.get_content_maintype() == 'text':
        print(part.get_content())
    # 处理附件
    else :
        # 获取附件的文件名
        filename = part.get_filename()
        # 如果没有文件名,程序要负责为附件生成文件名
        if not filename:
            # 根据附件的contnet_type来推测它的后缀名
            ext = mimetypes.guess_extension(part.get_content_type())
            # 如果推测不出后缀名
            if not ext:
                # 使用.bin作为后缀名
                ext = '.bin'
            # 程序为附件来生成文件名
            filename = 'part-%03d%s' % (counter, ext)
        counter += 1
        # 将附件写入的本地文件
        with open(os.path.join('.', filename), 'wb') as fp:
            fp.write(part.get_payload(decode=True))
# 退出服务器,相当于发送POP 3的quit命令
conn.quit()

上面程序通过 poplib 模块使用 POP3 命令从服务器端下载邮件,其实就是依次发送 user、pass、stat、list、retr 命令的过程。当 retr 命令执行完成后,将得到最后一封邮件的数据 data,该 data 是一个 list 列表,因此程序需要先将这些数据拼接成一个整体,然后使用 ① 号代码将邮件数据恢复成 EmailMessage 对象。

这里有一点需要指出,程序在创建 BytesParser(解析字节串格式的邮件数据)或 Parser(解析字符串格式的邮件数据)时,必须指定 policy=default;否则,BytesParse 或 Parser 解析邮件数据得到的就是过时的 Message 对象,处理起来非常不方便。程序在 ① 号代码之后特意输出了解析得到的 msg 类型,此时应该看到的是 EmailMesssage,而不是过时的 Message 对象。

在 ① 号代码之前,就是完成 poplib 模块收取邮件的第一步,即从服务器端下载邮件;在 ① 号代码之后,就是完成 poplib 模块收取邮件的第二步,也就是解析邮件内容。

如果程序要获取邮件的发件人、收件人和主题,直接通过 EmailMessage 的相应属性来获取即可,与前面为 EmailMessage 设置发件人、收件人和主题的方式是对应的。

如果程序要读取 EmailMessage 的各部分,则需要调用该对象的 walk() 方法,该方法返回一个可迭代对象,程序使用 for 循环遍历 walk() 方法的返回值,对邮件内容进行逐项处理:如果邮件某项的 maintype 是 'multipart',则说明这一项是容器,用于包含邮件内容、附件等其他项。如果邮件某项的 maintype 是 'text',则说明这一项的内容是文本,通常就是邮件正文或文本附件。对于这种文本内容,程序直接将其输出到控制台中。如果邮件某项的 maintype 是其他,则说明这一项的内容是附件,程序将附件内容保存在本地文件中。
运行上面程序,可以看到程序收取了指定邮件的最后一封邮件,并将邮件内容输出到控制台中,将邮件附件保存在本地文件中。

上述内容就是Python使用 poplib模块实现收取邮件,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注创新互联行业资讯频道。


分享题目:Python使用poplib模块实现收取邮件
文章地址:http://hbruida.cn/article/pgpise.html