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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:23:20