python flask发送邮件
* SMTPAuthenticationError: (535, ‘Error: authentication failed’)
解决办法:调用163邮箱服务器来发送邮件,我们需要开启POP3/SMTP服务,这时163邮件会让我们设置客户端授权码,这个授权码替代上面代码部分的passwd即可成功发送邮件
安装flask-mail
pip3 install flask-mail
总体结构图
hello.py
import os
from flask import Flask, render_template, session, redirect, url_for
from flask_script import Manager, Shell
from flask_bootstrap import Bootstrap
from flask_moment import Moment
from flask_wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import Required
from flask_mail import Mail, Message
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['MAIL_SERVER'] = 'smtp.163.com' # 163smtp服务器
app.config['MAIL_PORT'] = 25 # 端口号
app.config['MAIL_USERNAME'] = "[email protected]"
app.config['MAIL_PASSWORD'] = "abcabc" #填写客户端授权码
app.config['FLASKY_MAIL_SUBJECT_PREFIX'] = '[Flasky]'
app.config['FLASKY_MAIL_SENDER'] = '[email protected]'
app.config['FLASKY_ADMIN'] = "[email protected]"
manager = Manager(app)
bootstrap = Bootstrap(app)
moment = Moment(app)
mail = Mail(app)
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)
mail.send(msg)
class NameForm(Form):
name = StringField('What is your name?', validators=[Required()])
submit = SubmitField('Submit')
def make_shell_context():
return dict(app=app)
manager.add_command("shell", Shell(make_context=make_shell_context))
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
@app.errorhandler(500)
def internal_server_error(e):
return render_template('500.html'), 500
@app.route('/', methods=['GET', 'POST'])
def index():
form = NameForm()
if form.validate_on_submit():
user = form.name.data
session['known'] = True
if app.config['FLASKY_ADMIN']:
send_email([app.config['FLASKY_ADMIN'], '[email protected]'], 'New User',
'mail/new_user', user=user)
session['name'] = form.name.data
return redirect(url_for('index'))
return render_template('index.html', form=form, name=session.get('name'),
known=session.get('known', False))
if __name__ == '__main__':
manager.run()
404.html
{% extends "base.html" %}
{% block title %}Flasky - Page Not Found{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Not Foundh1>
div>
{% endblock %}
500.html
{% extends "base.html" %}
{% block title %}Flasky - Internal Server Error{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Internal Server Errorh1>
div>
{% endblock %}
index.html
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Flasky{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Hello, {% if name %}{{ name }}{% else %}Stranger{% endif %}!h1>
{% if not known %}
<p>Pleased to meet you!p>
{% else %}
<p>Happy to see you again!p>
{% endif %}
div>
{{ wtf.quick_form(form) }}
{% endblock %}
base.html
{% extends "bootstrap/base.html" %}
{% block title %}Flasky{% endblock %}
{% block head %}
{{ super() }}
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">
{% endblock %}
{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigationspan>
<span class="icon-bar">span>
<span class="icon-bar">span>
<span class="icon-bar">span>
button>
<a class="navbar-brand" href="/">Flaskya>
div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">Homea>li>
ul>
div>
div>
div>
{% endblock %}
{% block content %}
<div class="container">
{% for message in get_flashed_messages() %}
<div class="alert alert-warning">
<button type="button" class="close" data-dismiss="alert">×button>
{{ message }}
div>
{% endfor %}
{% block page_content %}{% endblock %}
div>
{% endblock %}
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}
异步发送电子邮件
from threading import Thread
def send_async_email(app,msg):
with app.app_context():
mail.send(msg)
def send_email(to,subject,template, **kwargs):
msg = Message(app.config['FLASK_MAIL_SUBJECT_PREFIX']+subject,
sender=app.config['FLASK_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
注意:很多Flask扩展都假设已经存在激活的程序上下文和请求上下文。Flask-Mail中的send()函数使用current_app,因此必须激活程序上下文。不过,在不同线程中执行mail.send()函数时,程序上下文要使用app.app_context()人工创建。