电子邮件 Flask-Mail
1.使用Flask-Mail提供电子邮件支持
举个例子,示例 6-1 展示了如何配置程序,以便使用 Google Gmail 账户发送电子邮件。
#初始化 Flask-Mail
from flask_mail import Mail
mail = Mail(app)
import os
# ...
app.config['MAIL_SERVER'] = 'smtp.googlemail.com'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME')
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD')
关于账户密码在环境变量中定义
Mac OS X 中使用 bash,那么可以按照下面的方式设定这两个变量:
(venv) $ export MAIL_USERNAME=<Gmail username>
(venv) $ export MAIL_PASSWORD=<Gmail password>
微软 Windows 用户可按照下面的方式设定环境变量:
(venv) $ set MAIL_USERNAME=<Gmail username>
(venv) $ set MAIL_PASSWORD=<Gmail password>
2.在程序中集成发送电子邮件
为了避免每次都手动编写电子邮件消息,我们最好把程序发送电子邮件的通用部分抽象出来,定义成一个函数。这么做还有个好处,即该函数可以使用 Jinja2 模板渲染邮件正文,灵活性极高。
from flask.ext.mail import Message
app.config['FLASKY_MAIL_SUBJECT_PREFIX'] = '[Flasky]'
app.config['FLASKY_MAIL_SENDER'] = 'Flasky Admin<flasky@example.com>'
#参数分别是 收件人地址、主题、渲染邮件正文的模板和关键字参数列表
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)
# 主题, 发送人 , 收件人 收件人要用列表
Message(app.config['FLASKY_MAIL_SUBJECT_PREFIX'] + subject,sender=app.config['FLASKY_MAIL_SENDER'], recipients=[to])
3 异步发送电子邮件
mail.send() 函数在发送电子邮件时停滞了几秒钟,在这个过程中浏览器就像无响应一样。为了避免处理请求过程中不必要的延迟,我们可以把发送电子邮件的函数移到后台线程中。
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
不过要记住,程序要发送大量电子邮件时,使用专门发送电子邮件的作业要比给每封邮件都新建一个线程更合适。例如,我们可以把执行 send_async_email() 函数的操作发给 Celery(http://www.celeryproject.org/)任务队列。