【Django】お問い合わせフォーム機能を作成してメールを送信する方法について

概要

お問い合わせフォーム機能を作成してメールを送信する方法についてまとめた。
尚、Gmailを使用してメールを送信している。

 

前提

Googleアカウントのアプリパスワードを生成していること。
※アプリパスワードがないとGmailで送信できない

 

お問い合わせ機能

お問い合わせ機能について、全体の概要と実装方法を紹介する。

画面遷移

お問い合わせ機能は以下のように画面遷移する。
※ブログサイトにお問い合わせ機能を導入する例

▲お問い合わせ画面表示

 

▲お問い合わせ情報入力

 

▲お問い合わせ完了

 

▲お問い合わせメール受信

 

▲入力エラーの場合

 

実装全体像

お問い合わせビューの処理の流れは以下になる。
※FormViewを継承して作成

 

▲お問い合わせ画面表示と送信処理の概要

 

全体の流れ

GETまたはPOSTリクエストを受け取ると、dispatch()メソッドによってget()またはpost()メソッドが呼ばれる。

GETリクエスト

お問い合わせ画面表示処理。

空のお問い合わせフォームインスタンスを作成して画面に渡す。

 

POSTリクエスト

お問い合わせ送信処理。

画面からお問い合わせ情報の入力値を取得して入力チェックする。
入力チェックエラーが有る場合、エラー情報を保持したフォームインスタンスを画面に渡す。
入力チェックエラーが無い場合、メール送信処理を行ってリダイレクトする。

お問い合わせ機能まわりの実装

サーバー側と画面側について、実装内容を説明する。

サーバー側

サーバー側はビュー、フォーム、設定ファイルを実装する。

ビュー

お問い合わせビュー処理


from django.views.generic import FormView	
from django.urls import reverse_lazy	
from . import forms	
from django.contrib import messages	
from django.core.mail import EmailMessage	
	
	
class ContactView(FormView):	
    """お問い合わせ"""	
	
    # テンプレート	
    template_name = "contact.html"	
    # フォーム	
    form_class = forms.ContactForm	
    # お問い合わせ送信成功後URL	
    success_url = reverse_lazy("blogapps:contact")	
	
    def form_valid(self, form):	
        """お問い合わせ送信処理"""	
	
        # パラメータ取得	
        name = form.cleaned_data["name"]	
        email = form.cleaned_data["email"]	
        title = form.cleaned_data["title"]	
        message_param = form.cleaned_data["message"]	
	
        # お問い合わせメールの送信処理(例として、自分自身にメールを送る設定)	
        subject = f"お問い合わせ: {title}"	
        message = f"名前: {name}\nメールアドレス: {email}\n\n{message_param}"	
        from_email = "XXXXXX@example.com"  # 送信元のメールアドレス	
        recipient_list = ["XXXXX@gmail.com"]  # 受信者のメールアドレスリスト	
	
        msg = EmailMessage(	
            subject=subject, body=message, from_email=from_email, to=recipient_list	
        )	
	
        try:	
            msg.send()	
            messages.success(self.request, "送信完了しました。")	
        except Exception as e:	
            messages.error(self.request, f"送信に失敗しました。エラー:{e}")	
	
        return super().form_valid(form)	

GETリクエストによるお問い合わせ画面表示処理の場合、ContactFormインスタンスを生成して”contact.html”と組み合わせてレスポンスを返却する。

POSTリクエストによるお問い合わせ送信処理の場合、ContactFormインスタンスから画面入力値を取得してメール送信する。

 

name = form.cleaned_data["name"]
email = form.cleaned_data["email"]
title = form.cleaned_data["title"]
message_param = form.cleaned_data["message"]

バリデーション後のフォーム内画面入力値は、上記の記述で取得できる。

 

django.core.mail.EmailMessage

メール送信処理には、Djangoにもともと用意されているEmailMessageクラスを使用する。
インスタンスを作成する際に、以下のオプションを設定できる。

オプション 内容
subject メールの件名
body メールの本文
from_email メールの送信元アドレス
to メールの送信先アドレス。リストまたはタプルで指定可能
bcc bcc機能。リストまたはタプルで指定可能
cc cc機能。リストまたはタプルで指定可能
attachments 添付する添付ファイルのリスト
headers メッセージに追加する追加ヘッダー。キーはヘッダー名、値はヘッダー値
reply_to メール送信時にReply-Toヘッダーで使用される受信者アドレスのリストまたはタプル

