【Django】お問い合わせフォームを作成しGmail(メール)を設定し送信する

投稿日 2019年10月14日 >> 更新日 2023年3月2日

今回はお問い合わせフォームを作成したあと、Gmail(メール)を設定し一方的な送信を試して行きます。

※ここではGmail限定で試して行きます。

Djangoには「send_mail」というメソッドが備わっていて、この引数にお問い合わせフォームの内容と自分のアドレスを与えることで簡単に自分宛てでメールを受け取ることができます。

他にも色々なメソッドがあるので、詳しくはDjangoの公式ドキュメントで確認してください。

「send_mail」の仕組みはPython標準モジュールの「 smtplib」が使われており、SMTP(Simple Mail Transfer Protocol)サーバーを利用して簡易的にメール転送が可能とのことです。

注意点がありますが、お問い合わせフォームを作成するにあたってユーザーから個人情報を受け取る事を想定していると思います。ユーザーや自分の個人情報も含め確実に情報漏洩などを防ぎ安全に管理を行うようにしましょう。

GitHubでコードを投稿する際は、「.gitignore」ファイルなどで除外するような施しを完全に行いましょう。【WSL】Heroku・Git・Djangoを使い無料でWebに公開(パート2)

実行環境&使用ライブラリ

実行環境
Windows Subsystem for Linux
Python 3.6.8
pip 9.0.1
使用ライブラリ ライセンス
Django==2.2.6 BSD

お問い合わせフォームアプリの作成

まずはお問い合わせフォームアプリを作成していきます。

モデルやadmin管理画面までは構築しないので安心してください。

フォーム作成に関して詳しく知りたい方は、Djangoの公式ドキュメントをお確かめください。

アプリの作成

Djangoをインストールしたら、プロジェクトを作成します。


$ django-admin startproject project

cdコマンドで「project」ディレクトリに移動したら、アプリのディレクトリを作成します。アプリ名は「contact」です。

# project/

$ python3 manage.py startapp contact

projectディレクトリ内の「project」というもう一つのディレクトリ内にある設定ファイル「settings.py」にアプリ名を記述します。

# project/project/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'contact',    ←ここ
]

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

settings.pyと同じディレクトリにある「urls.py」に、アプリが紐づくように編集します。

# project/project/urls.py

from django.contrib import admin
from django.urls import path, include # 追加


urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('contact.urls')),    # 追加
]

次は「contact」ディレクトリ内の編集です。

新しく「urls.py」を作成し、URLパターンを記述します。

# project/contact/urls.py

from django.urls import path
from . import views


app_name = 'contact'

urlpatterns = [
        path('', views.index, name='index'),  # 一覧画面
        path('contact_form/', views.contact_form, name='contact_form'),  # フォーム
        path('contact_form/contact/complete/', views.complete, name='complete'),  # 完了画面
]

テンプレートと紐づけるためにcontacディレクトリ内の「views.py」を編集します。

# project/contact/views.py

from django.shortcuts import render


""" 一覧画面"""
def index(request):
    return render(request, 'contact/index.html')


""" お問い合わせフォーム画面"""
def contact_form(request):
    return render(request, 'contact/contact_form.html')


""" 送信完了画面"""
def complete(request):
    return render(request, 'contact/complete.html')

続いてテンプレートの作成です。

contactディレクトリ内に新しく「templates」というディレクトリ(フォルダ)を作成し、templatesディレクトリ内「contact」ディレクトリを作成し、contactディレクトリ内にHTMLファイルを作成していきます。

一覧画面

<!-- project/contact/templates/contact/index.html -->

<!doctype html>
<html>
    <head>

        <title>Webサイト</title>

    </head>
    <body>

        <center>
            <a href="{% url 'contact:contact_form' %}">
                <h2>お問い合わせフォーム</h2>
            </a>
        </center>

    </body>
</html>

お問い合わせフォーム

<!-- project/contact/templates/contact/contact_form.html -->

<center>
    <h1>入力フォーム</h1><hr>
    <br>
</center>

送信完了画面

<!-- project/contact/templates/contact/complete.html -->

<center>
    <h1>送信完了</h1>
    <a href="{% url 'contact:index' %}">
        <p>トップへ</p>
    </a>
</center>

Djangoを起動します。

# project/

$ python3 manage.py runserver
127.0.0.1:8000

表示するとこのようになります。

URLの「127.0.0.1:8000/contact_form/contact/complete」と打ち込むと、完了画面に飛びます。

フォームの作成

DjangoのFormクラスを使ってテンプレートを表示させるので、contactディレクトリ内に新しく「forms.py」を作成します。

# project/contact/forms.py

from django import forms


class ContactForm(forms.Form):
    subject = forms.CharField(label='件名', max_length=100)
    sender = forms.EmailField(label='Email', help_text='※ご確認の上、正しく入力してください。')
    message = forms.CharField(label='メッセージ', widget=forms.Textarea)
    myself = forms.BooleanField(label='同じ内容を受け取る', required=False)

