> 文章列表 > 【转载+原创】python imaplib读邮件,存附件至本地,标记为已读,搜索邮件-腾讯qq邮箱

【转载+原创】python imaplib读邮件,存附件至本地,标记为已读,搜索邮件-腾讯qq邮箱

【转载+原创】python imaplib读邮件,存附件至本地,标记为已读,搜索邮件-腾讯qq邮箱

借鉴:python高阶教程-使用imap接收邮箱的附件(中文字符编码与MIME) - 码农教程

原版运行代码
 

import imaplib
import email
from email.parser import BytesParser
from email.utils import parseaddr
# 如果是企业邮箱,host要更换成企业邮箱的
host = 'imap.qq.com'
user = 'xxxxx@qq.com'
# 不是登录password,是单独生成的邮箱authCode
passwd = ''
mail_directory = 'INBOX'
conn = imaplib.IMAP4(host)
conn.login(user, passwd)
conn.select(mail_directory)
# status, data = conn.search(None, 'ALL')
# 多条件:来自xxx发件人,未读
status, data = conn.search(None, '(FROM "xxx@qq.com") UNSEEN')
email_list = list(reversed(data[0].split()))def decode_str(s):try:subject = email.header.decode_header(s)except:# print('Header decode error')return Nonesub_bytes = subject[0][0]sub_charset = subject[0][1]if None == sub_charset:subject = sub_byteselif 'unknown-8bit' == sub_charset:subject = str(sub_bytes, 'utf8')else:subject = str(sub_bytes, sub_charset)return subjectdef get_email(num, conn):typ, content = conn.fetch(num, '(RFC822)')msg = BytesParser().parsebytes(content[0][1])sub = msg.get('Subject')for part in msg.walk():fileName = part.get_filename()fileName = decode_str(fileName)if None != fileName:print('+++++++++++++++++++')print(fileName)print(num, decode_str(sub))for num in email_list:get_email(num, conn)
conn.close()
conn.logout()

获取附件

附件的获取按照网络上的代码没有出现问题.

for part in message.walk():  fileName = part.get_filename()  fileName = decode_str(fileName)# 保存附件  if fileName: data = part.get_payload(decode=True) localFileName = "D:\\\\" + fileNamewith open(localFileName,'wb') as f:f.write(data)print("附件%s已保存" % fileName)

按时间搜索 

不能有时间,只能有日期,而且格式是日月年

以下为引用:Python imaplib 搜索带有日期和时间的电子邮件

“不幸的是没有。 中定义的通用IMAP搜索语言RFC 3501 §6.4.4不包括任何按时间搜索的规定。

SINCE被定义为取一个<date>项,该项又被定义为date-day "-" date-month "-" date-year,可以带或不带引号。

IMAP甚至没有时区意识,所以你将不得不根据INTERNALDATE项,在本地过滤掉不符合你范围的前几条信息。 你甚至可能要多取几天的信息。

如果你使用的是Gmail,你也许可以使用Gmail的搜索语言,它可以作为一个extension.”

搜索其他文件夹

众所周知,收件箱统一交inbox,但是自定义或者其他文件呢?

有一个命令可以看到自己邮箱下那些文件夹的具体名称

import imaplib
import email
from email.parser import BytesParser
from email.utils import parseaddr
# 如果是企业邮箱,host要更换成企业邮箱的
host = 'imap.qq.com'
user = 'xxxxx@qq.com'
# 不是登录password,是单独生成的邮箱authCode
passwd = ''
conn = imaplib.IMAP4(host)
conn.login(user, passwd)
# 登录后使用
conn.list()
'''('OK',[b'(\\\\NoSelect \\\\HasChildren) "/" "&UXZO1mWHTvZZOQ-"',b'(\\\\HasNoChildren) "/" "INBOX"',b'(\\\\HasNoChildren) "/" "Sent Messages"',b'(\\\\HasNoChildren) "/" "Drafts"',b'(\\\\HasNoChildren) "/" "Deleted Messages"',b'(\\\\HasNoChildren) "/" "Junk"'])'''
mail_directory = 'Sent Messages'
conn.select("\\"" + mail_directory + "\\"")
# status, data = conn.search(None, 'ALL')
# 多条件:来自xxx发件人,未读
status, data = conn.search(None, '(FROM "xxx@qq.com") UNSEEN')
email_list = list(reversed(data[0].split()))

