naritoブログ

このブログはPython/DjangoとBootstrap4で作成されました
Githubのソースコード

Djangoで、メールを送信

約727日前 2016年8月19日2:12
プログラミング関連
Django Python

概要


Djangoでメールを送信するサンプルです。Django1.10で確認しています。

メール送信処理のテスト


まず、settings.pyに以下を追加します。
これはメールを実際には送らずに、コンソールに表示してくれるため、便利です。
ほかにも、ファイルに書き込むもの等、いくつかの種類があります。
言うまでもありませんが、本番の環境では使用しないようにしましょう。
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'


views.py
メールを送信するためのいくつかのサンプルビューを書きました。
from django.contrib.auth.models import User
from django.core.mail import send_mail, EmailMessage
from django.shortcuts import render, redirect
from django.template.loader import get_template
from django.views.decorators.http import require_POST
from testproject import settings


def mail1(request):
    subject = "題名"
    message = "本文\\nです"
    from_email = "info@mail.torina.top"
    # 宛先を変えたい場合は、このリストの中を変更しましょう。このアドレスは私のアドレスです。
    # たまにメールが届きます。ちょっとほんわかします。
    recipient_list = [
        "toritoritorina@gmail.com",
        "narito@mail.torina.top"
    ]

    send_mail(subject, message, from_email, recipient_list)
    return render(request, 'testapp/index.html')


def mail2(request):
    subject = "題名"
    message = "本文\\nです"
    # ログインユーザーなら、request.userでUserモデルインスタンスが取得できます
    user = User.objects.get(email="toritoritorina@gmail.com")
    user.email_user(subject, message)  # メールの送信

    from_email = "info@mail.torina.top"
    user.email_user(subject, message, from_email)  # メールの送信
    return render(request, 'testapp/index.html')


def mail3(request):
    subject = "題名"
    message = "本文\\nです"
    from_email = settings.EMAIL_HOST_USER
    recipient_list = [
        "narito@mail.torina.top"
    ]
    send_mail(subject, message, from_email, recipient_list)
    return render(request, 'testapp/index.html')


def mail4(request):
    subject = "題名"
    message = "本文\\nです"
    from_email = settings.EMAIL_HOST_USER
    to = ["narito@mail.torina.top"]
    bcc = ["info@mail.torina.top"]
    email = EmailMessage(subject, message, from_email, to, bcc)
    email.send()
    return render(request, 'testapp/index.html')


def mail5(request):
    subject = "題名"

    mail_template = get_template('testapp/mailtemplate/mail.txt')
    user = User.objects.get(pk=1)  # is_superuser=True 等もよく使う
    context = {
        "user": user,
    }
    message = mail_template.render(context)

    from_email = settings.EMAIL_HOST_USER
    recipient_list = [
        "narito@mail.torina.top"
    ]
    send_mail(subject, message, from_email, recipient_list)
    return render(request, 'testapp/index.html')




send_mail関数での送信


まずはメール1です。基本的なメールの送信方法になります。
send_mailに、件名、本文、from、toを指定するだけです。
def mail1(request):
    subject = "題名"
    message = "本文\\nです"
    from_email = "info@mail.torina.top"
    recipient_list = [
        "toritoritorina@gmail.com",
        "narito@mail.torina.top"
    ]

    send_mail(subject, message, from_email, recipient_list)
    return render(request, 'testapp/index.html')


送信すると、このようになります。大体動作しています。



Userモデルのemail_userメソッド


次に、mail2です。これはUserモデルに定義されているemail_userというメソッドを使用しています。
from_emailを指定しないと、DEFAULT_FROM_EMAILが使われます。
def mail2(request):
    subject = "題名"
    message = "本文\\nです"
    # ログインユーザーなら、request.userでUserモデルインスタンスが取得できます
    user = User.objects.get(email="toritoritorina@gmail.com")
    user.email_user(subject, message)  # メールの送信

    from_email = "info@mail.torina.top"
    user.email_user(subject, message, from_email)  # メールの送信
    return render(request, 'testapp/index.html')



このようになります。from_emailを省略したsend_mailは、
From: webmaster@localhostとなっていますね。


ちょっと脱線しますが、Djangoのデフォルトの設定はdjango/conf/global_setting.pyにあります。
そこで、
DEFAULT_FROM_EMAIL = 'webmaster@localhost'
と定義されており、このメールアドレスが使われたということです。
私達がsettings.pyを書くときは、上記のglobal_settings.pyを上書きしている形になります。

https://github.com/django/django/blob/master/django/conf/global_settings.py



メールサーバーを使った送信


mail3ですが、その前にsettings.pyを変更しましょう。
実際に、gmailを使ってメールを送信してみることにします。
他のメールサーバや、自分のメールサーバを利用する場合は書き換えてみましょう。
Gmailで上手く送信できない場合は、二段回認証を利用しましょう。その場合、PASSWORD部分がアカウントのパスではなく、発行されたパスワードを使うことになります。
# コメントアウト
# EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'gmailアカウント名'
EMAIL_HOST_PASSWORD = 'gmailパスワード'
EMAIL_USE_TLS = True


mail3です。mail1とほとんど同じですね。
def mail3(request):
    subject = "題名"
    message = "本文\\nです"
    from_email = settings.EMAIL_HOST_USER
    recipient_list = [
        "narito@mail.torina.top"
    ]
    send_mail(subject, message, from_email, recipient_list)
    return render(request, 'testapp/index.html')


