【转载+原创】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 None
    sub_bytes = subject[0][0]
    sub_charset = subject[0][1]
    if None == sub_charset:
        subject = sub_bytes
    elif 'unknown-8bit' == sub_charset:
        subject = str(sub_bytes, 'utf8')
    else:
        subject = str(sub_bytes, sub_charset)
    return subject


def 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:\\" + fileName
        with 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 None
    sub_bytes = subject[0][0]
    sub_charset = subject[0][1]
    if None == sub_charset:
        subject = sub_bytes
    elif 'unknown-8bit' == sub_charset:
        subject = str(sub_bytes, 'utf8')
    else:
        subject = str(sub_bytes, sub_charset)
    return subject


def 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(),把星期去掉,只处理后面的

更有效的连接邮箱,接收邮件

好吧,这是一种尝试和尝试的方法,但最终我们得到了一个解决方案,虽然不是最佳的,但黑客是每次在脚本从睡眠中唤醒后都重新连接一次,以便从开始获取收件箱,这很容易做到通过刷新页面(就像我们在普通浏览器中重新加载一样),所以看起来可能像这样:

mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login(user,passwd)
while True:
    mail.select("inbox")
    result, idData = mail.uid('search', query, "ALL")
    processIDs(idData)
    time.sleep(60)

借鉴:Python Imaplib:无需重新连接即可获取新的Gmail邮件 | 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mooncrystal123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值