电子邮件支持

因为博客要支持评论,所以我们需要在文章有了新评论后发邮件通知管理员。而且,当管理员回复了读者的评论后,也需要发送邮件提醒读者。

为了方便读者使用示例程序,personalBlog中仍然使用Flask-Mail来发送邮件。读者在运行程序前需要在项目根目录内创建.env文件写入对应的环境变量,以便让发信功能正常工作。

因为邮件的内容很简单,我们将直接在发信函数中写出正文内容,这里只提供了HTML正文。我们有两个需要使用电子邮件的场景:

1、当文章有新评论时,发送邮件给管理员;

2、当某个评论被回复时,发送邮件给被回复用户。

为了方便使用,我们在emails.py中分别为这两个使用场景创建了特定的发信函数,可以直接在视图函数中调用 。这些函数内部则通过我们创建的通用发信函数send_email()来发送邮件,如下所示 :

personalBlog/emails.py: 提醒邮件函数

from flask import url_for

def send_mail(subject, to, html):
pass def send_new_comment_email(post):
# blog.show_post是blog蓝本下的show_post视图函数
post_url = url_for('blog.show_post', post_id = post.id, _external = True) + '#comments'
send_mail(subject = 'New comment', to = current_app.config['BLUEBLOG_ADMIN_EMAIL'],
html = '<p>New comment in post <i>%s</i>, click the link below to check:</p>'
'<p><a href="%s">%s</a></p>'
'<p><small style = "color:#868e96">Do not reply this email.</small></p>'
% (post.title, post_url, post_url)) def send_new_reply_email(comment):
post_url = url_for('blog.show_post', post_id = comment.post_id, _external = True) + '#comments'
send_mail(subject = 'New reply', to = comment.email,
html = '<p>New reply for the comment you left in post <i>%s</i>, click the link below to check: </p>'
'<p><a href="%s">%s</a></p>'
'<p><small style="color: #868e96">Do not reply this email.</small></p>'
% (comment.post.title, post_url, post_url))

send_new_comment_email()函数用来发送新评论提醒邮件。 我们通过将url_for()函数的_external参数设为True来构建外部链接。链接尾部的#comments是用来跳转到页面评论部分的URL片段(URL fragment),comments是评论部分div元素的id值。这个函数接收表示文章的post对象作为参数,从而生成文章正文的标题和链接。

URL片段又称片段标识符(fragment identifier),是URL中用来表示页面中资源位置的短字符,以#开头,对于HTML页面来说,一个典型的示例是文章页面的评论区。假设评论区的div元素id为comment,如果我们访问http://example.com/post/7#comment,页面加载完成后将会直接跳到评论部分。

send_new_reply_email()函数则用来发送新回复提醒邮件。这个发信函数接收comment对象作为参数,用来构建邮件正文,所属文章的主键值通过comment.post_id属性获取,标题则通过comment.post.titlle属性获取。

在personalBlog源码中,我们没有使用异步的方式发送邮件,如果你希望编写一个异步发送邮件的通用发信函数send_mail(),和之前介绍的基本相同,如下所示

from threading import Thread
from flask import current_app
from flask_mail import Message from personalBlog.extensions import mail def _send_async_mail(app, message):
with app.app_context():
mail.send(message) def send_async_mail(subjecct, to, html):
app = current_app._get_current_object() # 获取被代理的真实对象
message = Message(subjecct, recipients=[to], html = html)
thr = Thread(target = _send_async_mail, args = [app, message])
thr.start()
return thr

需要注意,因为我们的程序是通过工厂函数创建的,所以实例化Thread类时,我们使用代理对象current_app作为args参数列表中app的值。另外,因为在新建线程时需要真正的程序对象来创建上下文,所以不能直接传入current_app,而是传入current_app调用_get_current_app()方法获取的被代理的程序实例。

