Python imap提取邮件时decode_header解码主题报TypeError如何解决
问题根因
报错由两个核心问题导致:
- 部分邮件不存在
Subject头字段,msg['Subject']返回None值,而decode_header()仅接受字符串/字节类型输入,传入None直接触发类型错误 - 异常捕获块逻辑本身存在错误:
- 重复调用
decode_header(msg['Subject']),如果msg['Subject']为None仍会触发相同报错 isinstance(subject_2, string)写法错误,Python无内置string类型判断;且字符串类型不需要调用decode()方法,会触发新报错- 原代码存在变量名冲突:循环外定义的
data变量被imap.fetch的返回值覆盖,容易引发隐性问题
- 重复调用
修复后代码
import email from email.header import decode_header import imaplib # 此处保留你自己的imap登录逻辑 # imap = imaplib.IMAP4_SSL('imap.gmail.com') # imap.login('你的邮箱', '你的密码') imap.select('[Gmail]/Enviados') typ, search_data = imap.search(None, 'ALL') to=[] subject=[] sent_date=[] delivered_mails=[] read_mails=[] relayed_mails=[] for num in search_data[0].split(): typ, msg_data = imap.fetch(num, '(RFC822)') msg = email.message_from_bytes(msg_data[0][1]) to.append(msg['To']) subject.append(msg['Subject']) sent_date.append(msg['Date']) # 先判断Subject是否为空 raw_subject = msg['Subject'] if not raw_subject: continue # 解码标题 try: subject_2, encoding = decode_header(raw_subject)[0] if isinstance(subject_2, bytes): # 编码为空时默认用utf-8解码,避免报错 subject_2 = subject_2.decode(encoding if encoding else 'utf-8') # 匹配三类状态 if "Delivered" in subject_2: delivered_mails.append(subject_2) elif "READ" in subject_2: read_mails.append(subject_2) elif "RELAYED" in subject_2: relayed_mails.append(subject_2) except Exception as e: # 解码异常直接跳过,避免中断程序 print(f"标题解码失败,跳过:{e}") continue
额外说明
- 如果你需要匹配大小写不敏感的状态(比如delivered、Delivered都算),可以把判断改成
if "delivered" in subject_2.lower(): - 邮件状态不一定都存储在标题里,部分邮件服务商的投递状态会放在
X-*自定义头字段里,如果你后续发现标题里匹配不到,可以打印msg.keys()查看所有头字段找对应的状态字段
内容的提问来源于stack exchange,提问作者alb
相关产品推荐
相关产品推荐

