1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Djangoで件名や本文の違うメールを一括送信する

Last updated at Posted at 2019-03-05

これはなに

  • 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 %}

どうやったか

  • ソースを読んだらわかった
    • このへんを読んだら送る前にrender()を呼び出す必要があるのがわかったので、以下のようにコードを修正したところ動いた
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()

参考にしたもの

その他

  • もっといいやり方/ライブラリがある、そもそもこのやり方ではパフォーマンス上意味がない等ございましたらご指摘ください
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?