Python|解析eml文件,批量下载邮件附件
目前在做文职工作,所以必须得找点方法让自己保持思考。
其中一项工作是要管理邮箱,经常需要和四五六七八十个单位发送和接收邮件并下载附件。
之前就是一个一个点开,然后点击复制,然后把它们从下载挪到邮箱里。
然后有一天发现菜单栏有一个打包下载功能。
于是试了一下,但是下载出来的文件是eml格式
用Python可以对eml文件进行解析
获取解析邮件内容
# 获取邮件内容
def get_message(eml_file):
# 解析 eml 文件
with open(eml_file, 'rb') as eml_file:
eml_content = eml_file.read()
# 解析EML文件内容
msg = email.message_from_bytes(eml_content)
return msg
# 获取发件人
def get_sender(message):
# sender = decode_and_extract(message['From'])
sender=message.get("From")
return decode_and_extract(sender)
decode方法是因为因为获取的From长这样,所以需要进行解码
From: =?UTF-8?B?一串Base64编码的UTF-8字符串?= <邮箱地址>
解码方法:
def decode_and_extract(input_str):
# 使用正则表达式匹配编码的UTF-8字符串和邮箱地址
match = re.match(r'=\?UTF-8\?B\?(.*?)\?= <(.*?)>', input_str)
if match:
encoded_part = match.group(1)
email = match.group(2)
# 解码Base64编码的UTF-8字符串
decoded_bytes = base64.b64decode(encoded_part)
decoded_str = decoded_bytes.decode('utf-8')
return decoded_str, email
else:
# 如果没有匹配到,则返回None
return None, None
解码后返回收件人和邮箱。
返回的收件人是一个string(可以用type()函数查看),但是收件人当不止一个,需要将其转化为数组。
使用split函数将其分割,然后解码,将单个对象加入新的数组,返回收件人数组。
=?UTF-8?B?收件人1==?= <邮箱1>,
=?UTF-8?B?收件人2==?= <邮箱2>
# 获取收件人
def get_recipient(message):
res=[]
recipients = message.get("To").split(",")
for rec in recipients:
res.append(decode_and_extract(rec.strip()))
return res
Subject: =?UTF-8?B?乱码1==?=
=?UTF-8?B?乱码2?=
=?UTF-8?B?乱码3?=
邮件主题返回的也是string,前面的方法和收件人一样,因为这里没有邮件地址,所以解码方法里也不需要匹配邮件地址
def get_subject(message):
res = []
str= message.get("Subject")
recipients = str.split("\n")
for rec in recipients:
res.append(decode_rfc2047(rec.strip()))
decoded_text = ''.join(res)
return decoded_text
def decode_rfc2047(encoded_str):
# 使用正则表达式匹配RFC 2047编码的字符串
match = re.match(r'=\?UTF-8\?B\?(.*?)\?=', encoded_str)
if match:
encoded_part = match.group(1)
decoded_bytes = base64.b64decode(encoded_part)
decoded_str = decoded_bytes.decode('utf-8')
return decoded_str
else:
# 如果没有匹配到,则返回None
return None
然后得到一个类似这样的数组,所以也需要使用join()方法把数组内容连接起来
["我是",“邮件”,“主题”]
# 下载附件
def get_and_download_attachment(msg,save_dir):
if not os.path.exists(save_dir):
os.makedirs(save_dir)
# 遍历邮件的各个部分
for part in msg.walk():
# 判断是否为multipart类型,如果是则跳过
if part.get_content_maintype() == 'multipart':
continue
# 判断是否有Content-Disposition头部,且其值为attachment,表示该部分为附件
content_disposition = part.get('Content-Disposition')
if content_disposition and 'attachment' in content_disposition:
# 获取附件的文件名
res=[]
f = part.get_filename().split("\n")
for i in f:
res.append(decode_rfc2047(i.strip()))
filename = ''.join(res)
print(filename)
if filename:
# 保存附件到本地文件系统
filepath = os.path.join(save_dir, filename)
with open(filepath, 'wb') as f:
f.write(part.get_payload(decode=True))
print("附件已保存: "+filepath)
从邮箱打包下载相关邮件之后就可以遍历文件夹对附件进行下载了。
def traverse_and_download_attachment(root_folder,save_dir):
for subdir in os.listdir(root_folder):
subdir_path = os.path.join(root_folder, subdir)
msg=get_message(subdir_path)
get_and_download_attachment(msg,save_dir)
作者:NuageL