因为有需求,所以自己就稍微琢磨了一下这个东西,然后代码是从网上找的,目前我已经自测过是可以使用的,而且非常方便省事,这里分享给大家!
直接上代码:
# _*_ coding: utf-8 _*_
import poplib
import email
import os
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
def decode_str(s):
value, charset = decode_header(s)[0]
if charset:
if charset == 'gb2312':
charset = 'gb18030'
value = value.decode(charset)
return value
def get_email_headers(msg):
headers = {}
for header in ['From', 'To', 'Cc', 'Subject', 'Date']:
value = msg.get(header, '')
if value:
if header == 'Date':
headers['Date'] = value
if header == 'Subject':
subject = decode_str(value)
headers['Subject'] = subject
if header == 'From':
hdr, addr = parseaddr(value)
name = decode_str(hdr)
from_addr = u'%s <%s>' % (name, addr)
headers['From'] = from_addr
if header == 'To':
all_cc = value.split(',')
to = []
for x in all_cc:
hdr, addr = parseaddr(x)
name = decode_str(hdr)
to_addr = u'%s <%s>' % (name, addr)
to.append(to_addr)
headers['To'] = ','.join(to)
if header == 'Cc':
all_cc = value.split(',')
cc = []
for x in all_cc:
hdr, addr = parseaddr(x)
name = decode_str(hdr)
cc_addr = u'%s <%s>' % (name, addr)
cc.append(to_addr)
headers['Cc'] = ','.join(cc)
return headers
def get_email_content(message, savepath):
attachments = []
for part in message.walk():
filename = part.get_filename()
if filename:
filename = decode_str(filename)
data = part.get_payload(decode=True)
abs_filename = os.path.join(savepath, filename)
attach = open(abs_filename, 'wb')
attachments.append(filename)
attach.write(data)
attach.close()
return attachments
if __name__ == '__main__':
# 账户信息
email = 'sunn@nfu.edu.cn'
password = 'SUNxxx'
pop3_server = 'imap.exmail.qq.com'
# 连接到POP3服务器,带SSL的:
server = poplib.POP3_SSL(pop3_server)
# 可以打开或关闭调试信息:
server.set_debuglevel(0)
# POP3服务器的欢迎文字:
print(server.getwelcome())
# 身份认证:
server.user(email)
server.pass_(password)
# stat()返回邮件数量和占用空间:
msg_count, msg_size = server.stat()
print('message count:', msg_count)
print('message size:', msg_size, 'bytes')
# b'+OK 237 174238271' list()响应的状态/邮件数量/邮件占用的空间大小
resp, mails, octets = server.list()
for i in range(1, msg_count):
resp, byte_lines, octets = server.retr(i)
# 转码
str_lines = []
for x in byte_lines:
str_lines.append(x.decode())
# 拼接邮件内容
msg_content = '\n'.join(str_lines)
# 把邮件内容解析为Message对象
msg = Parser().parsestr(msg_content)
headers = get_email_headers(msg)
attachments = get_email_content(msg, r'/Users/sun/Desktop')
print('subject:', headers['Subject'])
print('from:', headers['From'])
print('to:', headers['To'])
if 'cc' in headers:
print('cc:', headers['Cc'])
print('date:', headers['Date'])
print('attachments: ', attachments)
print('-----------------------------')
server.quit()
这里主要说明2点:
-
对应代码中的69-71行,需要分别改成自己的邮箱、邮箱密码、邮箱对应的收件POP3服务器。
比如,我使用的是腾讯企业邮箱,那么我的pop3_server就是:
a、收件服务器:imap.exmail.qq.com,使用SSL,端口号993b、发件服务器:smtp.exmail.qq.com,使用SSL,端口号465
https://m.dingtalk.com/qidian/help-keyword-4088
-
第二个需要更改的地方就是对应代码的99行,改成你需要保存的文件的本地路径。
经过本人测试,可正常运行程序!
以上如何附件中的文件命名后缀名都是规范的话,不是出现解码出错的问题,但是我下载的附件中我发现有一个.JPG,是大写字母的话好像就无法正确解码。
发生异常: UnicodeDecodeError
'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
总结,文件规范命名基本上不会出现这样的下载错误。
最后附上代码的源作者:感谢作者,如有侵权,立刻删!
https://blog.csdn.net/ghostresur/article/details/81875574?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-2.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-2.pc_relevant_default&utm_relevant_index=5
大家觉得还不错的话给个小❤️❤️~~~