これを実際に送信してみました。
gmailの送信済みを見ると、ちゃんと送信されていることがわかります。



EmailMessageでの柔軟なメール送信


続いてmail4。今回はbccを使いたいと思いました。
bccやファイル添付をしたい場合、EmailMessageを使います。
Django の send_mail 関数は、実際には EmailMessage クラスに対して薄いラッパをかぶせたものに すぎません。
def mail4(request):
    subject = "題名"
    message = "本文\\nです"
    from_email = settings.EMAIL_HOST_USER
    to = ["narito@mail.torina.top"]
    bcc = ["info@mail.torina.top"]
    email = EmailMessage(subject, message, from_email, to, bcc)
    email.send()
    return render(request, 'testapp/index.html')


ちゃんとbccも追加されてますね。



テンプレートを使った送信


最後、mail5です。
メールの文章が複雑になったり、あるモデルの属性を文章に埋め込みたくなりました。
このような場合、以下のようにします。
def mail5(request):
    subject = "題名"

    mail_template = get_template('testapp/mailtemplate/mail.txt')
    user = User.objects.get(pk=1)  # is_superuser=True 等もよく使う
    context = {
        "user": user,
    }
    message = mail_template.render(context)

    from_email = settings.EMAIL_HOST_USER
    recipient_list = [
        "narito@mail.torina.top"
    ]
    send_mail(subject, message, from_email, recipient_list)
    return render(request, 'testapp/index.html')



testproject/templates/testapp/mailtemplate/mail.txt
ちょっと置き場所が複雑になってしまいましたが、好きな場所に置きましょう。
通常のtemplateと、同じように書けます。
{{ user.username }}様

苗字: {{ user.first_name }}
名前: {{ user.last_name }}
メールアドレス: {{ user.email }}
{% if user.is_superuser %}
あなたは管理者です。
{% endif %}


以下の部分がポイントです。
mail_template = get_template('testapp/mailtemplate/mail.txt')
user = User.objects.get(email="toritoritorina@gmail.com")
context = {
    "user": user,
}
message = mail_template.render(context)



実際に送信してみました。
上のメールは、通常のUser。下は管理者で送信しました。
初心者a 約192日前 2018年2月5日21:29 返信する
メールについて詳しくないのですが、EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587はGmailを使用する場合には固定で構わないのでしょうか?
なりと 約192日前 2018年2月5日21:59
はい、Gmail利用の場合はその2つは固定で大丈夫です。
初心者a 約192日前 2018年2月5日22:17 返信する
ありがとうございます。
生徒 約48日前 2018年6月29日20:50 返信する
いつも楽しく拝見しています。
この記事と、「Djangoでユーザー作成処理(仮登録後、URLクリックで本登録(https://torina.top/detail/273/))」の記事を参考にして、gmailで確認メールが送信される会員登録システムを作ろうとしていますが、エラーが出て先に進まなくなってしまったので質問させて頂きます。

osはcentOS7を使用しています。
localhostの環境では問題なく動いていたのですが、centOS上にデプロイすると、仮登録画面の「送信」をクリックした次の画面で画面が真っ白になり500(server error)と表示されます。

settings.pyは、以下の通りです。
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'gmailのメールアドレス'
EMAIL_HOST_PASSWORD ='gmailのパスワード'
EMAIL_USE_TLS = True

views.pyは、narito先生が「Djangoでユーザー作成処理」内で紹介している「UserCreate」classを使用しています。
また、このエラーが発生したときにサーバー内のデータベースを確認すると、サーバー内にはメールアドレス等は登録されています。

この状況において、どのような事が原因と考えられるでしょうか。
ヒントだけでも頂けると嬉しく思います。
なりと 約47日前 2018年6月29日23:11
メール送信処理でエラーが出ているように感じます。
念の為一旦DEBUG=Trueでエラー内容を確認するか
又は、cat /var/log/nginx/error.log
などにエラーログが表示されているかもしれませんので、そちらを確認してみてください。
生徒 約47日前 2018年6月30日3:50
ご指導頂きまして誠に有難うございます。
DEBUGモードをオンにしてみると、smtplib.SMTPAuthenticationError が表示されました。
このエラーメッセージをstackoverflowで調べてみると、googleのセキュリティ設定を「安全性の低いアプリのアクセスを許可」するとメールを送信できるという回答がありました。
しかし、すでにこの設定は許可しているのですが、依然としてこのエラーが表示されます。
djangoから視点をcentOSに移してインターネットで検索を行うと、Postfixというメール転送エージェントがさくらのVPSには標準でついているという記述を見かけたのですが、このエージェントの設定は関係ありますでしょうか。
質問ばかりで心苦しいですが、アドバイス頂けたら嬉しく思います。
なりと 約47日前 2018年6月30日7:57
その場合は2段階認証を利用するようにしてください。
http://blog.saboh.net/smtpgmailcom/
アプリケーション専用のパスワードを作成したら、それをsettings.pyに書きます。

今回のように、Googleのような外部のメールサーバーを利用する場合はPostfixはを使いません。そのパソコンをメールサーバーとして利用する場合(送信処理)に、Postfixが使われます。
生徒 約47日前 2018年6月30日19:02
narito大先生、googleの2段階認証の設定をすることで、実装することができました!
2段階認証に、他のアプリケーションからのアクセスを許可する機能が備わっているとは思いませんでした。
いつも的確なアドバイスを頂きまして誠に有難うございます!