valine评论触发邮件通知
之前总结了在Hugo中如何加入valine来实现第三方评论插件,可以回顾《Hugo中加入Valine评论功能》,但希望Hugo上有评论时能够有一个通知的机制,这里就以邮件通知为例,基于之前介绍的Valine评论功能,进一步介绍如何实现Valine的评论通知。
总体思路是基于LeanCloud提供的API,来获取Valine存储的comments信息,通过计算获取最新的comments,然后发送通知。其实通知可以用任何方式,这里用比较简单的发送邮件来举例。
LeanCloud上绑定域名
因为要使用LeanCloud的API,基于LeanCloud的要求,必须绑定一个自己的域名。所以需要几个步骤
- 在LeanCloud账户上的 设置=>域名绑定 中的API访问域名,按照设置步骤设置一个二级域名,比如可以是Hugo网站域名的二级域名;
- 在DNS解析上增加一个CNAME配置(会提示如何配置);
- 等待一段时间。需要经过域名配置检查、备案审核、SSL分配的过程,最后变成已绑定的状态;

使用LeanCloud的SDK访问API
这里以Python的SDK举例,参考https://leancloud.cn/docs/sdk_setup-python.html。除了Python之外,也有很多其它编程语言的SDK可以使用,这里使用Python主要是考虑简单。
可以创建Python的virtualenv来管理后续的Python代码,也可以直接在全局环境下操作,但是建议使用virtualenv管理代码和运行。
安装Python的SDK库
pip install leancloud
安装Python的pytz库,主要是比较datetime时间,由于LeanCloud返回的datetime数据包含timezone,所以需要做一个转换,用到pytz库
pip install pytz
核心代码
import leancloud
from datetime import datetime
import pytz
## 这里用一个本地的文件保存上次最后获取的comment的时间戳
def get_pos_from_file():
with open("./comment_pos.txt", "r") as f:
line = f.readline()
## 文件中的第一行,可以手动收入:2020-10-01 12:00:01这种
## 但是由于LeanCloud获取的comment时间数据是包含市区的,所以为了后面比较大小,这里也转换成有时间戳的datetime
pos = datetime.strptime(line, "%Y-%m-%d %H:%M:%S").replace(tzinfo=pytz.timezone('UTC'))
f.close()
return pos
## 处理完之后更新时间戳
def set_pos_to_file(pos):
with open("./comment_pos.txt", "w+") as f:
pos = pos.strftime("%Y-%m-%d %H:%M:%S")
f.write(pos)
f.close()
## 获取最新的comments
def get_new_comments(update_time):
leancloud.init("{你的LeanCloud账户的中APPID}", "{你的LeanCloud账户的中APP KEY}")
## 这里comments是配置放在LeanCloud的Comment结构中
Comment = leancloud.Object.extend('Comment')
query = Comment.query
## 查询大于某个时间的所有comments
query.greater_than('updatedAt', update_time)
items = query.find()
return items
if __name__ == '__main__':
tm = get_pos_from_file()
comments = {}
new_pos = tm
ret_leancloud = get_new_comments(tm)
## 如果没有新的comments,则不做处理
if len(ret_leancloud) == 0:
exit(0)
for comment in ret_leancloud:
url = comment.get('url')
content = comment.get('comment')
updateTm = comment.get('updatedAt')
if updateTm > new_pos:
new_pos = updateTm
if url in comments:
comments[url].append(content)
else:
comments[url] = [content]
### 这里SendEmail,是自己实现发邮件,拼装邮件内容,这行代码不能直接copy,只是一个sample
### SendEmail(comments)
set_pos_to_file(new_pos)
这段代码可以放在crontab中运行,即可完成定期查找最新comments并邮件通知的功能。
Python发送邮件
这里简单提一下发邮件,以使用163的smtp服务为例子(其它比如qq也都一样)。
首先先要获取一个邮箱账户的授权码,基本上现在主流邮箱都有,在开启smtp功能时,获取授权码,这个适用于smtp服务的登录,避免直接使用邮箱帐号和密码。
# coding: utf-8
import smtplib
from email.mime.text import MIMEText
class SmtpEmail:
def __init__(self):
self.host = 'smtp.163.com'
self.port = 465
self.username = '{你的邮箱帐号}'
self.password = '{你的授权码}'
self.sender = '{你的邮箱帐号}' ## 邮件的发送人,一般要求跟username一样,否则会报错
self.smtp = None
self.isLogin = False
def login(self):
self.smtp = smtplib.SMTP_SSL(self.host, self.port)
self.smtp.login(self.username, self.password)
self.isLogin = True
def sendEmail(self, receivers, title, content):
if not self.isLogin:
self.login()
## 这里使用html格式,即content可以是一段html代码。也可以用plain格式
message = MIMEText(content, 'html', 'utf-8')
message['Subject'] = title
message['From'] = self.sender
message['To'] = ",".join(receivers)
self.smtp.sendmail(self.sender, receivers, message.as_string())
if __name__ == '__main__':
smtp = SmtpEmail()
smtp.sendEmail()