「subject」は件名、「sender」はEメール入力で、「help_text」は後にテンプレートで表示される注意書きです。

「message」は書き込む内容、「widget=forms.Textarea」とすることで複数行書き込めるテキストボックスが渡されます。

「myself」はチェックボックス。「required=False」はDjango公式通り。

作成したContactFormを「views.py」の「contact_form」で処理し、テンプレートに表示できるようにします。

# project/contact/views.py

from django.shortcuts import render, redirect \# 追加
from .forms import ContactForm \# 追加


........
........


def contact_form(request):

    if request.method == 'POST':
        form = ContactForm(request.POST)

        if form.is_valid():
            return redirect('contact:complete')

    else:
        form = ContactForm()

    return render(request, 'contact/contact_form.html', {'form': form})

.........
.........

「POST」されたフォームの内容を「form.is_valid()」で検証し正しければ「complete.html」に渡されるという記述です。

次に表示するための記述をしていきます。

「contact_form.html」を編集します。

<!-- project/contact/templates/contact/contact_form.html -->

<center>
    <h1>入力フォーム</h1><hr>
    <br>

    <!-- 追加-->
    <form action="{% url 'contact:contact_form' %}" method="post">
        {% csrf_token %}
        <table>
            {{ form.as_table }}
        </table>
        <br>

        <input type="submit" value="送信">
    </form>
</center>

「{{ form.as_table }}」とすることでテーブル形式で表示されます。なのでスタイルを崩さないためにtableタグで挟みます。

他にもDjangoのテンプレートタグでは、pタグ形式の「{{ form.as_p }}」やulタグ形式の「{{ form.as_ul }}」などがあるのでお好きな形式にしてみましょう。

「{% csrf_token %}」はクロスサイトリクエストフォージェリ (CSRF) 対策というもので、悪用対策に使われます。詳しくはDjango公式ドキュメントへ。

それでは起動中であろうcontactアプリをリロードしてしっかり機能するか確かめてみましょう。

適当に入力して送信完了画面にリダイレクトされればひとまず成功です。

安心してください、誰にも送信されていませんよ!

Gmailでのアプリパスワードの設定

ここでひとまずGmailのアプリパスワードの取得をしていきたいと思います。

もし既に取得されている方は次へ進んでしまってください。

もしくわ、先にフォームを完成させたい人は後からでも大丈夫です。

Gmailのアプリパスワードというのは、外部アプリで利用するためのパスワードです。

なのでそのGmailアカウントは適切な設定をし、二段階認証をされていないと取得することができません。

ここでは簡単に説明しますが詳しくはGoogleアカウントヘルプへ。

説明が行き届かない可能性もあるので、自己責任の上でお願いします。

使用するアカウントを決めて二段階認証をする

まずGmailアプリを開き左上にあるメニューバーをタップします。

下の方にスクロールすると「設定」とあるのでタップします。

使用するアカウントを選択し「Googleアカウントの管理」をタップします。

すると下図のような画面になるので、「セキュリティ」の項目を選択し、「アカウントの保護」や適切な設定を行った上で二段階認証などの設定をしましょう。

※二段階認証設定後に、アプリパスワードの項目が現れます。

実際に受け取るパスワードはこのような画面からです。

取得したパスワードは、アプリにだけ使うのでGoogleが推奨しているように保管などの処置は取らなくてもいいとの事です。

ただしDjangoの設定ファイル「settings.py」に記述するのでテキストエディタにコピーしておきましょう。

メール送信機能を追加する

ここからはDjangoのメール送信機能を追加していきます。

前提としては、Gmailアドレス・アプリパスワードを取得していることです。

電子メール使わずに行いたい場合は、Django公式ドキュメントのメールを送信するをお確かめください。

まずは設定ファイルの「settings.py」にメールサーバーを使う為の記述をします。

GitHubでコードを投稿する際は、「.gitignore」ファイルなどで除外するような施しを完全に行いましょう。

# project/project/settings.py

STATIC_URL = '/static/'

# メールサーバー用
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'アドレス@gmail.com'
EMAIL_HOST_PASSWORD = '取得したアプリパスワード'
EMAIL_PORT = 587
EMAIL_USE_TLS = True

次に「views.py」にて、お問い合わせフォームに書かれたメッセージを処理し適切な応答をするように追記していきます。

# project/contact/views.py

from django.shortcuts import render, redirect
from .forms import ContactForm
""" 追加でインポート"""
from django.http import HttpResponse
from django.conf import settings
from django.core.mail import BadHeaderError, send_mail


.........
.........

