【Django】メール送信による通知機能を実装する|簡単な掲示板アプリの作成

Djangoで掲示板に新しいコメントが投稿された際に、メールで通知する機能の実装方法を解説します。HTMLテンプレートを使って投稿内容を含んだ動的なメール本文を作成し、掲示板の作成者やお気に入り登録者といった複数の宛先にBCCで一斉送信する実践的な流れを学べます。

作成日: 更新日:

開発環境

  • OS: Windows10
  • Visual Studio Code: 1.73.0
  • Python: 3.10.11
  • Django: 5.0.3

サンプルコード

/app/views.py

/app/views.py
1 from django.http import JsonResponse
2 from django.db.models import Count
3 from django.db import models
4-from django.core.mail import send_mail
5+from django.core.mail import send_mail, EmailMessage
6 from django.conf import settings
7+from django.template.loader import render_to_string
8 
9 def user_owns_board(view_func):
10     @wraps(view_func)
11         if comment_form.is_valid():
12             comment_form.instance.user = request.user
13             comment_form.instance.board_id = pk
14-            comment_form.save()
15+            comment = comment_form.save()
16+
17+        # 掲示板所有者とお気に入りに登録しているユーザーにメール通知
18+        favorite_users = Board.objects.get(pk=pk).favorited_by.values_list('email', flat=True)
19+        recipient_list = [Board.objects.get(pk=pk).user.email] + list(favorite_users)
20+        subject = '新しいコメントが投稿されました。'
21+        message = render_to_string('mail/comment_notification_email.html', {
22+            'title': Board.objects.get(pk=pk).title,
23+            'url': 'http://127.0.0.1:8000/'+ str(pk) + '/',
24+            'user': request.user.username,
25+            'comment': comment.content,
26+        })
27+        email = EmailMessage(subject, message, settings.EMAIL_HOST_USER, [], bcc=recipient_list)
28+        email.send()
29+
30     return redirect('show', pk=pk)
31 
32 @login_required
33

/templates/mail/comment_notification_email.html

/templates/mail/comment_notification_email.html
1+掲示板:{{ title }}
2+URL:{{ url }}
3+投稿者:{{ user }}
4+コメント:{{ comment }}
5

コード解説

変更点: HTMLメールやBCC送信に必要なモジュールのインポート

/app/views.py
1-from django.core.mail import send_mail
2+from django.core.mail import send_mail, EmailMessage
3 from django.conf import settings
4+from django.template.loader import render_to_string

メール送信機能を実装するために、Djangoが提供しているモジュールをインポートします。

EmailMessageは、単純なテキストメールだけでなく、宛先をTO, CC, BCCに分けたり、HTML形式のメールを送信したりするなど、より高度なメール送信機能を使うためのクラスです。今回は複数の宛先にBCCで一斉送信するためにEmailMessageをインポートしています。

render_to_stringは、HTMLテンプレートファイル(.html)を文字列に変換するための関数です。これを使うことで、Pythonのコード内で動的に生成したデータをHTMLテンプレートに埋め込み、それをメール本文として利用できます。

変更点: 保存したコメント情報を変数に格納

/app/views.py
1             comment_form.instance.user = request.user
2             comment_form.instance.board_id = pk
3-            comment_form.save()
4+            comment = comment_form.save()

comment_form.save()は、フォームから送信された新しいコメントの情報をデータベースに保存するメソッドです。このメソッドは、保存したレコード(この場合は新しいコメント)の情報をオブジェクトとして返します。

ここでは、その返り値をcommentという変数に格納しています。こうすることで、後続の処理で、保存されたばかりのコメント内容(comment.contentなど)をメール本文に含めるために利用できるようになります。

変更点: 掲示板作成者とお気に入り登録者のメールアドレスを取得

/app/views.py
1+        # 掲示板所有者とお気に入りに登録しているユーザーにメール通知
2+        favorite_users = Board.objects.get(pk=pk).favorited_by.values_list('email', flat=True)
3+        recipient_list = [Board.objects.get(pk=pk).user.email] + list(favorite_users)

