Home

DjangoでGmail送信

update: 2019-04-22

python

メールの送信方法

  1. OS 内部のメールサーバ(postfix 等)
  2. 外部 smtp サービス(gmail 等)
  3. 外部メール配信サービス(mailgun,SendGrid)

smtp で送信する場合は 1,2、Rest API でも送信したい場合は 3 の方式になるかなと。どの方法も一長一短ですが、ここでは gmail の smtp サービスを利用して、Django からメールを送信する方法をご紹介します。

Google 提供の smtp サービス

実は smtp サービスには下記の 3 種類(詳細はこちら)があります。 当然ですがそれぞれドメインと port が異なるので、それに応じて Django の設定値を変更する必要があります。Django での設定も含めて紹介します。
メール送信はsend_mail関数を次のように使用

from django.core.mail import send_mail
send_mail(
   "Subject here",
   "Here is the message.",
   "alice@example.com",
   ["{確認用gmail}"],
   fail_silently=False,
)

G Suite SMTP リレー

有料サービスです。G Suite(無償版)では利用できません。有償なだけあって柔軟な設定が出来ます。認証方法もパスワード認証だけでなく、静的 IP アドレスで許可も出来ます。 企業で利用する場合はこちらの利用が推奨されています。G Suite の admin 権限で設定する感じです。

権限がないもので、こちらの具体的な方法は紹介できません 🙇‍♂️ 次に紹介する2つは無料なのでいろいろ試してみました。

Gmail SMTP サーバー

スタンダード。この方法は認証が必須で、 Gmail とパスワードを設定する必要があります。

EMAIL_HOST = "smtp.gmail.com"
EMAIL_PORT = 587
EMAIL_HOST_USER = "{gmailのアドレス}"
EMAIL_HOST_PASSWORD = "{パスワード}"
EMAIL_USE_TLS = True

google 側で何も設定しないで  メール送信を行った場合下記のエラーが起こるかと思います。

smtplib.SMTPAuthenticationError: (535, b'5.7.8 Username and Password not accepted. Learn more at\n5.7.8 https://support.google.com/mail/?p=BadCredentials v1sm1470542pff.9 - gsmtp')

エラーメッセージのリンク先にも解決方法が書かれていますが、 アプリ パスワードを使用する方法はこちら、安全性の低いアプリを許可する方法はこちらのブログでご紹介されるので具体的な設定方法は割愛します。

受信メールを確認すると from が EMAIL_HOST_USER で設定した値となっており、send_mail の from アドレスは無視されます。

制限付き Gmail SMTP サーバー

なんと認証不要です。なので下記のみの設定でメール送信できます。

EMAIL_HOST = "aspmx.l.google.com"
EMAIL_PORT = 25

認証しないので EMAIL_HOST_USER 以下 の定義は不要です。あと認証が無い分送信も早いです。注意点としては gmail アカウントにしか送信できません。これが制限付きの意味するところ。

メールを確認したところ、from のアドレスは send_mail の引数通り alice@example.com になってます。設定次第で迷惑メールに振り分けられるかもです。

送信対象が gmail のみで返信が不要の場合や、自分宛ての場合はこちらの方法で十分な気がします。

また、send_mail の from_email をめちゃくちゃな値にしてみるとエラーになってしまします。迷惑メールに突っ込まれることもなかったです。SPF(後ほど紹介)が fail でも受信できているアドレスに対して同様に送ってるので謎いです。存在しないドメイン(spf が temperror)でもいけたんですよね。。

smtplib.SMTPDataError: (550, b'5.7.1 This message does not have authentication information or fails to pass\n5.7.1 authentication checks. To best protect our users from spam, the\n5.7.1 message has been blocked. Please visit\n5.7.1 https://support.google.com/mail/answer/81126#authentication for more\n5.7.1 information. cn6si984272plb.242 - gsmtp')

他にも様々なエラーがあるようです。 SMTP エラー リファレンス

送信者偽称

これで送信者の偽装ができるようになったわけですが、こんなこと許されて言い訳がないと思ったのでどんな対策方法があるのか調査してみたところ、SPF というフレームワークがあるようです。gmail でも使われています。
簡単に説明すると、送信者のドメインが実際の送信元 ip を承認しているかチェックする手法です。ドメインに SPF レコードが登録されているかどうかは checkmxで確認出来ます。

ということで、先程送信してみた alice@example.com に偽ったメールのメールヘッダをG Suite Toolbox Messageheader で確認したみたら SPF の結果が fail となっていました。 ちなみに、メールヘッダは下記手順で簡単に解析できます。

  1. gmail のメールを表示
  2. メニューからメッセージのソースを表示
  3. クリップボードにコピー
  4. Messageheader にペースト

結果が fail のになぜ受信できるのかというと、DMARC が設定されてないからです。example.com の checkmx 実行結果からもわかります。 DMRAC は SPF や DKIM で失敗した際の受信側の挙動を指示するものです。受信側が DMRAC に対応していないと、意味がありませんが gmail はもちろん対応しています。

参考

https://salt.iajapan.org/wpmu/anti_spam/admin/tech/explanation/spf/ https://www.nic.ad.jp/ja/basics/terms/spf.html https://www.cuenote.jp/library/marketing/dmarc.html https://simpleisbetterthancomplex.com/tutorial/2017/05/27/how-to-configure-mailgun-to-send-emails-in-a-django-app.html