资讯专栏INFORMATION COLUMN

Flask Web Development —— Email

SKYZACK / 3263人阅读

摘要:函数携带目的地址主题邮件体模板和一组关键字参数。许多扩展操作是在假设有活动的应用程序和请求上下文的情况下进行的。但是当函数在一个不同的线程上执行,应用程序上下文需要人为地创建使用。例如,执行函数可以将邮件发送到的任务队列中。

许多类型的应用程序都会在某些事件发生的时候通知用户,常用的沟通方法就是电子邮件。尽管在Flask应用程序中,可以使用Python标准库中的smtplib包来发送电子邮件,不过Flask-Mail扩展封装了smtplib且与Flask整合的非常好。

1、使用Flask-Mail作为邮件支持

使用pip安装Flask-Mail:

(venv) $ pip install flask-mail

扩展连接到一个简单邮件传输协议(SMTP)服务器并将邮件传递给它由它递送。如果没有给出配置,Flask-Mail则连接到localhost25端口并发送无验证的电子邮件。表6-1所示的配置键列表可以用来配置SMTP服务器。

表格6-1. Flask-Mail SMTP服务器配置键

在开发过程中如果能连接到一个外部SMTP服务器会更方便。示例6-1展示了如何配置应用程序通过谷歌的Gmail帐户发送电子邮件。

示例6-1. hello.py:Flask-Mail配置Gmail

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")
  

建议:永远不要将账户证书直接写在你的脚本里面,尤其是如果你打算将你的的工作开源。为了保护你的帐户信息,必须让脚本从你的配置环境中导入敏感信息。

示例6-2展示了Flask-Mail的初始化。

示例6-2. hello.py:Flask-Mail初始化

from flask.ext.mail import Mail

mail = Mail(app)

持有email服务器用户名和密码的两个变量需要在环境中定义。如果你是使用Linux或Mac OS X上的bash,你可以设置这些变量如下:

(venv) $ export MAIL_USERNAME=
(venv) $ export MAIL_PASSWORD=

对于Windows用户,可以设置环境变量如下:

(venv) $ set MAIL_USERNAME=
(venv) $ set MAIL_PASSWORD=
1.1、使用python shell发送邮件

为了测试配置,你可以开启一个shell会话并发送测试email:

(venv) $ python hello.py shell
>>> from flask.ext.mail import Message
>>> from hello import mail
>>> msg = Message("test subject", sender="you@example.com",
... recipients=["you@example.com"])
>>> msg.body = "text body"
>>> msg.html = "HTML body"
>>> with app.app_context():
... mail.send(msg)
...

注意,Flask-Mail的send()函数使用current_app,所以它需要执行已激活的应用程序上下文。

1.2、集成邮件到应用程序

为了避免每次都手动创建电子邮件消息,将应用电子邮件发送功能的共同部分抽象到一个函数中是非常不错的做法。另一个好处是,这个函数可以用Jinja2模板尽情渲染。示例6-3展示了怎么实现。

示例6-3. hello.py:Email支持

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()调用,这样模板就可以生成email体。

index()视图函数可以非常容易的扩充用来发送一个email给管理员,当从表单中收到一个新的名字的时候。示例6-4展示所做的改动。

示例6-4. hello.py:Email示例

# ...
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))

启动过程中,在FLASKY_ADMIN环境变量中给出的email收件人会加载到同名的配置变量中。需要创建文本和HTML两个版本的email模板文件。这些文件都存储在template内的mail子目录中,让他们独立于普通模板。电子邮件模板需要给出用户作为该模板参数,因此send_email()调用包括用户来作为一个关键字参数。

  

建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 6a来切换到这个版本的应用程序。

除了前面描述的MAIL_USERNAMEMAIL_PASSWORD环境变量,这个版本的应用程序需要FLASKY_ADMIN环境变量。对于Linux和Mac OS X用户来说,启动应用程序命令:

(venv) $ export FLASKY_ADMIN=

对于Windows用户,命令如下:

