我們在某個網站進行開戶時,往往會收到網站發過來的确認郵件,隻有點選确認郵件裡面的連結後,我們所開的賬戶才能生效。本文主要介紹在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='[email protected]',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