使用Python3 imap_tools库筛选指定发件人未读邮件报错求助
解决imap_tools查询指定发件人未读邮件的报错问题
看起来你的邮件服务器的IMAP实现不支持同时组合FROM和UNSEEN这两个搜索条件,这就是报错Unsupported search criterion: FROM "ZOYA1608@YANDEX.RU" UNSEEN的原因——很多小众或者配置特殊的邮件服务器会有这类限制,拒绝这种复合搜索请求。
下面给你两种可行的解决方案:
方案一:本地筛选(最稳妥)
先从服务器获取所有未读邮件,然后在本地筛选出目标发件人的邮件。这种方式把筛选逻辑从IMAP服务器转移到本地,避开了服务器的搜索限制:
from imap_tools import parse_email_address # 可选,用于更精准匹配邮箱地址 with open("..\\conf\\conf.yaml", mode="r") as stream: for conf in yaml.safe_load_all(stream): with MailBox(conf['host']).login(conf['mailbox'], conf['password']) as mailbox: for sender in conf['senders']['from']: # 先拉取所有未读邮件 for msg in mailbox.fetch(Q(seen=False)): # 精准匹配邮箱地址(忽略显示名和大小写) sender_email = parse_email_address(msg.from_)[1].lower() if sender_email == sender.lower(): for att in msg.attachments: with open(get_path(file_name=att.filename, store_paths=conf['store_paths']), 'w+b') as f: f.write(att.payload)
这里用parse_email_address工具是为了处理类似"Zoya" <ZOYA1608@YANDEX.RU>这种带显示名的发件人格式,确保只匹配纯邮箱地址部分,避免因为显示名导致匹配失败。
方案二:尝试原始IMAP搜索语句(视服务器情况而定)
如果你的服务器只是对imap_tools的Q对象生成的命令格式不兼容,可以试试直接传入原始的IMAP搜索字符串:
with open("..\\conf\\conf.yaml", mode="r") as stream: for conf in yaml.safe_load_all(stream): with MailBox(conf['host']).login(conf['mailbox'], conf['password']) as mailbox: for sender in conf['senders']['from']: # 直接使用原始IMAP搜索指令 search_query = f'(FROM "{sender}" UNSEEN)' for msg in mailbox.fetch(search_query): for att in msg.attachments: with open(get_path(file_name=att.filename, store_paths=conf['store_paths']), 'w+b') as f: f.write(att.payload)
不过这个方案不一定能解决问题,因为本质还是取决于服务器是否支持该组合搜索。
为什么原代码会报错?
imap_tools的Q(from_=sender, seen=False)会生成一个复合的IMAP搜索命令,但你的邮件服务器不支持同时使用FROM和UNSEEN这两个筛选条件,因此返回了NO状态,触发了UnexpectedCommandStatusError异常。
内容的提问来源于stack exchange,提问作者N. Turshiev
相关产品推荐
相关产品推荐

