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

Django循环发送邮件仅首封附件有内容,其余为空如何解决?

解决Django多附件邮件仅第一个收件人收到有效附件的问题

问题原因

核心问题出在文件对象的指针位置:第一次调用f.read()读取附件内容后,文件指针会移动到文件末尾,后续再次调用f.read()时会直接返回空字节,导致后续收件人的附件内容为空。

修复方案

方案1:每次读取前重置文件指针到开头

在每次循环发送邮件前,将文件指针重置到起始位置(seek(0)),确保每次读取都能获取完整的文件内容。

修改views.py中的循环部分:

def newsletter(request):
    users = User.objects.all()
    receipient_list = []
    for user in users:
        if user.profile.newsletter_agree and user.profile.verified_member:
            receipient_list.append(user.email)

    if request.method == 'POST':
        form = NewsletterForm(request.POST, request.FILES)
        if form.is_valid():
            mail_subject = 'Some newsletter subject'
            # 移除末尾逗号,避免message变成元组
            message = form.cleaned_data['message']
            files = request.FILES.getlist('attach')

            for contact_name in receipient_list:
                try:
                    email = EmailMessage(mail_subject, message, 'email@email.com', to=[contact_name])
                    email.encoding = 'utf-8'
                    for f in files:
                        # 重置文件指针到开头
                        f.seek(0)
                        email.attach(f.name, f.read(), f.content_type)
                    email.send()
                except BadHeaderError:
                    return HttpResponse('Invalid header found.')

            messages.success(request, f'Newsletter sent successfully')
            return redirect('main_page')
    
    form = NewsletterForm()
        
    context = {'form':form}

    return render(request, 'my_app/newsletter.html', context)

方案2:提前将所有附件内容读入内存

如果附件体积不大,可以提前把所有文件的名称、内容、类型存储在内存列表中,后续循环直接使用内存数据,避免重复操作文件对象。

修改views.py:

def newsletter(request):
    users = User.objects.all()
    receipient_list = []
    for user in users:
        if user.profile.newsletter_agree and user.profile.verified_member:
            receipient_list.append(user.email)

    if request.method == 'POST':
        form = NewsletterForm(request.POST, request.FILES)
        if form.is_valid():
            mail_subject = 'Some newsletter subject'
            message = form.cleaned_data['message']
            # 提前读取所有附件内容到内存
            attachments = []
            for f in request.FILES.getlist('attach'):
                attachments.append({
                    'name': f.name,
                    'content': f.read(),
                    'content_type': f.content_type
                })

            for contact_name in receipient_list:
                try:
                    email = EmailMessage(mail_subject, message, 'email@email.com', to=[contact_name])
                    email.encoding = 'utf-8'
                    for att in attachments:
                        email.attach(att['name'], att['content'], att['content_type'])
                    email.send()
                except BadHeaderError:
                    return HttpResponse('Invalid header found.')

            messages.success(request, f'Newsletter sent successfully')
            return redirect('main_page')
    
    form = NewsletterForm()
        
    context = {'form':form}

    return render(request, 'my_app/newsletter.html', context)

额外注意点

  • 原代码中message = form.cleaned_data['message'],末尾多了一个逗号,会导致message变成元组类型,可能引发邮件内容显示异常,修复代码中已移除。
  • 大附件建议用方案1,避免占用过多内存;小附件用方案2更高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 17:10:25