flask实战-个人博客-电子邮件支持的更多相关文章

  1. flask实战-个人博客-虚拟环境、项目结构

    个人博客 博客是典型的CMS(Content Management system,内容管理系统),通常由两部分组成:一部分是博客前台,用来展示开放给所有用户的博客内容:另一部分是博客后台,这部分内容仅 ...

  2. flask实战-个人博客-编写博客前台

    编写博客前台 博客前台需要开放给所有用户,这里包括显示文章列表.博客信息.文章内容和评论等功能功能. 分页显示文章列表 为了在主页显示文章列表,我们要先在渲染主页模板的index视图的数据库中获取所有 ...

  3. flask实战-个人博客-模板 --

    模板 personalBlog采用典型的博客布局,左侧三分之二为主体,显示文章列表.正文:右侧三分之一为边栏,显示分为类列表.社交链接等.现在的工作是将HTML文件加工为模板,并创建对应的表单类,在模 ...

  4. flask实战-个人博客-数据库-生成虚拟数据 --

    3.生成虚拟数据 为了方便编写程序前台和后台功能,我们在创建数据库模型后就编写生成虚拟数据的函数. 1)管理员 用于生成虚拟管理员信息的fake_admin()函数如下所示: personalBlog ...

  5. flask实战-个人博客-程序骨架、创建数据库模型、临接列表关系 --

    编写程序骨架 personalBlog的功能主要分为三部分:博客前台.用户认证.博客后台,其中包含的功能点如下图所示: 数据库 personalBlog一共需要使用四张表,分别存储管理员(Admin) ...

  6. flask实战-个人博客-使用蓝本模块化程序

    使用蓝本模块化程序 实例化flask提供的blueprint类就创建一个蓝本实例.像程序实例一样,我们可以为蓝本实例注册路由.错误处理函数.上下文处理函数,请求处理函数,甚至是单独的静态文件文件夹和模 ...

  7. flask实战-个人博客-表单

    表单 下面我们来编写所有表单类,personalBlog中主要包含下面这些表单: 登录表单: 文章表单: 评论表单: 博客设置表单: 这里仅介绍登录表单.文章表单.分类表单和评论表单,其他的表单在实现 ...

  8. flask实战-个人博客-使用工厂函数创建程序实例 --

    使用工厂函数创建程序实例 使用蓝本还有一个重要的好处,那就是允许使用工厂函数来创建程序实例.在OOP(Object-Oriented Programming,面向对象编程)中,工厂(factory)是 ...

  9. flask实战-个人博客-使用类组织配置

    使用类组织配置 在实际需求中,我们往往需要不同的配置组合.例如,开发用的配置,测试用的配置,生产环境用的配置.为了能方便地在这些配置中切换,你可以把配置文件升级为包,然后为这些使用场景分别创建不同的配 ...

随机推荐

  1. [LeetCode] 772. Basic Calculator III 基本计算器之三

    Implement a basic calculator to evaluate a simple expression string. The expression string may conta ...

  2. 阿里Sentinel控制台源码修改-对接Apollo规则持久化

    改造背景 前面我们讲解了如何对接Apollo来持久化限流的规则,对接后可以直接通过Apollo的后台进行规则的修改,推送到各个客户端实时生效. 但还有一个问题就是Sentinel控制台没有对接Apol ...

  3. 第09组 Beta冲刺(1/5)

    队名:观光队 链接 组长博客 作业博客 组员实践情况 王耀鑫 过去两天完成了哪些任务 文字/口头描述 任务分配 展示GitHub当日代码/文档签入记录 接下来的计划 完成短租车,页面美化 还剩下哪些任 ...

  4. intellij idea安装教程

    1. 双击ideaIU-12.1.1.exe,点击下一步,安装目录改为d:\Program Files\JetBrains\IntelliJ IDEA,其他项都默认即可(此处更改目录方便重做系统,不用 ...

  5. Error running 'xxx': Command line is too long. Shorten command line for xxx

    跑单元测试时,报错如下: Error running 'xxx': Command line is too long. Shorten command line for xxx 解决方案: 在项目所在 ...

  6. oracle--10GRAC集群(NFS共享存储)

    一,NFS服务器配置 01, 安装包查看 [root@standby2 ~]# rpm -qa|grep nfs nfs-utils-lib--.el6.x86_64 nfs4-acl-tools-- ...

  7. ZROI1153 【线上训练3】数个数

    ZROI1153 [线上训练3]数个数 传送门 一道非常有意思的题,涵盖了各种知识点. 首先,很显然,这是个容斥.容斥可以过掉\(30pts\). 这里我们考虑容斥+DP. 我们令\(dp[i][j] ...

  8. Golang 基础语法介绍及对比(二)

    传值与传参 Golong func main() { a := fmt.Println("a = ", a) // 应该输出 "a= 3" a1 := add1 ...

  9. C# HTTP系列8 GET与POST对比说明

    系列目录     [已更新最新开发文章,点击查看详细]  HTTP协议,即超文本传输协议(Hypertext transfer protocol).是一种详细规定了浏览器和万维网(WWW = Worl ...

  10. GC分析工具使用-gceacy分析堆栈

    gceasy是一款在线的gc分析工具.试用一下分析jstack的日志 1.jstack -l 3539 > 3539.stack 2.打包成zip文件 3.上传https://gceasy.io ...