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

如何使用Python2.7读取Gmail邮件正文并下载附件?

搞定邮件附件下载:从问题排查到代码修复

我太懂这种感觉了——能顺利读出邮件正文,偏偏卡在附件下载这一步,还碰到消息类型的小坑,确实让人头疼。咱们一步步来拆解,先把附件下载的核心逻辑捋顺,再解决消息类型的疑问。

一、先把附件下载的核心逻辑补全

邮件的结构其实是MIME多部分(Multipart)嵌套的,附件一般藏在子部分里,关键是要准确识别出哪些部分是附件。这里给你一个基于Python imaplib和email库的修复示例,你可以对照自己的代码调整:

import imaplib
import email
from email.policy import default
from email.header import decode_header

# 连接IMAP邮箱(替换成你的邮箱服务器地址)
mail = imaplib.IMAP4_SSL('imap.yourmail.com')
mail.login('your_email@example.com', 'your_auth_code') # 注意:有些邮箱需要用授权码而非密码
mail.select('inbox')

# 搜索目标邮件(这里以所有邮件为例,你可以改成已读/未读等条件)
status, message_ids = mail.search(None, 'ALL')
for msg_id in message_ids[0].split():
    # 获取原始邮件内容
    status, raw_msg = mail.fetch(msg_id, '(RFC822)')
    msg = email.message_from_bytes(raw_msg[0][1], policy=default)

    # 遍历邮件的所有MIME部分
    for part in msg.walk():
        # 跳过正文部分(纯文本/HTML)
        if part.get_content_type() in ['text/plain', 'text/html']:
            continue
        
        # 判断是否为附件:检查Content-Disposition或是否有文件名
        content_dispo = part.get("Content-Disposition", "")
        filename = part.get_filename()
        if ("attachment" in content_dispo) or (filename is not None and filename != ""):
            # 解码文件名(处理中文/特殊字符编码)
            if filename:
                decoded_name = decode_header(filename)[0][0]
                if isinstance(decoded_name, bytes):
                    decoded_name = decoded_name.decode('utf-8')
                
                # 写入附件到本地
                with open(decoded_name, 'wb') as f:
                    f.write(part.get_payload(decode=True))
                print(f"✅ 成功下载附件: {decoded_name}")

关键要点解释:

  • msg.walk():能遍历所有嵌套的MIME部分,不管邮件是单层还是多层嵌套结构,都不会漏掉附件
  • 附件判断逻辑:同时检查Content-Disposition(是否包含attachment)和文件名,避免漏掉那些没明确标记但有文件名的附件
  • 文件名解码:用decode_header()处理中文或特殊字符的文件名,避免出现乱码

二、聊聊邮件消息类型的坑

你提到无附件邮件的消息类型有疑问,这里给你梳理常见类型:

  • 纯文本无附件:text/plain(单部分结构,非Multipart)
  • HTML正文无附件:要么是text/html单部分,要么是multipart/alternative(同时包含纯文本和HTML两个子部分)
  • 带附件的邮件:基本都是multipart/mixed,正文和附件作为独立子部分存在
  • 带嵌入资源(比如签名图片)的邮件:会用multipart/related,这类资源可以通过Content-ID区分——如果part.get('Content-ID')不为空,大概率是嵌入资源,不是需要下载的附件,可以跳过

如果你不确定当前处理的邮件类型,建议在代码里加一行打印:

print(f"当前邮件类型: {msg.get_content_type()}")

这样就能针对性调整处理逻辑。

三、容易踩的小坑提醒

  • 授权码问题:现在很多邮箱(比如QQ、网易)禁用了直接用密码登录IMAP,需要在邮箱设置里开启IMAP服务并生成授权码
  • 超大附件:如果遇到几百MB的大附件,直接get_payload(decode=True)会占用大量内存,可以改成分块写入
  • 服务器限制:部分IMAP服务器会限制单次获取的邮件大小,这时候可以用BODY.PEEK[]分部分获取附件内容

如果你的代码还有具体的报错或者逻辑问题,把代码贴出来咱们可以精准定位!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:08:23