Python按主题关键词筛选邮件 自动定位目标邮件
用imaplib的SUBJECT搜索条件按主题关键词找邮件,支持多关键词与或逻辑,自动把带关键词的邮件挑出来下载附件,附完整可运行代码。
场景痛点
公司每天发"日报""周报""付款通知""发票"之类的邮件,主题里都带固定关键词。要把这类邮件批量找出来处理,手动在网页邮箱搜"日报"再一封封点,遇到不同人写法不一还容易漏。用imaplib的SUBJECT搜索直接按关键词过滤,命中的邮件一次性抓出来,附件同步下载。
用到的库
imaplib、email都是Python标准库,无需pip安装。
# 无需安装,Python3自带
完整代码
# -*- coding: utf-8 -*-
import os
import imaplib
import email
from email.header import decode_header, make_header
IMAP_SERVER = "imap.qq.com"
IMAP_PORT = 993
ACCOUNT = "your_account@qq.com"
PASSWORD = "your_imap_auth_code"
# 主题里包含这些关键词之一就算命中
KEYWORDS = ["日报", "周报", "发票"]
SAVE_DIR = "./attachments_by_subject"
def decode_str(s):
if not s:
return ""
return str(make_header(decode_header(s)))
def safe_filename(name):
for ch in '/\\:*?"<>|':
name = name.replace(ch, "_")
return name or "attachment"
def search_by_keywords():
os.makedirs(SAVE_DIR, exist_ok=True)
mail = imaplib.IMAP4_SSL(IMAP_SERVER, IMAP_PORT)
mail.login(ACCOUNT, PASSWORD)
mail.select("INBOX")
hit_ids = set()
for kw in KEYWORDS:
# SUBJECT按主题搜索,关键词加引号
status, messages = mail.search(None, 'SUBJECT', f'"{kw}"')
if status == "OK" and messages[0]:
for mid in messages[0].split():
hit_ids.add(mid)
print(f"命中 {len(hit_ids)} 封邮件")
count = 0
for msg_id in hit_ids:
status, msg_data = mail.fetch(msg_id, "(BODY.PEEK[])")
msg = email.message_from_bytes(msg_data[0][1])
subject = decode_str(msg.get("Subject"))
sender = decode_str(msg.get("From"))
print(f" 命中:{subject} 来自 {sender}")
# 顺手把附件下载下来
for part in msg.walk():
filename = part.get_filename()
if not filename:
continue
filename = safe_filename(decode_str(filename))
payload = part.get_payload(decode=True)
if payload is None:
continue
filepath = os.path.join(SAVE_DIR, filename)
i = 1
base, ext = os.path.splitext(filepath)
while os.path.exists(filepath):
filepath = f"{base}_{i}{ext}"
i += 1
with open(filepath, "wb") as f:
f.write(payload)
count += 1
mail.logout()
print(f"完成,下载附件 {count} 个")
if __name__ == "__main__":
search_by_keywords()
代码讲解
mail.search(None, 'SUBJECT', f'"{kw}"'):IMAP服务器端按主题搜索,命中主题里包含关键词的邮件。和FROM一样是子串匹配。- 多关键词逻辑:对每个关键词单独search,结果用set去重。这是"或"关系——命中任意一个关键词就算。
- 想要"与"关系(主题同时含两个词),把多个条件放在同一次search里:
mail.search(None, 'SUBJECT', '"日报"', 'SUBJECT', '"张三"')。 - 中文字符在IMAP搜索里要注意编码:上面这种直接传中文字符串给imaplib,它会按ASCII处理,中文关键词在部分邮箱上可能搜不到。搜不到时改用本地过滤——先
ALL把邮件拉下来,再用if kw in decode_str(subject)判断。 - 命中后顺手遍历
msg.walk()下载附件,和上一篇逻辑一样。
运行结果
终端列出所有主题里带"日报/周报/发票"的邮件,附件自动存到attachments_by_subject。如果搜中文关键词没结果,就用代码讲解里说的本地过滤法兜底。
注意事项
- IMAP搜索本身对中文支持不好,QQ、163的服务器端搜中文经常返回空。实战里更稳的做法是:
search(None, "ALL")拉最近邮件,再在Python里if any(kw in subject for kw in KEYWORDS)本地过滤,只是邮件量大时慢一些。 - 关键词区分大小写不严格,SUBJECT搜索对英文不区分大小写。
- 主题里常带"Re:""Fwd:"前缀,关键词命中不受影响,因为是子串匹配。
- 想排除某些主题(比如"退信""测试"),就在本地过滤时加
if "退信" in subject: continue。 - 搜索结果编号是会话临时ID,不要存到数据库里跨会话用。

更新时间:2026-09-14 21:09:04