做自动化办公项目中,经常会和邮箱打交道,这里记录了python应用poplib, email获取邮件内容
# 登录邮箱下载附件
class Down_Email():
def __init__(self, user, password, email_server):
# 输入地址,口令和POP3服务器地址
self.user = user
# 此处密码是授权码,用于登录第三方邮箱客户端
self.password = password
self.pop3_server = email_server
# 字符编码转换
# @staticmethod
def decode_str(self, str_in):
if str_in is None:
value = ''
return value
value, charset = decode_header(str_in)[0]
if charset:
value = value.decode(charset)
return value
# 解析邮件,获取邮件
def get_att(self, msg_in, folder_rule, date3, id, Subject):
attachment_files = []
for part in msg_in.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]:
# 将附件名称可读化
filename = self.decode_str(str(filename, dh[0][1]))
# print(filename)
if ".PDF" in filename or ".pdf" in filename:
# 下载附件
# print(f'正在读取{filename}')
data = part.get_payload(decode=True)
filename = filename.replace('/', '_').replace('\r\n', '')
# now = str(int(time.time()))
att_file = open(os.path.join(dowload_path, filename), 'wb')
att_file.write(data) # 保存附件
att_file.close()
logger.info(f'Save【{filename}】to {dowload_path} directory')
attachment_files.append(filename)
elif ".XLS" in filename or ".xls" in filename:
data = part.get_payload(decode=True)
filename = filename.replace('/', '_')
# att_file = open(os.path.join(os.getcwd(), 'Download File', filename), 'wb')
att_file = open(os.path.join(dowload_path, filename), 'wb')
att_file.write(data)
att_file.close()
logger.info(f'Save【{filename}】to {dowload_path} directory')
attachment_files.append(filename)
download_filename = find_new_file(dowload_path)
dispose_file(download_filename,director_number_list)
logger.info(f'{download_filename}数据处理完成')
file_send_email(filename, Subject)
return attachment_files
# 连接服务器,获取指定日期的邮件
def run_ing(self, start_day, end_day,folder_rule):
end_day = end_day
str_day = start_day # 日期赋值
print(f'The date of getting PDF mail is {str_day}to {end_day}')
# 连接到POP3服务器,有些邮箱服务器需要ssl加密,可以使用poplib.POP3_SSL
try:
telnetlib.Telnet(self.pop3_server, 995)
self.server = poplib.POP3_SSL(self.pop3_server, 995, timeout=10)
# print('try')
except:
time.sleep(5)
self.server = poplib.POP3(self.pop3_server, 110, timeout=10)
self.server.user(self.user)
self.server.pass_(self.password)
# 返回邮件数量和占用空间:
print('Number of messages %s. Occupied space: %s' % self.server.stat())
# list()返回所有邮件的编号:
resp, mails, octets = self.server.list()
# 可以查看返回的列表类似[b'1 82923', b'2 2184', ...]
# print(mails)
index = len(mails)
print(f'共{index}多封邮件')
for i in range(index, 0, -1): # 倒序遍历邮件
# for i in range(1, index + 1):# 顺序遍历邮件
resp, lines, octets = self.server.retr(i)
# lines存储了邮件的原始文本的每一行,
# 邮件的原始文本:
msg_content = b'\r\n'.join(lines).decode('utf-8')
# 解析邮件:
msg = Parser().parsestr(msg_content)
# 获取发件人
From = parseaddr(msg.get('from'))[1]
# 获取收件人
To = parseaddr(msg.get('To'))[1]
# 抄送人
Cc = parseaddr(msg.get_all('Cc'))[1]
# 获取邮件主题
Subject = self.decode_str(msg.get('Subject'))
date = msg.get("Date")[0:25]
# print('from:%s,to:%s,Cc:%s,subject:%s' % (From, To, Cc, Subject))
# 获取邮件时间,格式化收件时间
date = msg.get("Date")[0:25]
# print('date12',date)
if date.find('+') >= 0:
date = msg.get("Date")[0:20]
# print('date12', date)
date1 = time.strptime(date, '%d %b %Y %H:%M:%S')
else:
# print('----date---', date.split("\r")[0])
date = date.strip()
date1 = time.strptime(date, '%a, %d %b %Y %H:%M:%S')
# 邮件时间格式转换
date2 = time.strftime("%Y-%m-%d", date1)
date3 = time.strftime("%Y%m%d", date1)
# 从最近的日期获取邮件
if Subject.find('Daily Exercise Report ')> 0:
id = (index + 1 - i)
if date2 < str_day and (index + 1 - i) > 200:
# attach_file = self.get_att(msg, str_day)
break # 倒叙用break
# continue # 顺叙用continue
elif date2 < str_day or date2 > end_day:
print(f'Reading {id} message,Read on {date2}')
continue
else:
print(f'download {id} message,Read on {date2}')
# 获取附件
# try:
# 解析邮件,获取附件
attach_file = self.get_att(msg, folder_rule, date3, id, Subject)
# except Exception as e:
# print('Unknown exception', e, type(e))
# time.sleep(2)
# print(attach_file)
# 可以根据邮件索引号直接从服务器删除邮件:
# self.server.dele(7)
self.server.quit()