Flask Web 开发学习稿(三)

发布时间:2017-09-11 12:14:37
Flask Web 开发学习稿(三) 第六章 电子邮件

当我们需要在特定事件发生时提醒用户,包装了 smtplib 的 Flask-Mail 扩展能更好的和 Flask 集成
安装 pip install flask-mail
Flask-Mail 连接到 SMTP 服务器,如果不进行配置,Flask-Mail 会连接 localhost 上的端口 25

配置 默认值 说明
MAIL_SERVER localhost Email服务器的ip地址或者主机名
MAIL_PORT 25 Email服务器端口
MAIL_USE_TLS False 启用传输层安全协议
MAIL_USE_SSL False 启用安全套接曾协议
MAIL_USERNAME None Email用户名
MAIL_PASSWORD None Email密码

使用外部 SMTP 服务器更加方便

from flask.ext.mail import Mail app.config['MAIL_SERVER'] = 'mail.xxx.com' app.config['MAIL_PORT'] = '587' app.config['MAIL_USE_TLS'] = 'True' app.config['MAIL_USERNAME'] = 'username' app.config['MAIL_PASSWORD'] = 'pwd' mail = Mail(app)

将账户和密码写在程序里太不安全了,为了保护敏感信息,需要让脚本从环境变量中导入这些信息

app.config['MAIL_USERNAME'] = os.environ.get('MALI_USERNAME') app.config['MAIL_PASSWORD'] = os.environ.get('MALI_PASSWORD')

如何设置环境变量呢?

# Linux 或者 Mac OS X export MALI_USERNAME= export MALI_PASSWORD= # Windows set MALI_USERNAME= set MALI_PASSWORD=

在程序中集成发送电子邮件功能

from flask.ext.mail import Message app.config['FLASKY_MAIL_SUBJECT_PREFIX'] = '[Flasky]' app.config['FLASKY_MAIL_SENDER'] = 'Flasky Admin ' 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)

这两个程序特定配置项,分别定义了邮件主题的前缀和发件人的地址
send_email() 函数的参数分别为收件人地址,主题,渲染邮件正文的模版和关键字参数列表
指定模版时不能包含扩展名,这样才能使用两个模版分别渲染纯文本正文和富文本正文
调用者将关键字参数传给 render_template() 函数以便在模版中使用,进而生成电子邮件正文,下面修改视图函数

app.config['FLASKY_ADMIN'] = os.environ.get('FLASKY_ADMIN') #... @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))

我们要创建两个模版文件,分别用于渲染纯文本和 HTML 版的邮件正文,这两个模版文件都保存在 tmplates 文件夹下的 mail 子文件夹中,以便和普通模版区分开来。电子邮件的模版中要有一个模版参数是用户,因此调用 send_mail() 函数时要以关键字参数的形式传入用户
这样的程序会在发送邮件的时候造成短暂阻塞,异步发送电子邮件来消除这种不必要的延迟

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['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

很多 Flask 扩展都假设已经存在激活的程序上下文和请求上下文,Flask-Mail 中的 send() 函数使用 current_app,因此必须激活程序上下文,不过不同线程中执行mail.send()函数时,程序上下文要使用 app.app_context() 人工创建
当你需要大量发送电子邮件时,使用 Celery 任务队列更合适

第七章 大型程序的结构

企业建站2800元起,携手武汉肥猫科技,做一个有见地的颜值派!更多优惠请戳:湖北SEO http://hubei.raoyu.net