(venv) $ set FLASKY_ADMIN=

使用这些环境变量设置,当你每次在表单中输入一个新的名字的时候都可以测试应用程序和接收电子邮件。

1.3、发送异步邮件

如果你发送一些测试邮件,你可能注意到mail.send()函数在发送电子邮件的时候会阻塞几秒钟,这段时间浏览器看起来没有响应。为了避免请求处理不必要的延误,可以将邮件发送功能移到一个后台线程去处理。示例6-5展示了以上改动。

示例6-5. hello.py:异步邮件支持

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()

  

建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 6b来切换到这个版本的应用程序。

如果你现在运行应用程序,你会发现它响应更快了,但请记住,发送大量的电子邮件的应用程序,其拥有一个致力于发送电子邮件的服务比开启一个新的线程更合适。例如,执行send_async_email()函数可以将邮件发送到Celery的任务队列中。

本章完成的是大多数web应用程序必备的功能。现在的问题是,hello.py脚本开始大,这使得它变得更难管理。在下一章中,你将学习如何构建一个更大的应用程序。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/45324.html

相关文章

  • Flask Web Development —— 大型应用程序结构(上)

    摘要:被定义在包的构造函数中的应用程序工厂函数会在示例中展示。这个构造函数导入大部分当前需要使用的扩展,但因为没有应用程序实例初始化它们,它可以被创建但不初始化通过不传递参数给它们的构造函数。而应用程序范围内的错误处理则必须使用。 虽然小型web应用程序用单个脚本可以很方便,但这种方法却不能很好地扩展。随着应用变得复杂,在单个大的源文件中处理会变得问题重重。 与大多数其他web框架不同,Fl...

    chemzqm 评论0 收藏0
  • Flask 插件系列 - Flask-Mail

    摘要:带附件的邮件有时候,我们发邮件的时候需要添加附件,比如文档和图片等,这也很简单,代码如下邮件服务器地址邮件服务器端口启用上面的代码中,我们通过打开了本机的某张图片,然后通过方法将附件内容添加到对象。 前往本文博客 简介 给用户发送邮件是 Web 应用中最常见的任务之一,比如用户注册,找回密码等。Python 内置了一个 smtplib 的模块,可以用来发送邮件,这里我们使用 Flask...

    ingood 评论0 收藏0
  • 初见Flask

    摘要:接收用户请求并分析请求的。执行函数并生成响应,返回给浏览器。这个过程我们称为注册路由,路由负责管理和函数之间的映射,而这个函数则被称为视图函数。文件是一个名为的文本文件,它存储了项目中提交时的忽略文件规则清单。 flask简述 Flask 是一个基于 Python 开发并且依赖 jinja2 模板和 Werkzeug WSGI 服务的一个微型框架,对于 Werkzeug 本质是 Soc...

    tomorrowwu 评论0 收藏0
  • [分享] Flask 网络开发经典书籍: Flask Web Development

    摘要:他和妻子四个孩子两只狗和一只猫共同生活在俄勒冈州波特兰市。。还邀请他根据书的内容,制作了两个视频教程。 showImg(http://img4.douban.com/lpic/s27205547.jpg); 这本书算是学习Flask的权威材料了,网上很多人都是推荐从这本书开始学习。起初,作者在自己的博客发布了一个大型的Flask建站教程,在这个教程大受欢迎的基础上,才与OReilly公...

    HmyBmny 评论0 收藏0
  • Flask Web Development —— Web表单(上)

    摘要:每个表单域都可以连接到一个或多个是一个用于检查用户提交的输入是否合法的函数。表单域构造函数的第一个参数是一个,在渲染表单到时会使用。验证确保提交的表单域不为空。表单域验证都是直接从包中导入。表格展示了一组支持的标准表单域。 第二章中介绍的request对象公开了所有客户端发送的请求信息。特别是request.form可以访问POST请求提交的表单数据。 尽管Flask的request...

    CODING 评论0 收藏0

发表评论

0条评论

SKYZACK

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<