【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.py1 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.html1+掲示板:{{ title }} 2+URL:{{ url }} 3+投稿者:{{ user }} 4+コメント:{{ comment }} 5
コード解説
変更点: HTMLメールやBCC送信に必要なモジュールのインポート
/app/views.py1-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.py1 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.py1+ # 掲示板所有者とお気に入りに登録しているユーザーにメール通知 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.py1+ 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引数: メール本文の雛形となるHTMLテンプレートファイル(
'mail/comment_notification_email.html')のパスを指定します。 - 第2引数: テンプレート内で使用するデータを辞書形式で渡します。ここで指定したキー(
'title'など)が、テンプレートファイル内の変数({{ title }}など)に対応します。これにより、掲示板のタイトルやコメント内容といった動的な情報をメール本文に埋め込むことができます。
変更点: BCCを利用したメールの一斉送信
/app/views.py1+ 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.html1+掲示板:{{ title }} 2+URL:{{ url }} 3+投稿者:{{ user }} 4+コメント:{{ comment }}
これは、メール本文の見た目を定義するHTMLテンプレートファイルです。
{{ title }}や{{ comment }}のように{{ }}で囲まれた部分は「テンプレート変数」と呼ばれます。views.pyのrender_to_string関数に渡された辞書のキーに対応しており、メールが生成される際に実際の値(掲示板のタイトルやコメント内容など)に置き換えられます。
このように、ロジック(views.py)と見た目(テンプレート)を分離することで、コードの可読性が高まり、管理がしやすくなります。
おわりに
今回はEmailMessageクラスを使い、複数の宛先へBCCで一斉送信する方法を解説しました。render_to_string関数でHTMLテンプレートを読み込めば、投稿内容のような動的な情報を含んだメール本文も簡単に作成できます。送信先リストを動的に生成し、プライバシーに配慮して通知するこの一連の流れは、様々なアプリケーションで応用できる実践的なテクニックです。