def contact_form(request):

    if request.method == 'POST':
        form = ContactForm(request.POST)

        if form.is_valid():
            """ 追記"""
            subject = form.cleaned_data['subject']
            message = form.cleaned_data['message']
            sender = form.cleaned_data['sender']
            myself = form.cleaned_data['myself']
            recipients = [settings.EMAIL_HOST_USER]

            if myself:
                recipients.append(sender)
            try:
                send_mail(subject, message, sender, recipients)
            except BadHeaderError:
                return HttpResponse('無効なヘッダーが見つかりました。')
            return redirect('contact:complete')

    else:
        form = ContactForm()

    return render(request, 'contact/contact_form.html', {'form': form})

.........
.........

「form.is_valid()」で検証されたデータを整形して返すために「cleaned_data[]」を使って変数に格納します。

「recipents」は設定ファイルのsettings.pyで定義した自分のアドレスを渡しています。

「send_mail」では、4つの引数が必須とのことです。引数を見てわかる通り、自分のアドレス宛にsubject・message・senderを送ります。※sender(送信者のアドレス)は自分のメール受信箱に表示されないので後に変更します。

「BadHeaderError」は、ヘッダインジェクションを防ぐ為の記述です。詳しくは公式ドキュメントへ。

「if_myself」は、送信者がチェックボックスにチェックを入れたときに、送信者のアドレス(sender)がrecipientsに追加され双方にメールが送られます。

双方に送られたメールの送信者は設定した自分のアドレスからとなります。

さっそく送信してみましょう。

送信完了へリダイレクトされれば成功です。

おそらくメールが受信されています。

Emailアドレスの見える化&フォームのスタイルを変更

最後にメッセージを送った送信者のEmailアドレスの見える化とフォームスタイルを少しだけ変更して終わりたいと思います。

まず「views.py」の編集です。

# project/contact/views.py

def contact_form(request):

    if request.method == 'POST':
        form = ContactForm(request.POST)

        if form.is_valid():
            subject = form.cleaned_data['subject']
            message = form.cleaned_data['message']
            """ 変更箇所"""
            sender = []
            sender.append(form.cleaned_data['sender'])
            myself = form.cleaned_data['myself']
            recipients = [settings.EMAIL_HOST_USER]

            if myself:
                recipients.append(sender)
            try:
                send_mail(subject, message, sender, recipients)
            except BadHeaderError:
                return HttpResponse('無効なヘッダーが見つかりました。')
            return redirect('contact:complete')

    else:
        form = ContactForm()

    return render(request, 'contact/contact_form.html', {'form': form})

「sender」の空リストにEmailアドレスを与えて表示させます。ただしこの方法は明らかに切羽詰まったやりかたです。

このやり方ですと「スパム」扱いされてしまう可能性があるので、「自分のみ」に送信する場合に限定した方がよさそうです。

他に良い方法がある方は違うやり方を試してみてください。

次にお問い合わせフォームのスタイルを少しだけ変更します。

「contact_form.html」の上にstyleタグを設けて記述しますが、formタグ内も少し変更します。

<!-- project/contact/templates/contact/contact_form.html -->

<center>
    <h1>入力フォーム</h1><hr>
    <br>

    <form action="{% url 'contact:contact_form' %}" method="post">
        {% csrf_token %}
        <!-- for文使って要素を取り出す-->
        {% for field in form %}
            <div class="field">
                {{ field.errors }}
                {{ field.label_tag }}
                {{ field }}
                {% if field.help_text %}
                    <p class="help">{{ field.help_text|safe }}</p>
                {% endif %}
            </div>
        {% endfor %}
        <button type="submit">送信</button>
    </form>
</center>

続いてスタイルの設定です。同じファイル内にstyleタグを設けてフォームの枠などを調整します。

<!-- project/contact/templates/contact/contact_form.html -->

<style>

    /* fieldブロックの上部20px空ける */
    .field  {
        margin-top: 20px;
    }

    /* ブロック要素にする */
    label {
        display: block;
    }

    /* 件名・Emailの枠 */
    input {
        width: 20%;
        padding: 5px;
        box-sizing: border-box;
        border: solid 2px;
    }

    /* 注意書きを赤色指定 */
    .help {
        color: red;
    }

    /* メッセージの枠 */
    textarea {
        width: 50%;
        box-sizing: border-box;
        border-radius: 4px;
        border: solid 2px;
    }

    /* 送信ボタン */
    button {
        margin-top: 30px;
        width: 10%;
        padding: 5px;
    }

</style>
....
....
<center>
    <h1>入力フォーム</h1><hr>
    <br>
    ...............
    ...............

label・input・textareaなどは、DjangoのFormクラスが内部的に使っているタグです。

ですので困惑しないでください。

表示してみますと

お問い合わせフォームを設けることによって、そのWebサイトの信用度も増すと思われますのでぜひ取り入れてみましょう。

それでは以上となります。

最後までご覧いただきありがとうございました。

一覧へ戻る