You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python email模块处理邮件时遇int类型错误问题求助

问题分析与解决方案

问题根源

  1. 邮件ID失效:循环内执行server.expunge()会触发邮箱邮件重新编号,你提前获取的未读邮件ID列表(msg_list)在expunge后已经失效,用旧ID调用fetch会得到错误响应,而非目标邮件内容。
  2. 错误处理fetch结果:imaplib.fetch()返回的data中可能混有状态响应(字节串格式),直接取data[0][1]会在非邮件内容项时得到字节的ASCII数值(比如b'62 (...)'[1]对应字符'2'的ASCII码50),导致email_body变成int类型,触发decode属性错误。

修正后的代码

import imaplib
import email
import os

download_folder = "/Users/zonghan/Desktop"

def get_mail(username, password):
    server = imaplib.IMAP4_SSL('imap.gmail.com')
    server.login(username, password)
    # 可读写模式打开收件箱,若仅测试可改为readonly=True避免误操作
    server.select("INBOX", readonly=False)
    
    email_type, items = server.search(None, "UNSEEN")
    msg_list = items[0].split()
    
    for email_id in msg_list:
        print(f'id:{email_id}')
        email_type, data = server.fetch(email_id, "(RFC822)")
        
        # 过滤出真正的邮件内容元组
        email_body = None
        for item in data:
            if isinstance(item, tuple):
                email_body = item[1]
                break
        if not email_body:
            print(f"无法获取邮件 {email_id} 的内容")
            continue
        
        print(email_body[:100], type(email_body))  # 仅打印前100字节避免输出过长
        mail = email.message_from_bytes(email_body)
        
        # 标记邮件为已读
        server.store(email_id, '+FLAGS', '\\Seen')
        
        # 处理邮件附件逻辑
        for part in mail.walk():
            # 跳过多部分容器
            if part.get_content_maintype() == 'multipart':
                continue
            # 跳过无附件标识的部分
            if part.get('Content-Disposition') is None:
                continue
            
            filename = part.get_filename()
            if not filename:
                continue
            
            # 保存附件到指定目录
            filepath = os.path.join(download_folder, filename)
            with open(filepath, 'wb') as f:
                f.write(part.get_payload(decode=True))
            print(f"附件 {filename} 已保存到 {filepath}")
    
    # 所有邮件处理完成后再执行expunge(仅当需要删除已标记为删除的邮件时保留,否则可删除)
    # server.expunge()
    server.close()
    server.logout()

关键修改点

  • 将server.expunge()移到循环结束后,避免中途打乱邮件ID序列;若无需删除邮件,可直接移除该语句。
  • 遍历fetch返回的data集合,仅处理元组类型元素,确保拿到正确的邮件字节内容。
  • 补充完整的附件下载逻辑(原代码仅跳过了多部分容器,未实现附件保存)。
  • 增加server.close()和server.logout(),规范关闭IMAP连接。

额外提示

  • 若Gmail账号开启了两步验证,需使用应用专用密码登录;未开启的话需允许"不太安全的应用访问"(或在Google账号设置中调整IMAP权限)。
  • 测试阶段建议用readonly=True打开收件箱,避免误修改邮件状态。

内容的提问来源于stack exchange,提问作者hans

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 17:30:44