电子邮件支持

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

为了方便读者使用示例程序,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. torch_09_DCGAN_注意的细节

    DCGAN github链接:https://github.com/darr/DCGAN DCGAN:1.在一次epoch中,如果第i批的i能够整除every_print,则打印到output文件中( ...

  2. 将Prometheus alerts保存到elasticsearch

    Prometheus产生的告警通常会发送到alertmanager,当使用alertmanager时,其告警信息仅存在于alertmanager的内存中,无法持久化.故实现了小工具,用于将Promet ...

  3. XMLHttpRequest原生方法

    时间久了,在工作中会有很多方法和见解. 随着时间的推移,慢慢的写的代码越来越多,封装分方法也越来越多,为的是方便后续工作,加快开发效率! 与此同时,我们会相应的去找一些插件,来代替我们在开发过程中执行 ...

  4. python的深浅拷贝-成为马老师的弟子

    参考链接 骏马金龙 前提 想要了解深浅拷贝之前必须要知道可变和不可变类型,和他们的特性 不可变类型 数字 字符串 元组 不可变集合 特性:改变值,会创建新的内存空间存储数据 可变类型 列表 字典 可变 ...

  5. sql server生成随机id

    SQL Server中生成随机ID的函数是newId(),但是这样生成出来的随机ID是36位带[-]符号的. select newId(); -- 746516E0-95D6-4BAF-8826-6C ...

  6. 2019-11-29-WPF-开启-ScrollViewer-的触摸滚动

    原文:2019-11-29-WPF-开启-ScrollViewer-的触摸滚动 title author date CreateTime categories WPF 开启 ScrollViewer ...

  7. IEEE浮点表示 (原发布 csdn 2018-10-14 10:29:33)

    目录 观察IEEE浮点表示 工作中遇到过整型转浮点型(union那种转换),碰到就看下书,过后就遗忘了.等过段时间又出现此现象,又重新拿起书本,这次记录了过程.然而一直等到今天才写出来,以防以后还用到 ...

  8. 未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序报错的解决办法

    https://www.jb51.net/article/157457.htm 下载32位版本安装即可 Microsoft Access Database Engine Redistributable ...

  9. PIE SDK直方图统计法

    1.算法功能简介 图像直方图描述了图像中每个亮度值DN的像元数量的统计分布.它通过每个亮度值的像元数除以图像中总得像元数,即频率直方图.在很多遥感应用中,直方图是遥感图像中所包含的信息的一种有用的图示 ...

  10. mysql的my.cnf

    配置参数详解 [client] #客户端设置,即客户端默认的连接参数port = 3307   #默认连接端口socket = /data/mysqldata/3307/mysql.sock #用于本 ...