Django批量发送邮件时如何在每封邮件模板中获取单个收件人地址
问题解答
该需求完全可以实现,你当前的写法本身就不适合个性化批量发信场景:把所有收件人塞到同一个EmailMessage的recipient_list属于单封邮件群发模式,所有收件人会收到完全相同的内容,还会暴露同批次其他收件人的邮箱地址,根本无法给不同收件人传递独立的模板变量。
正确实现方式如下:
- 核心逻辑是为每个收件人生成独立的
EmailMessage实例,每个实例的收件人列表仅传入当前单个收件人,单独渲染对应模板传入专属变量即可。 - 如果担心循环发送重复建立SMTP连接带来性能开销,可以手动复用连接提升效率。
基础实现代码
from django.core.mail import EmailMessage from django.template.loader import render_to_string from django.utils import timezone # 配置项 sender_email = 'sender@email.com' recipient_list = ['first@recipient.com', 'second@recipient.com'] for recipient in recipient_list: # 渲染当前收件人专属的邮件模板,传入独立的收件人变量 html_content = render_to_string('template.html', { 'datetime_sent': timezone.now(), 'recipient_address': recipient }) # 生成单收件人的邮件实例 mail = EmailMessage( subject='Subject', body=html_content, from_email=sender_email, to=[recipient] # 收件人列表仅放当前单个地址 ) # 若模板为HTML格式需指定该参数,纯文本可省略 mail.content_subtype = 'html' mail.send()
优化版(复用SMTP连接提升性能)
循环单封发送默认每次发信都会新建、断开SMTP连接,批量发送时可以手动维护连接复用,减少开销:
from django.core import mail from django.core.mail import EmailMessage from django.template.loader import render_to_string from django.utils import timezone sender_email = 'sender@email.com' recipient_list = ['first@recipient.com', 'second@recipient.com'] # 全局建立一次SMTP连接,所有邮件复用 with mail.get_connection() as smtp_conn: for recipient in recipient_list: html_content = render_to_string('template.html', { 'datetime_sent': timezone.now(), 'recipient_address': recipient }) mail = EmailMessage( subject='Subject', body=html_content, from_email=sender_email, to=[recipient], connection=smtp_conn # 绑定复用的连接 ) mail.content_subtype = 'html' mail.send()
注意事项
- 不要使用
send_mass_mail方法实现该需求,该方法是为无差异化的同内容批量发信设计的,不支持给不同邮件传入独立的模板上下文。 - 单实例单收件人的写法除了满足自定义模板变量的需求,还能避免群发泄露收件人地址的问题,后续扩展个性化内容(比如用户专属称呼、专属操作链接)也更灵活。
- 如果单批次发信量超过千封级别,建议搭配Celery这类异步任务队列发送,不要在Web请求的同步流程中执行,避免阻塞请求。
内容的提问来源于stack exchange,提问作者StackCode400
相关产品推荐
相关产品推荐

