Python实现邮件自动下载与附件解析实战
本文详解如何使用Python实现邮件自动下载功能。通过对比SMTP、POP3和IMAP协议,重点讲解基于IMAP协议的邮件登录与解析。代码示例展示了如何提取邮件主题、下载附件至指定路径,并解析HTML正文保存为文本文件,同时提及利用Pandas处理表格附件,提供完整的类封装与运行逻辑。
在编写代码之前,首先需要了解三种常见的邮件服务协议:
1、SMTP协议
SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)主要充当中转站角色,负责将邮件从发送方传输至接收方的客户端。
2、POP3协议
POP3(Post Office Protocol 3,邮局协议第3版)是电子邮件的早期离线协议标准。该协议将邮件下载到本地计算机,不与服务器保持同步。其缺点在于容易导致邮件丢失或重复下载相同邮件。
3、IMAP协议
IMAP(Internet Mail Access Protocol,交互式邮件存取协议)允许直接连接远程邮箱进行操作,并能与服务器内容保持同步,适合多设备管理。
接下来介绍Python中的email包。
该包的核心组件是代表电子邮件消息的“对象模型”。应用程序主要通过message子模块中定义的对象模型接口与该包交互。利用此API,用户可以查询现有电子邮件信息、构造新邮件,或添加、移除遵循相同对象模型接口的邮件子组件。简言之,电子邮件对象模型是一个树状结构,包含所有提供EmailMessage API的对象,反映了电子邮件及其MIME子组件的性质。
随后,我们将通过具体代码实现一个登录邮箱客户端的功能,包括下载邮件、解析邮件附件内容等步骤。
首先,我们需要定义一个用于邮件解析的类,该类包含三个关键变量:
1、邮箱所属的IMAP服务地址;
2、邮箱账号;
3、邮箱密码。需要注意的是,不同邮箱服务商有不同的安全策略,例如QQ邮箱需要短信验证并获取登录授权码,而不能直接使用明文密码登录远程客户端。
class Email_parse:
def __init__(self,remote_server_url,email_url,password):
# imap服务地址
self.remote_server_url = remote_server_url
# 邮箱账号
self.email_url = email_url
# 邮箱密码
self.password = password
接着定义类的入口函数,用于登录远程服务器并默认获取第一页的所有邮件。我们会获取邮件主题并打印输出。由于不同邮件主题的编码方式可能不同,二进制数据需要正确转码才能正常显示。
def main_parse_Email(self):
"""入口函数,登录imap服务"""
server = imaplib.IMAP4_SSL(self.remote_server_url, 993)
server.login(self.email_url, self.password)
server.select('INBOX')
status,data = server.search(None,"ALL")
if status != 'OK':
raise Exception('read email error')
emailids = data[0].split()
mail_counts = len(emailids)
print("count:",mail_counts)
# 邮件的遍历是按时间从后往前,这里我们选择最新的一封邮件
for i in range(mail_counts - 1, mail_counts - 2, -1):
status, edata = server.fetch(emailids[i], '(RFC822)')
msg = email.message_from_bytes(edata[0][1])
#获取邮件主题title
subject = email.header.decode_header(msg.get('subject'))
if type(subject[-1][0]) == bytes:
title = subject[-1][0].decode(str(subject[-1][1]))
elif type(subject[-1][0]) == str:
title = subject[-1][0]
print("title:", title)
其中,msg变量保存了邮件的主体内容。由于后续会重复使用msg和title,我们将构造一个类函数来返回这两个值。
def get_email_title(msg):
subject = email.header.decode_header(msg.get('subject'))
if type(subject[-1][0]) == bytes:
title = subject[-1][0].decode(str(subject[-1][1]))
elif type(subject[-1][0]) == str:
title = subject[-1][0]
print("title:", title)
return title
邮件解析分为两部分:邮件正文(HTML格式)和附件(如xlsx等格式)。如果检测到附件,则将其保存到指定路径。表格解析部分不再赘述,使用pandas等库即可轻松处理。
def get_att(msg):
"""获取附件并下载"""
filename = Email_parse.get_email_name(msg)
for part in msg.walk():
file_name = part.get_param("name")
if file_name:
data = part.get_payload(decode=True)
if data != None:
att_file = open('./src/' + filename, 'wb')
att_file.write(data)
att_file.close()
else:
pass
对于邮件正文内容,我们直接解析HTML,并将文本内容保存为.txt文件,以便于后续读取。
def get_text_from_HTML(msg):
"""获取邮件中的html"""
filename = Email_parse.get_email_name(msg)
current_title = Email_parse.get_email_title(msg)
print("filename:",filename,type(filename))
for part in msg.walk():
if not part.is_multipart():
result = part.get_payload(decode=True)
result = result.decode('gbk')
f = open(f'./src/{current_title}.txt','w')
f.write(result)
f.close()
return result
完整代码如下:
import email
import imaplib
from email.header import decode_header
import pandas as pd
import datetime
class Email_parse:
def __init__(self,remote_server_url,email_url,password):
self.remote_server_url = remote_server_url
self.email_url = email_url
self.password = password
def get_att(msg):
filename = Email_parse.get_email_name(msg)
for part in msg.walk():
file_name = part.get_param("name")
if file_name:
data = part.get_payload(decode=True)
if data != None:
att_file = open('./src/' + filename, 'wb')
att_file.write(data)
att_file.close()
else:
pass
def get_email_title(msg):
subject = email.header.decode_header(msg.get('subject'))
if type(subject[-1][0]) == bytes:
title = subject[-1][0].decode(str(subject[-1][1]))
elif type(subject[-1][0]) == str:
title = subject[-1][0]
print("title:", title)
return title
def get_email_name(msg):
for part in msg.walk():
file_name = part.get_param("name")
if file_name:
h = email.header.Header(file_name)
dh = email.header.decode_header(h)
filename = dh[0][0]
if dh[0][1]:
value, charset = decode_header(str(filename, dh[0][1]))[0]
if charset:
filename = value.decode(charset)
print("附件名称:", filename)
return filename
def main_parse_Email(self):
server = imaplib.IMAP4_SSL(self.remote_server_url, 993)
server.login(self.email_url, self.password)
server.select('INBOX')
status,data = server.search(None,"ALL")
if status != 'OK':
raise Exception('read email error')
emailids = data[0].split()
mail_counts = len(emailids)
print("count:",mail_counts)
for i in range(mail_counts - 1, mail_counts - 2, -1):
status, edata = server.fetch(emailids[i], '(RFC822)')
msg = email.message_from_bytes(edata[0][1])
subject = email.header.decode_header(msg.get('subject'))
if type(subject[-1][0]) == bytes:
title = subject[-1][0].decode(str(subject[-1][1]))
elif type(subject[-1][0]) == str:
title = subject[-1][0]
print("title:", title)
Email_parse.get_att(msg)
Email_parse.get_text_from_HTML(msg)
def get_text_from_HTML(msg):
filename = Email_parse.get_email_name(msg)
current_title = Email_parse.get_email_title(msg)
print("filename:",filename,type(filename))
for part in msg.walk():
if not part.is_multipart():
result = part.get_payload(decode=True)
result = result.decode('gbk')
f = open(f'./src/{current_title}.txt','w')
f.write(result)
f.close()
return result
if __name__ == "__main__":
remote_server_url = 'imap.qq.com'
email_url = "*********@qq.com"
password = "**********"
demo = Email_parse(remote_server_url,email_url,password)
demo.main_parse_Email()
运行结果:


以上就是Python实现邮件自动下载的示例详解的详细内容,更多关于Python邮件自动下载的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









