第一次实习,什么也不会,公司让写一个自动定时读取邮件的代码,只好自己去网上搜,踩了很多坑,现在终于弄好了,在这里记录一下,也希望能给需要的人一点帮助。
首先就是登陆邮箱并读取邮件,outlook的话一般使用imap连接,如果是qq邮箱可以使用pop3连接,因为pop3连接一般要求账号是数字开头,但是一般邮件如outlook都是字母开头,所以除了qq邮箱其他建议使用imap。我这边的要求是读取未读邮件。所以email_type选择的是UNSEEN,如果是全部读取可以设置为ALL。
# 登陆邮箱并读取原始邮件
def get_mail(email_address, passsword):
# 选择服务器
server = imaplib.IMAP4_SSL('outlook.office365.com')
server.login(email_address, passsword)
inbox = server.select("INBOX")
# 搜索匹配的邮件
email_type, data = server.search(None, "UNSEEN")
# 邮件列表,使用空格分割得到邮件索引
msglist = data[0].split()
if len(msglist) != 0:
# 最新邮件
latest = msglist[len(msglist)-1]
email_type, datas = server.fetch(latest, '(RFC822)')
# 使用utf-8解码
text = datas[0][1].decode('utf-8')
# 转为email.message对象
message = email.message_from_string(text)
# 获取未读邮件数量
server.select()
email_unseen_count = len(server.search(None, 'UNSEEN')[1][0].split())
print('未读邮件一共有:', email_unseen_count)
email_unseen_id_byte = server.search(None, 'UNSEEN')[1][0].split()
email_unseen_id = []
for row in email_unseen_id_byte:
email_unseen_id.append(row.decode('utf-8'))
print(email_unseen_id)
return message
else:
print("暂无未读邮件")然后就是解析邮件内容了,将原始邮件转化为可读邮件,邮件的subject或者email中包含的名字都是经过编码后的字符串,要正常显示就必须decode,定义一个decode函数。
# 将原始邮件转化为可读邮件
def decode_str(s):
value, charset = decode_header(s)[0]
if charset:
value = value.decode(charset)
return value这里有一个注意的点是导入decode_headers时是从email.header中导入,如果从nntplib中导入会因为格式不对而报错。
import email
import imaplib
from email.utils import parseaddr
from email.header import decode_header #正确
#from nntplib import decode_header 错误为了防止非utf-8编码的邮件无法显示,定义一个检测邮件编码函数
def guess_charset(msg):
charset = msg.get_charset()
if charset is None:
content_type = msg.get('Content-Type','').lower()
pos = content_type.find('charset=')
if pos >= 0:
charset = content_type[pos + 8:].strip()
return charset接下来是通过循环遍历来读取邮件内容
def print_info(msg, indent=0):
if indent == 0:
for header in ['From', 'To', 'Subject']:
value = msg.get(header, '')
if value:
if header == 'Subject':
value = decode_str(value)
else:
hdr, addr = parseaddr(value)
name = decode_str(hdr)
value = u'%s <%s>' % (name, addr)
print('%s%s: %s' % (' ' * indent, header, value))
'''
if msg.is_multipart():
parts = msg.get_payload()
for n, part in enumerate(parts):
#print('%spart %s' % (' ' * indent, n))
#print('%s--------------------' % (' ' * indent))
print_info(part, indent + 1)
else:
content_type = msg.get_content_type()
if content_type == 'text/plain' or content_type == 'text/html':
content = msg.get_payload(decode=True)
charset = guess_charset(msg)
if charset:
content = content.decode(charset)
print('%sText: %s' % (' ' * indent, content + '...'))
else:
print('%sAttachment: %s' % (' ' * indent, content_type))
'''上面的代码中被注释掉的是邮件的内容,因为我觉得内容太多不想显示所以就注释掉了,有需要的可以自己去掉注释符号。
最后就是主函数调用上面的函数,输出邮件内容了
if __name__ == "__main__":
email_addr = "xxxxxxxx@outlook.com"
password = "xxxxxxxxx"
messageObject = get_mail(email_addr, password)
if messageObject:
msgDate = messageObject["date"]
print("发送时间:%s" % msgDate)
res = print_info(messageObject)
print(res)email_addr就是邮件的账号,password就是密码,我还设置了一个发送的时间,是对方发送邮件的时间,如果对方是别的国家,时间可能和这边对不上,我也暂时没找到合适的解决办法
给大家看一下结果,这是不显示邮件内容的情况下

因为想要更加解放人力,所以设置了定时启动程序,这样每天只要打开定时程序就可以了
#定义tick,执行我们的python读取邮件任务
def tick():
print("tick! the time is :%s" % datetime.now())
os.system("python email_imaplib_t.py")
#设置每10分钟运行一次tick,每5分钟睡眠一次
if __name__ == "__main__":
scheduler = BackgroundScheduler(timezone="Asia/ShangHai")
scheduler.add_job(tick, 'interval', minutes=10, start_date="2022-4-1 15:00:00")
scheduler.start()
print("Press ctrl + {0} to exit".format('Break' if == 'nt' else 'C'))
try:
while True:
time.sleep(300)
print(f"sleep!-{datetime.now()}")
except(KeyboardInterrupt, SystemExit):
scheduler.shutdown()
print("exit the job")结果如下

















