发送邮件
在用户模型中添加是否通过验证邮箱的字段
因为我们的AbstractUser中并未提供是否验证过邮箱的字段,所以我们需要在model中添加一个email_active字段
active_email=models.BooleanField(default=False,verbose_name='activate email')
在添加这条数据后别忘了迁移,否则数据库会报错
添加完成
完成我们发送邮件需要的包和setting配置
配置setting.py字段
由于django自带了邮件发送系统,我们只需要在setting.py文件中添加以下字段注册邮箱
这是QQ邮箱的形式
EMAIL_BACKEND='django.core.mail.backends.smtp.EmailBackend'
EMAIL_USE_SSL = True
# 邮箱服务
EMAIL_HOST = 'smtp.qq.com'
# 端口号
EMAIL_PORT = 465
# 账号
EMAIL_HOST_USER = '921393289@qq.com'
# 授权秘钥 密钥要在QQ邮箱内开启IMAP/SMTP服务会获得
EMAIL_HOST_PASSWORD =''
# 发件人
EMAIL_FROM='<921393289@qq.com>'
添加验证邮箱需要的包
这里我们使用itsdangerous 包加密用户验证邮箱发回给后端
下载itsdangerous包
在终端进入项目所在虚拟环境,键入
pip install itsdangerous
下载itsdangerous包,就直接可以使用
根据逻辑确定视图类和序列化器
这里选用了UpdataAPIView视图和ModelSerializer序列化器,至于为什么使用UpdataAPIView是因为我用户登录以后用户专用的界面都是通过他们浏览器留下的token来进行数据访问的,所以我们需要实时更新这些信息,比如用户的邮箱。其实也就是前端传回了一个PUT请求,只有UpdataAPIView才能接收。
class EmailSendView(UpdateAPIView):
pass
创建视图,补全
class EmailSerializer(serializers.ModelSerializer):
class Meta:
model=models.User
fields = ('id','email')
def validate(self, attrs):
return attrs
指定序列化器使用模型和字段和validate()方法,由于暂时没有涉及到验证,而且只是简单的取值,所以validate()并没有用到,如果要添加邮箱逻辑中其他认证,在这里面可以添加逻辑
from itsdangerous import TimedJSONWebSignatureSerializer as ts
from django.conf import settings
from django.core.mail import send_mail
class EmailSendSerializer(serializers.ModelSerializer):
........
def update(self, instance, validated_data):
# instance是从数据库查询出的对象
instance.email=validated_data['email']
# 这里更新一次email字段数据
instance.save()
# 创建一个isdangerous的对象,传入我们设置中的密钥
idsfy=ts(settings.SECRET_KEY)
print(idsfy)
data={
'user_id' :instance.id,
'username':instance.username,
'email':instance.email,
}
# 生成isdangerous token
token=idsfy.dumps(data).decode()
# 拼接路径
url='http://127.0.0.1:8000/email/vary/?token='+token
# 拼接邮件内容
url_str='<a href='+url+'>click to verify ur email</a>'
print(instance)
email_url=validated_data['email']
print(email_url)
# 发送验证邮件
send_mail(subject='hermit email active', message=url_str, from_email=settings.EMAIL_FROM,
recipient_list=[email_url], html_message=url_str)
return instance
序列化器中实现了我们发送邮件的主要逻辑,现在只要在视图中查询到验证后的用户对象就可以了
class EmailSendView(UpdateAPIView):
serializer_class = serializers.EmailSendSerializer
permission_classes = (IsAuthenticated,)
def get_object(self):
return self.request.user
获取到前端传入的token信息验证后读取用户信息,并通过get_object查询数据库得到用户对象。最后注册一下url就可以了
urlpatterns = [
......
url(r'^email/$',views.EmailSendView.as_view()),
]
前端JWT实现发送
在上一篇的基础上,JS文件中添加
$(function () {
.....
$.ajax({
......
success(data){
........
# 成功加载页面后才会有验证邮箱逻辑
$('#active_button').click(function () {
$.ajax({
url:'http://127.0.0.1:8000/email/',
# 再发送一次带token的put请求
headers:{
'Authorization':'JWT '+token
},
type:'PUT',
拼接后端需要的数据
id1=data.id
email1=data.email
data: {
_method: 'PUT',
id:id1,
email:email1
},
dataType:'json',
发送成功后的返回值
success:function () {
alert('okay')
}
})
})
},
error(data){
..........
},
})
})
验证邮件
点击前端的验证按钮,我们就可以收到一份邮件了,邮件的位置是我们注册时用户的邮箱,发送邮件的邮箱则是我们在setting中使用的邮箱
验证邮件中包含了一个url可以发送一个get请求给后端来修改前面设置的active_email属性。所以这里只需要获取到前端的url字段中token信息查找到用户对象,修改用户对象中的字段就行
如果使用serializer我们可以用updata方法实现,这里我使用APIView并且把所有逻辑都在APIView中实现
from itsdangerous import TimedJSONWebSignatureSerializer as ts
from django.conf import settings
from . import models
from rest_framework.response import Response
class emailvaryView(APIView):
def get(self,request):
# 得到url中的token信息
receive_token = request.query_params.get('token')
print('#############email#########')
print(receive_token)
# 如果没有收到token报错
if not receive_token:
return Response({'err_msg:lack token'},status=401)
# 新建一个isdangerous对象,将密钥传入
ts_obj = ts(settings.SECRET_KEY)
# 用带密钥的isdangerous对象解码传入token,注意两次密钥都是相同的
data=ts_obj.loads(receive_token)
print(data)
# 获取token解码后的信息
user_id=data['user_id']
username= data['username']
email = data['email']
# 用信息获取用户对象
user_obj=models.User.objects.get(id=user_id,username=username,email=email)
print(user_obj)
# 将用户对象中的字段信息修改并保存
user_obj.active_email=True
user_obj.save()
return Response('Okay')
urls文件中注册这个视图
urlpatterns = [
.........
url(r'^email/vary/$',views.emailvaryView.as_view())
]
这里就完成了整个邮箱验证的逻辑了