メールを送ってみよう。
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に設定されたアドレスにメールが送られます。
動いたやったー!!!
前回の記事はこちら
前回の記事はこちら