見出し画像

Flask Web Development P69~73

メールを送ってみよう。

flaskにはflask-mailというpythonのメール送信モジュールsmtplibを使いやすくする拡張機能があります。

ということでインストールしましょう。

> conda install -c conda-forge flask-mail

この拡張機能は、SMTP(Simple Mail Transfer Protocol)サーバーに接続し、電子メールを メールを配信します。何も設定されていない場合、Flask-Mail はポート 25 で localhost に接続し、認証なしでメールを送信します。

Google側の設定

今回はgmailから送るのでまずはGoogleアカウント側の設定を行いましょう。
①この設定はGoogleの2段階認証を設定済みの状態が必要になりますので、事前に2段階認証の設定を済ませておいてください。参考ページ:https://www.google.com/landing/2step/?hl=ja
②2段階認証設定後にGoogleアカウント->セキュリティ->アプリパスワードにアクセスします。
③「アプリを選択」の「その他(名前を入力)」を選んで適当に名前を付けます。
④アルファベット16桁のパスワードが発行されるので、メモっておきましょう。


Pythonコードを編集する

STMPのコンフィグレーションキーは以下の通りです。
Default Description

MAIL_HOSTNAME localhost Hostname or IP address of the email server
MAIL_PORT 25 Port of the email server
MAIL_USE_TLS False Enable Transport Layer Security (TLS) security
MAIL_USE_SSL False Enable Secure Sockets Layer (SSL) security
MAIL_USERNAME None Mail account username
MAIL_PASSWORD None Mail account password

hello.pyにメールを送る設定を書き込みます。

import os
from flask_mail import Mail

app.config['MAIL_SERVER'] = 'smtp.gmail.com'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_SSL'] = False
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME')
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD')

mail = Mail(app)

Gmailにメールを送ってみましょう。

anacondaのターミナルを起動して、先ほどのMAIL_USERNAMEとMAIL_PASSWORDを入力しましょう。
hello.pyに直接書いてしまうと危険なのでターミナル上で設定します。

>set MAIL_USERNAME=xxxxxx@gmail.com <- gmailアドレス
>set MAIL_USERPASSWORD=xxxxxxxxxxxxxxxx <- 16桁のパスワード
(ここで、gmailアドレスなどを'xxxxxx@gmail.com'と書かないようにしましょう。メールが送れないです。)

ターミナルでpythonを起動させて

> python

以下のコマンドを打ち込んでいきます。

>> from flask_mail import Message
>> from hello import app, mail
>> msg = Message('test subject', sender = 'xxxxxx@gmail.com', recipients=['xxxxxx@gmail.com'])
>> msg.body = 'text body'
>> msg.html = '<b>HTML</b> body'
>> with app.app_context():
...     mail.send(msg)
...                   <- Enterを押す
>>                   <- これが出たら送信完了

(私は、senderとrecipientsを同じアドレスにしました。)

エラーについて

・smtplib.SMTPAuthenticationError: =>

> set MAIL_USERNAME=xxxxxx@gmail.com <- gmailアドレス
> set MAIL_USERPASSWORD=xxxxxxxxxxxxxxxx <- 16桁のパスワード

が間違ってる可能性があります。

・ConnectionRefusedError: [WinError 10061] 対象のコンピューターによって拒否されたため、接続できませんでした。
アプリのパスワードを使って接続していない可能性があります。
コードのスペルミスもご確認ください。

hello.pyの中に組み込む
shellコマンドを打つのがめんどうくさいので、hello.pyの中で動くようにしましょう。

hello.pyにこんな感じのコードを書き加えます。

app.config['FLASKY_MAIL_SUBJECT_PREFIX'] = 'Tanuki'
app.config['FLASKY_MAIL_SENDER'] = 'Tanuki Yo-ri'
app.config['FLASKY_ADMIN'] = os.environ.get('FLASKY_ADMIN')

mail = Mail(app)

def send_async_email(app, msg):
   with app.app_context():
       mail.send(msg)

def send_email(to, subject, template, **kwargs):
   msg = Message(app.config['FLASKY_MAIL_SUBJECT_PREFIX'] + subject,
                 sender=app.config['FLASKY_MAIL_SENDER'],
                 recipients=[to])
   msg.body = render_template(template + '.txt', **kwargs)
   msg.html = render_template(template + '.html', **kwargs)
   thr = Thread(target=send_async_email, args=[app, msg])
   thr.start()
   return thr

んで、index関数も以下のように書き換えます。

@app.route('/', methods=['GET', 'POST'])
def index():
   form = NameForm()
   if form.validate_on_submit():
       user = User.query.filter_by(username=form.name.data).first()
       if user is None:
           user = User(username = form.name.data)
           db.session.add(user)
           session['known'] = False
           if app.config['FLASKY_ADMIN']:
               send_email(app.config['FLASKY_ADMIN'], 'New User',
                          'mail/new_user', user=user)
       else:
           session['known'] = True
           session['name'] = form.name.data
           form.name.data = ''
           return redirect(url_for('index'))
   return render_template('index.html',
                          form = form, name = session.get('name'),
                          known = session.get('known', False))

①動かす前に、hello.pyを実行するターミナルでFLASKY_ADMINを設定します。(MAIL_USERNAMEとMAIL_PASSWORDは設定済みと想定しています。)

> set FLASKY_ADMIN='xxxxxx@gmail.com'

②hello.pyを実行します。

> python hello.py

③indexの画面で新規の名前を入力してsubmitを押します。
ここで、index関数のif user is None:のif文に入って、app.config['FLASKY_ADMIN']が設定済み(True)なのでsend_email関数が実行されます。

④send_emailとともにsend_async_email関数が実行されて、app.app_context()によってバックグラウンドで(非同期で)、メールが送られます。
app.app_context()についてはこちらのページが参考になると思います。=>https://teratail.com/questions/324503

⑤FLASKY_ADMINに設定されたアドレスにメールが送られます。

動いたやったー!!!


この記事が気に入ったらサポートをしてみませんか?