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

Python用BytesIO+MIMEApplication从S3发图片邮件附件为0字节问题

问题描述

我使用如下代码从S3存储桶下载文件,通过BytesIO将读取的数据存入内存而非本地文件:

with io.BytesIO() as img:
    img.name = 'screenshot.png'
    try:
        get_bucket().download_fileobj(key, img)
    except Exception as e:
        logger.error('ERROR processing screenshot, exception: %s',
                     str(e))
        raise NotFoundError()

随后通过以下代码发送邮件:

part = MIMEApplication(attachment.read())
part.add_header('Content-Disposition', 'attachment',
                filename=os.path.basename(attachment.name))
msg.attach(part)

_ses.send_raw_email(Source=sender, Destinations=recipients,
                    RawMessage={'Data': msg.as_string()})

其中attachment为上述img(BytesIO)对象。但收到邮件时,附件字节数为0或无法正常显示。应用使用的是旧版本boto3 1.13.13,当前仅进行维护工作。请问该问题的可能原因是什么?

可能的原因
  • BytesIO指针位置未重置:调用download_fileobj写入数据后,BytesIO的文件指针会停留在数据末尾,此时直接调用read()会读取到空内容。需要在读取前执行attachment.seek(0)将指针移到起始位置。
  • 旧版boto3的潜在bug:boto3 1.13.13是2020年的旧版本,download_fileobj在处理BytesIO时可能存在兼容性问题,比如未能完整写入数据,或者写入后指针状态异常。可以在写入后通过img.tell()检查是否有数据写入(返回值为0则说明未写入任何内容),同时确认S3桶中的目标文件本身不为空。
  • MIME类型处理不当:如果附件是PNG图片,直接使用MIMEApplication通用类型可能不如指定具体MIME类型可靠,旧版email库可能对通用类型的解析存在问题。可以替换为MIMEImage(attachment.read()),或者在MIMEApplication中指定_subtype='png'参数。
  • 上下文管理器作用域问题:img是在with语句块内创建的,当代码退出with块时,BytesIO对象会被自动关闭。如果后续在with块外使用attachment(即已关闭的对象)读取内容,会导致读取失败,附件为空。需要确保邮件附件的处理逻辑在with块内完成,或者将BytesIO中的数据复制到另一个持久化的BytesIO对象中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 09:50:31