我们在某个网站进行开户时,往往会收到网站发过来的确认邮件,只有点击确认邮件里面的链接后,我们所开的账户才能生效。本文主要介绍在flask中进行这种确认机制的方法。
一、定义邮件发送的方法send_email
首先,我们在email.py中定义一个发送邮件的方法send_email:
from flask_mail import Message
from app import mail
from flask import render_template
def send_email(to,subject,template,**kwargs):
msg=Message("[TecnologyDreamer]"+subject,sender='879651072@qq.com',recipients=[to])
msg.body=render_template(template+'.txt',**kwargs)
msg.html=render_template(template+'.html',**kwargs)
mail.send(msg)
send_email接收4个参数,第1个参数是发送邮件的目标地址,第2个参数是邮件主题,第3个参数是模板的名称,第4个参数是一个字典,用来渲染模板。我们在tempates目录下创建mail目录,在mail下创建new_user.html和new_user.txt分别作为邮件的文本和html模板。new_user.htm和new_user.txt模板的内容如下:
Welcome {{ user.username }}!
Click {{ url_for('main.confirm',token=token,_external=True)}} to confirm.
二、在User模型中定义生成令牌和验证令牌的方法
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
class User(db.Model,UserMixin):
__tablename__='users'
......
confirmed=db.Column(db.Boolean,default=False)
def generate_token(self,expiration=3600):
s=Serializer('secret key',expiration)
return s.dumps({'confirm':self.id})
def confirm(self,token):
s=Serializer('secret key')
data=s.loads(token)
if data.get('confirm')!=self.id:
return False
self.confirm = True
db.session.add(self)
return True
我们在User模型中增加了一个confirmed字段,用来表示用户是否得到了确认。generate_token方法用来产生令牌,Serializer是我们从itsdangerours引入的序列化的对象,它的第一个参数是加密的秘钥,我们这里设置成了字符串'secret key',第二个参数是要加密的字段。它返回序列化对象的一个方法dumps的执行结果,将由confirm和id组成的字典序列化成一个令牌。confirm方法用来验证令牌的有效性,它调用序列化对象的loads方法,将令牌还原成加密之前的字典对象,最后得到里面的id值和user的id进行比较。
三、定义发送邮件的视图函数
我们在上一文的注册视图函数register基础之上进行修改:
@main.route('/register',methods=['GET','POST'])
def register():
form=RegisterForm()
if form.validate_on_submit():
user=User(username=form.name.data,password=form.password1.data)
db.session.add(user)
db.session.commit()
token=user.generate_token()
send_email(form.email.data,'Confirm Account','mail/new_user',user=user,token=token)
return render_template('register.html',form=form)
这里面我们在创建一个user之后,要手动调用db.session.commit进行提交,因为后面我们需要调用方法user.generate_token(),这个方法需要用到user的id字段,而id只有我们将user存入数据库后才会生成。
四、定义确认路由
最后一步是定义确认路由,即用户在其邮件中点击的url,这个url含有令牌,而对应的路由中这个令牌被做成了变量,被传给视图函数。我们在该视图函数中调用user的confirm方法进行确认,是否和current_user的id一致。
@main.route('/confirm/<token>')
@login_required
def confirm(token):
if not current_user.confirmed:
if current_user.confirm(token):
flash('Confirm succeed')
else:
flash('Confirm fail')
return redirect(url_for('main.register'))
现在,输入http://localhost:5000/register,并点击注册按钮之后,就会给注册的邮箱发一封确认邮件,如下所示:
点解连接就完成了注册。
Github位置:
https://github.com/HymanLiuTS/flaskTs
克隆本项目:
Git clone Git @github.com:HymanLiuTS/flaskTs.Git
获取本文源代码:
git checkout FL33
https://github.com/HymanLiuTS/flaskTs
克隆本项目:
Git clone Git @github.com:HymanLiuTS/flaskTs.Git
获取本文源代码:
git checkout FL33