これはなに
- Djangoでメールを一括送信する際に詰まったので自分用にメモを残しておきます
- 環境
- Python 3.6.2
- Django==2.1.3
- django-mail-templated==2.6.5
- djangorestframework==3.8.2
 
詰まったところ
- mail_templatedから宛先や文面の違うメールを生成して一括送信したかったので下のようなコードを書いたが、送信されたメールの件名や本文がすべて空になってしまっていた
- 同じ件名・本文のメールを複数件送る場合はto=["user1@example.com", "user2@example.com"...]と書けばよいです
sample.py
from django.core.mail import get_connection
from mail_templated import EmailMessage
from app.models.user import User
class Sample():
    def sample_function(self):
        users = User.objects.exclude(email__isnull=True).annotate(
            fullname=Concat('user__last_name', 'user__first_name', output_field=CharField())).values(
                'email', 'fullname')
        user_list = list(users)
        connection = get_connection()
        connection.open()
        email_list = [EmailMessage(
            'email/example.tpl', {'fullname': user['fullname']},
            'from@example.com',
            to=[user['email']]
            ) for user in user_list]
        connection.send_messages(email_list)
        connection.close()
- ちなみにUserモデルとメールのテンプレートは以下のような感じです
app/models.py
from django.db import model
class User(models.Model):
    class Meta:
        app_label = 'test'
        db_table = 'users'
    email = models.EmailField(blank=False, null=True, default='')
    first_name = models.CharField(max_length=32, blank=False, default='')
    last_name = models.CharField(max_length=32, blank=False, default='')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
app/templates/email/example.tpl
{% extends "mail_templated/base.tpl" %}
{% block subject %}
【例】サンプルメール
{% endblock %}
{% block body %}
{{ full_name }}様
…
…
…
{% endblock %}
{% block html %}
{% endblock %}
どうやったか
sample.py
from django.core.mail import get_connection
from mail_templated import EmailMessage
from app.models.user import User
class Sample():
    def sample_function(self):
        users = User.objects.exclude(email__isnull=True).annotate(
            fullname=Concat('user__last_name', 'user__first_name', output_field=CharField())).values(
                'email', 'fullname')
        user_list = list(users)
        email_list = []
        connection = get_connection()
        connection.open()
        for user in user_list:
            email = EmailMessage(
                'email/example.tpl', {'fullname': user['fullname']},
                'from@example.com',
                to=[user['email']]
                )
            email.render()
            email_list.append(email)
        connection.send_messages(email_list)
        connection.close()
参考にしたもの
- Sending email | Django documentation | Django(公式のドキュメント)
- artemrizhov/django-mail-templated: Send emails using Django template system(使っているライブラリ)
その他
- もっといいやり方/ライブラリがある、そもそもこのやり方ではパフォーマンス上意味がない等ございましたらご指摘ください