Python批量删除垃圾邮件 imaplib清理收件箱
用imaplib按发件人、主题关键词筛选垃圾邮件,加\Deleted标志并expunge彻底删除,带dry-run预览防止误删,附完整可运行代码。
场景痛点
订阅的营销邮件、退信、钓鱼广告,每天收件箱攒几十封,手动删要点半天。按发件人、主题关键词把这些垃圾邮件批量清掉,再配合定期跑,收件箱只留真正要看的。但删邮件是不可逆操作,脚本必须先列出要删哪些让人确认,再真删。
用到的库
imaplib、email都是Python标准库,无需pip安装。
# 无需安装,Python3自带
完整代码
# -*- coding: utf-8 -*-
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"
# 垃圾邮件规则:发件人包含这些域名 或 主题含这些关键词
SPAM_SENDERS = ["newsletter@spam.com", "promo@marketing.cn"]
SPAM_SUBJECT_KEYWORDS = ["促销", "免费领取", "中奖", "发票异常"]
DRY_RUN = True # True只预览不真删,确认无误后改False
def decode_str(s):
if not s:
return ""
return str(make_header(decode_header(s)))
def is_spam(msg):
sender = decode_str(msg.get("From") or "").lower()
subject = decode_str(msg.get("Subject") or "")
for s in SPAM_SENDERS:
if s.lower() in sender:
return True
for kw in SPAM_SUBJECT_KEYWORDS:
if kw in subject:
return True
return False
def clean_spam():
mail = imaplib.IMAP4_SSL(IMAP_SERVER, IMAP_PORT)
mail.login(ACCOUNT, PASSWORD)
mail.select("INBOX")
# 先拉最近500封判断,避免扫全量历史
status, messages = mail.search(None, "ALL")
ids = messages[0].split()[-500:]
to_delete = []
for mid in ids:
_, data = mail.fetch(mid, "(BODY.PEEK[HEADER])")
msg = email.message_from_bytes(data[0][1])
if is_spam(msg):
to_delete.append((mid, decode_str(msg.get("Subject")), decode_str(msg.get("From"))))
print(f"共筛选出 {len(to_delete)} 封疑似垃圾邮件:")
for mid, subj, sender in to_delete:
print(f" [{mid.decode()}] {subj} <- {sender}")
if DRY_RUN:
print("\n当前是预览模式(DRY_RUN=True),未真正删除。确认后把DRY_RUN改成False再跑。")
mail.logout()
return
# 真删:先加\Deleted标志,再expunge物理删除
for mid, _, _ in to_delete:
mail.store(mid, "+FLAGS", "\\Deleted")
mail.expunge()
print(f"\n已永久删除 {len(to_delete)} 封")
mail.logout()
if __name__ == "__main__":
clean_spam()
代码讲解
- 删除分两步:先
store(mid, "+FLAGS", "\\Deleted")给邮件打上删除标志,再expunge()把所有带这个标志的邮件从服务器物理抹掉。只store不expunge,邮件还在服务器上,只是标了个记号。 DRY_RUN开关:默认只打印要删的清单,不真删。这是删除类脚本必须有的安全闸,先跑一遍预览,看清单没问题再改False。BODY.PEEK[HEADER]:只抓邮件头来判断发件人、主题,不下载正文和附件,速度快一个数量级,也不会误标已读。is_spam:自定义规则,发件人域名命中或主题命中关键词就算垃圾。规则可以按自己邮箱情况加,比如"退信""自动回复"。- 只扫最近500封:全量扫历史容易把正常老邮件误判,窗口小一点风险低。
运行结果
第一次跑打印所有疑似垃圾邮件的清单,不动真格。核对完把DRY_RUN改成False再跑,这些邮件从服务器上彻底删除,网页邮箱里也消失。
注意事项
- 永久删除不可恢复,跑之前一定要先DRY_RUN预览。重要邮箱建议先在网页邮箱把重要邮件移到别的文件夹。
- 不同邮箱删除后可能进"已删除"文件夹,expunge之后才是真没了;QQ、163一般expunge就直接清空。
- 规则别写太宽。比如只匹配"发票"两个字,正常的"发票已开请查收"也会被删。关键词尽量长一点、特征明确一点。
- 想更安全:不要expunge,只
+FLAGS \\Deleted,让邮件进已删除文件夹,定期人工清空,给一次后悔机会。 - 附件类垃圾邮件删之前想清楚,脚本默认不下载附件,只删邮件本身。

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