新しく投稿されたコメントを通知するために、送信先のメールアドレスリストを作成しています。

まず、Board.objects.get(pk=pk)でコメントが投稿された掲示板の情報を取得します。 .favorited_by.values_list('email', flat=True)の部分では、その掲示板をお気に入りに登録している全ユーザーのオブジェクトを取得し、その中からメールアドレス(email)だけを抜き出してリスト形式で取得しています。

次に、[Board.objects.get(pk=pk).user.email]で掲示板の作成者のメールアドレスを取得し、+ list(favorite_users)で先ほど取得したお気に入り登録者のリストと結合しています。これにより、掲示板作成者とお気に入り登録者全員のメールアドレスが含まれたrecipient_listというリストが完成します。

変更点: HTMLテンプレートから動的なメール本文を作成

/app/views.py
1+        subject = '新しいコメントが投稿されました。'
2+        message = render_to_string('mail/comment_notification_email.html', {
3+            'title': Board.objects.get(pk=pk).title,
4+            'url': 'http://127.0.0.1:8000/'+ str(pk) + '/',
5+            'user': request.user.username,
6+            'comment': comment.content,
7+        })

メールの件名と本文を準備しています。

subjectには、メールの件名となる文字列を代入しています。

messageには、render_to_string関数を使って生成したメール本文を代入します。この関数は2つの引数を取ります。

  1. 第1引数: メール本文の雛形となるHTMLテンプレートファイル('mail/comment_notification_email.html')のパスを指定します。
  2. 第2引数: テンプレート内で使用するデータを辞書形式で渡します。ここで指定したキー('title'など)が、テンプレートファイル内の変数({{ title }}など)に対応します。これにより、掲示板のタイトルやコメント内容といった動的な情報をメール本文に埋め込むことができます。

変更点: BCCを利用したメールの一斉送信

/app/views.py
1+        email = EmailMessage(subject, message, settings.EMAIL_HOST_USER, [], bcc=recipient_list)
2+        email.send()

EmailMessageクラスを使ってメールオブジェクトを生成し、実際に送信する処理です。

EmailMessageの引数はそれぞれ以下の意味を持ちます。

  • subject: メールの件名
  • message: メールの本文
  • settings.EMAIL_HOST_USER: 送信元のメールアドレス(設定ファイルsettings.pyで定義)
  • []: TO(宛先)のリスト。今回はBCCで送信するため空にしています。
  • bcc=recipient_list: BCCのリスト。ここに、先ほど作成した送信先メールアドレスのリストrecipient_listを指定します。BCCで送信することで、受信者はお互いのメールアドレスを見ることができなくなり、プライバシーが保護されます。

最後にemail.send()メソッドを呼び出すことで、設定した内容でメールが一斉送信されます。

変更点: メール本文のテンプレートファイルを作成

/templates/mail/comment_notification_email.html
1+掲示板:{{ title }}
2+URL:{{ url }}
3+投稿者:{{ user }}
4+コメント:{{ comment }}

これは、メール本文の見た目を定義するHTMLテンプレートファイルです。

{{ title }}{{ comment }}のように{{ }}で囲まれた部分は「テンプレート変数」と呼ばれます。views.pyrender_to_string関数に渡された辞書のキーに対応しており、メールが生成される際に実際の値(掲示板のタイトルやコメント内容など)に置き換えられます。

このように、ロジック(views.py)と見た目(テンプレート)を分離することで、コードの可読性が高まり、管理がしやすくなります。

おわりに

今回はEmailMessageクラスを使い、複数の宛先へBCCで一斉送信する方法を解説しました。render_to_string関数でHTMLテンプレートを読み込めば、投稿内容のような動的な情報を含んだメール本文も簡単に作成できます。送信先リストを動的に生成し、プライバシーに配慮して通知するこの一連の流れは、様々なアプリケーションで応用できる実践的なテクニックです。

関連コンテンツ