Flask上传文件直接作为邮件附件发送(无需暂存)问题求助
解决Flask上传文件直接作为邮件附件发送(无服务器暂存)的0KB问题
问题核心:你当前代码中,Flask的FileStorage对象在读取时可能因流指针位置不正确,导致file.read()返回空内容,最终生成0KB附件。以下是修正方案:
修正后的代码
import os import smtplib import ssl from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.base import MIMEBase from email import encoders from flask import request def upload_and_send_email(): files = request.files.getlist("file") # 定义邮件发送方、接收方 email_sender = os.environ['EMAILSENDER'] # 注意:修正环境变量拼写(原代码为EMAILPASWOORD) email_password = os.environ['EMAILPASSWORD'] email_receiver = Emailreceiver # 假设Emailreceiver为已定义变量 # 设置邮件主题和正文 subject = 'Mail test' body = """ Check if it works """ em = MIMEMultipart() em['From'] = email_sender em['To'] = email_receiver em['Subject'] = subject # 明确指定正文为纯文本类型 em.attach(MIMEText(body, 'plain')) for file in files: # 跳过未选择文件的情况 if not file or file.filename == '': continue part = MIMEBase('application', "octet-stream") # 关键:重置文件流指针到起始位置,确保读取完整内容 file.seek(0) part.set_payload(file.read()) encoders.encode_base64(part) # 用引号包裹文件名,避免特殊字符解析问题 part.add_header( 'Content-Disposition', f'attachment; filename="{file.filename}"' ) em.attach(part) # 建立SSL连接并发送邮件 context = ssl.create_default_context() with smtplib.SMTP_SSL('smtp.gmail.com', 465, context=context) as smtp: smtp.login(email_sender, email_password) smtp.sendmail(email_sender, email_receiver, em.as_string())
关键修正点
- 重置文件流指针:调用
file.read()前执行file.seek(0),确保从文件起始位置读取内容。部分场景下(如框架内部读取过文件头信息),流指针会停在文件末尾,导致后续读取返回空。 - 过滤空文件:添加判断跳过未选择文件的情况,避免生成无效附件。
- 文件名引号包裹:在
Content-Disposition头中用双引号包裹文件名,避免文件名含空格或特殊字符时出现解析错误。 - 修正环境变量拼写:原代码中
EMAILPASWOORD为拼写错误,改为EMAILPASSWORD(若你的环境变量确实用错误拼写则忽略此点)。
原理说明
Flask的request.files返回的FileStorage是文件流对象,当流指针不在起始位置时,read()会返回空字节串。通过seek(0)重置指针到开头,即可完整读取上传文件内容,无需暂存到服务器磁盘,直接作为附件发送。
内容的提问来源于stack exchange,提问作者Skay
相关产品推荐
相关产品推荐