インスタンスを作成する際にオプションをつけることで、メッセージ内容や送信先メールアドレス等を保持したオブジェクトを作成できる。

 

msg.send()

EmailMessageインスタンスのsend()メソッドを呼び出すことでメール送信ができる。

 

フォーム

お問い合わせフォーム


from django import forms	
	
	
class ContactForm(forms.Form):	
    """お問い合わせフォーム"""	
	
    # フィールド	
    name = forms.CharField()	
    email = forms.EmailField()	
    title = forms.CharField()	
    message = forms.CharField()	

画面に表示させるフォーム部品を設定する。

 

設定ファイル

settings.py


EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

上記を設定することで、ターミナル上にメール送信内容を表示することができる。
テスト送信になるため、実際にメール送信はされない。

実際にメール送信する際には以下の設定を行う必要がある。

settings.py


EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = "smtp.gmail.com" # GmailのSMTPサーバー
EMAIL_PORT = 587 # Gmailサーバーのポート
EMAIL_HOST_USER = "XXXXX@gmail.com" # 自身のGmailアドレス(メール送信用SMTPサーバーの認証)
EMAIL_HOST_PASSWORD = "XXXXXX" # アプリパスワード
EMAIL_USE_TLS = True # SMTPサーバーと通信する際に、TLS(セキュア)接続する

上記を設定することで、実際にメール送信ができる。
自身のGmailと作成したアプリパスワード(セキュリティページから作成可能)を設定することで、Gmail経由でメール送信することができるようになる。

 

画面側

お問い合わせ画面は以下のように実装する。

お問い合わせ画面


<main class="mb-4">	
  <div class="container px-4 px-lg-5">	
    <div class="row gx-4 gx-lg-5 justify-content-center">	
      <div class="col-md-10 col-lg-8 col-xl-7">	
        <p>当ブログへのご意見、ご質問、ご相談等ありましたらお気軽に下記のフォームからお問い合わせください。<br/>また、コンテンツ等に問題がありましたらご報告ください。<br/><br/>必要事項を入力の上、【送信】ボタンをクリックしてください。</p>	
        <!-- メッセージ出力領域 -->	
        {% if messages %}	
        <ul class="list-unstyled">	
          {% for message in messages %}	
          <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>	
          {% endfor %}	
        </ul>	
        {% endif %}	
        <div class="my-5">	
          <!-- * * * * * * * * * * * * * * *-->	
          <!-- * * お問い合わせフォーム * *-->	
          <!-- * * * * * * * * * * * * * * *-->	
          <form method="post">	
            {% csrf_token %}	
            <div class="form-floating">	
              <input class="form-control" id="name" type="text" name="name" placeholder="お名前を入力してください"/>	
              <label for="name">お名前</label>	
              {% if form.name.errors %}	
              <div class="text-danger">{{ form.name.errors.as_text }}</div>	
              {% endif %}	
            </div>	
            <div class="form-floating">	
              <input class="form-control" id="email" type="email" name="email" placeholder="メールアドレスを入力してください" />	
              <label for="email">メールアドレス</label>	
              {% if form.email.errors %}	
              <div class="text-danger">{{ form.email.errors.as_text }}</div>	
              {% endif %}	
            </div>	
            <div class="form-floating">	
              <input class="form-control" id="title" type="text" name="title" placeholder="件名を入力してください"/>	
              <label for="title">件名</label>	
              {% if form.title.errors %}	
              <div class="text-danger">{{ form.title.errors.as_text }}</div>	
              {% endif %}	
            </div>	
            <div class="form-floating">	
              <textarea class="form-control" id="message" name="message" placeholder="メッセージを入力してください"></textarea>	
              <label for="message">メッセージ</label>	
              {% if form.message.errors %}	
              <div class="text-danger">{{ form.message.errors.as_text }}</div>	
              {% endif %}	
            </div>	
            <br />	
            <!-- 送信ボタン-->	
            <button class="btn btn-primary" id="" type="submit">送信</button>	
          </form>	
        </div>	
      </div>	
    </div>	
  </div>	
</main>	

お問い合わせフォームのname、email、title、messageに合わせて画面を作成する。

 

メール送信に失敗したとき

VSCodeを使用していると、たまに以下のようなエラーが発生する。

送信に失敗しました。エラー:[Errno -3] Temporary failure in name resolution

 

対応

DNSサーバーをGoogleのDNSサーバーに変更することで解決した。

ターミナル


sudo vi /etc/resolv.conf

resolv.conf


nameserver 8.8.8.8
スポンサーリンク