DjangoBrothers BLOG ✍️

2021/06/25

このエントリーをはてなブックマークに追加
Django メール

Django HTML・txt テンプレートでメール送信

メール送信時にHTMLファイルtxtファイルをテンプレートとして使う方法です。

バージョン

  • Django 3.2.4

シンプルな例

まずはメールを送るための最もシンプルな実装方法から。send_mail関数のパラメータに文字列型を直接指定します。

メール送信

from django.core.mail import send_mail

send_mail(
  subject="件名です。",
  message="本文です。",
  from_email="[email protected]",
  recipient_list=["[email protected]"],
)

HTMLテキストで送る

HTMLで作ったテキストを送りたい場合はhtml_messageパラメータを指定するだけです。

HTMLテキストを送信

from django.core.mail import send_mail

send_mail(
  subject="件名です。",
  message="お知らせ\nかくかくしかじか",
  from_email="[email protected]",
  recipient_list=["[email protected]"],
  # 追加
  html_message="<h1>お知らせ</h1><p>かくかくしかじか</p>",
)

以下のようなメールが送られます。

こちらの記事で説明されているように、「HTMLパートを送る際はテキストパートも一緒に送るのが一般的」であるため、messageパラメータも指定します。

html_messageパラメータが指定された場合、送信されるメールのContent-Typeはmultipart/alternativeとなります。

text/plainにはmessageパラメータの値が、text/htmlにはhtml_messageパラメータの値が使われます。メールを受信したメーラーの設定に応じて、どちらで表示されるかが決まります。

テキストファイルを使う

文章が長くなる場合などは文字列を直接指定するのではなく、txt形式のファイルを活用できます。

templatesディレクトリ内にtxtファイルを作成し、それを読み込みます。

~/アプリ/templates/mailers/notification_mail.txt

お知らせです。

会員登録が完了しました。

お問い合わせ: [email protected]

render_to_string関数でこのtxtファイルを読み込むことができます。

txtファイルを使ってメール送信

from django.core.mail import send_mail
from django.template.loader import render_to_string

send_mail(
  subject="件名です。",
  message=render_to_string("mailers/notification_mail.txt"),
  from_email="[email protected]",
  recipient_list=["[email protected]"],
)

render_to_string関数はファイルの中身を読み取って、文字列型を返します。

render_to_string関数

>>> from django.template.loader import render_to_string
>>> render_to_string("mailers/notification_mail.txt")
'お知らせです。\n\n会員登録が完了しました。\n\nお問い合わせ: [email protected]'

変数を埋め込む

render_to_string関数の第二引数には、contextを指定できるので変数を埋め込む場合はこれを使います。

~/アプリ/templates/mailers/notification_mail.txt

{{ user.last_name }} {{ user.first_name }}様

お知らせです。

会員登録が完了しました。{{ date }}までにログインしてください。

お問い合わせ: [email protected]

contextを指定してメール送信

context = {
  "user": {
    "last_name": "山田",
    "first_name": "太郎",
  },
  "date": "2021/6/25",
}

send_mail(
  subject="件名です。",
  # contextを追加
  message=render_to_string("mailers/notification_mail.txt", context),
  from_email="[email protected]",
  recipient_list=["[email protected]"],
)

HTMLファイルを使う

render_to_string関数はHTMLファイルでも同様に使えます。

~/アプリ/templates/mailers/notification_mail.html

<p>{{ user.last_name }} {{ user.first_name }}様</p>

<p style="color: #F00;">重要なお知らせです。</p>

<p>会員登録が完了しました。{{ date }}までにログインしてください。</p>

<p><small>お問い合わせ: [email protected]</small></p>

前述したように、messageとhtml_messageパラメータを指定します。

HTMLテキストで送信

from django.utils.html import strip_tags

# HTMLファイルを読み込む
html_content = render_to_string("mailers/notification_mail.html", context)
# HTMLタグを取り除く
text_content = strip_tags(html_content)

send_mail(
  subject="件名です。",
  message=text_content,
  from_email="[email protected]",
  recipient_list=["[email protected]"],
  html_message=html_content,
)

strip_tags関数は、HTMLタグを取り除いてくれます。これにより、プレーンテキストも取得できます。

開発環境下では、送信されたメールがコンソールに出力されるようになっていると思いますが、以下のような出力となります。multipartでプレーンテキスト、HTMLテキスト両方が送られていることがわかります。

コンソール出力

Content-Type: multipart/alternative;
 boundary="===============6767683329911943638=="
MIME-Version: 1.0
Subject: =?utf-8?b?5Lu25ZCN44Gn44GZ44CC?=
From: [email protected]
To: [email protected]
Date: Fri, 25 Jun 2021 08:25:16 -0000
Message-ID: 
 <[email protected].0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa>

--===============6767683329911943638==
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit

山田 太郎様

重要なお知らせです。

会員登録が完了しました。2021/6/25までにログインしてください。

お問い合わせ: [email protected]
--===============6767683329911943638==
Content-Type: text/html; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit

<p>山田 太郎様</p>

<p style="color: #F00;">重要なお知らせです。</p>

<p>会員登録が完了しました。2021/6/25までにログインしてください。</p>

<p><small>お問い合わせ: [email protected]</small></p>
--===============6767683329911943638==--

-------------------------------------------------------------------------------

説明は省きますが、EmailMultiAlternativesクラスを使うことでも、同様のことが実現できます。