Django中使用EmailMessage发送带附件邮件的问题求助
解决Django EmailMessage添加上传文件附件失败的问题
你遇到的问题根源很明确:EmailMessage.attach_file()方法需要传入本地文件系统的路径字符串,但你传给它的是Django从request.FILES获取的InMemoryUploadedFile或TemporaryUploadedFile对象——这俩类型不匹配,所以导致带附件的邮件发送失败。
下面给你两种解决方案,优先推荐第一种,更简洁高效:
方案一:使用attach()方法直接处理上传文件
EmailMessage.attach()方法支持直接传入文件对象的相关信息,不需要本地文件路径,完美适配request.FILES里的上传文件。
修改你的邮件发送代码:
if request.method == 'POST': email = EmailMessage() email.subject = "Test" email.body = mainMessage email.from_email = "SMTP <XXX@XXX.net>" email.to = [ "XXX@XXX.net" ] # 获取上传文件(优化判断逻辑,不存在时返回None) file = request.FILES.get('file') if file: # 用attach方法添加附件:参数依次是文件名、文件二进制内容、MIME类型 email.attach(file.name, file.read(), file.content_type) email.send()
为什么这个方法可行?
file.name:获取用户上传文件的原始文件名file.read():读取上传文件的二进制内容(Django的上传文件对象支持直接读取)file.content_type:获取文件的MIME类型(比如image/png、application/pdf等),确保邮件客户端能正确识别附件类型
方案二:先保存上传文件到本地再使用attach_file()(不推荐)
如果因为特殊需求一定要用attach_file(),你需要先把上传的文件临时保存到服务器本地,再传入文件路径。这种方法需要额外处理文件保存和清理,不如方案一高效:
import os from django.conf import settings if request.method == 'POST': email = EmailMessage() # ... 其他邮件设置代码 ... file = request.FILES.get('file') if file: # 定义临时保存路径(比如用Django的MEDIA目录) temp_file_path = os.path.join(settings.MEDIA_ROOT, file.name) # 分块写入文件(大文件推荐用chunks()避免内存溢出) with open(temp_file_path, 'wb+') as destination: for chunk in file.chunks(): destination.write(chunk) # 添加附件 email.attach_file(temp_file_path) # 发送后删除临时文件(可选,避免服务器空间占用) os.remove(temp_file_path) email.send()
额外检查项
你已经做对的点:
- 表单设置了
enctype="multipart/form-data":这是上传文件必须的,确保表单能正确传递文件数据 - 视图里判断了
request.FILES的存在:逻辑没问题,用get()方法可以让代码更简洁(避免else设为False)
内容的提问来源于stack exchange,提问作者Keimeno
相关产品推荐
相关产品推荐