如果文件夹名有空格,一定要按照一下格式写!

email-Python imaplib 无法选择()自定义 Gmail 标签 - 糯米PHP

与朋友讨论了几个小时后解决了这个问题。事实证明,问题是 imap.select() 想要在邮箱名称周围加上引号,如果它包含空格。所以 imap.select("INBOX") 很好,但有空格你需要 imap.select("\\"" + "Label Name" + "\\"") 

最有效的搜索方式 

试验了一个晚上,发现inbox通过:发件人,日期,是否已读来搜索是最有效的,理论上按照subject应该也是可以的,但是我试了半天,如果使用中文搜索,完全不行,都会搜到一大堆,根本不能完全匹配,只有标题里有英文,通过那个英文搜索才可以完全匹配!

发件人 未读 日期 

conn = imaplib.IMAP4(host)
conn.login(user, passwd)
conn.select('INBOX')
status, data = conn.search(None, '(FROM "xxxx@qq.com") UNSEEN SINCE "05-04-2023"')

标题中含有‘hk_us’的邮件 

conn = imaplib.IMAP4(host)
conn.login(user, passwd)
conn.select('INBOX')
status, data = conn.search(None, 'SUBJECT "hk_us"')

标记为已读

import imaplib
import email
from email.parser import BytesParser
from email.utils import parseaddr
# 如果是企业邮箱,host要更换成企业邮箱的
host = 'imap.qq.com'
user = 'xxxxx@qq.com'
# 不是登录password,是单独生成的邮箱authCode
passwd = ''
mail_directory = 'INBOX'
conn = imaplib.IMAP4(host)
conn.login(user, passwd)
conn.select(mail_directory)
# status, data = conn.search(None, 'ALL')
# 多条件:来自xxx发件人,未读
status, data = conn.search(None, '(FROM "xxx@qq.com") UNSEEN')
email_list = list(reversed(data[0].split()))def decode_str(s):try:subject = email.header.decode_header(s)except:# print('Header decode error')return Nonesub_bytes = subject[0][0]sub_charset = subject[0][1]if None == sub_charset:subject = sub_byteselif 'unknown-8bit' == sub_charset:subject = str(sub_bytes, 'utf8')else:subject = str(sub_bytes, sub_charset)return subjectdef get_email(num, conn):typ, content = conn.fetch(num, '(RFC822)')msg = BytesParser().parsebytes(content[0][1])sub = msg.get('Subject')for part in msg.walk():fileName = part.get_filename()fileName = decode_str(fileName)if None != fileName:print('+++++++++++++++++++')print(fileName)# 标记为已读conn.store(num,'+FLAGS','\\Seen')print(num, decode_str(sub))for num in email_list:get_email(num, conn)
conn.close()
conn.logout()

获取邮件时间

引用:PYTHON 获取邮件发送时间_获取邮件日期_稚麟的博客-CSDN博客 

def get_email(num, conn):typ, content = conn.fetch(num, '(RFC822)')msg = BytesParser().parsebytes(content[0][1])# 获得标题sub = msg.get('Subject')# 获得邮件时间mailDate = msg.get("Date")mailDate = mailDate.split(',')[1]mailDate = datetime.datetime.strptime(mailDate,'%d %b %Y %H:%M:%S %z').strftime('%Y%m%d%H%M%S')

 我用的腾讯邮箱,他里面的日期是以下这样:

Tue, 24 Aug 2021 09:17:00 +0800 (CST)
Mon, 23 Aug 2021 09:35:26 +0000 (UTC)
Wed, 28 Jul 2021 00:51:23 +0000 (GMT)

用split(),把星期去掉,只处理后面的