026、163邮箱验证

    xiaoxiao2023-11-21  43

    一、添加邮箱后端逻辑

    1. 添加邮箱接口设计和定义

    1.请求方式

    选项

    方案

    请求方法

    PUT

    请求地址

    /emails/

    2.请求参数

    参数名

    类型

    是否必传

    说明

    email

    string

    邮箱

    3.响应结果:JSON

    字段

    说明

    code

    状态码

    errmsg

    错误信息

    2. 添加邮箱后端逻辑实现

    class EmailView(View): """添加邮箱""" def put(self, request): """实现添加邮箱逻辑""" # 接收参数 json_dict = json.loads(request.body.decode()) email = json_dict.get('email') # 校验参数 if not email: return http.HttpResponseForbidden('缺少email参数') if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email): return http.HttpResponseForbidden('参数email有误') # 赋值email字段 try: request.user.email = email request.user.save() except Exception as e: logger.error(e) return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '添加邮箱失败'}) # 响应添加邮箱结果 return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '添加邮箱成功'})

    3. 判断用户是否登录并返回JSON

    重要提示:

    只有用户登录时才能让其绑定邮箱。此时前后端交互的数据类型是JSON,所以需要判断用户是否登录并返回JSON给用户。

    方案一:

    使用Django用户认证系统提供的is_authenticated()

    class EmailView(View): """添加邮箱""" def put(self, request): """实现添加邮箱逻辑""" # 判断用户是否登录并返回JSON if not request.user.is_authenticated(): return http.JsonResponse({'code': RETCODE.SESSIONERR, 'errmsg': '用户未登录'}) pass

    方案二:

    自定义返回JSON的login_required装饰器

    在meiduo_mall.utils.views.py中

    def login_required_json(view_func): """ 判断用户是否登录的装饰器,并返回json :param view_func: 被装饰的视图函数 :return: json、view_func """ # 恢复view_func的名字和文档 @wraps(view_func) def wrapper(request, *args, **kwargs): # 如果用户未登录,返回json数据 if not request.user.is_authenticated(): return http.JsonResponse({'code': RETCODE.SESSIONERR, 'errmsg': '用户未登录'}) else: # 如果用户登录,进入到view_func中 return view_func(request, *args, **kwargs) return wrapper class LoginRequiredJSONMixin(object): """验证用户是否登陆并返回json的扩展类""" @classmethod def as_view(cls, **initkwargs): view = super().as_view(**initkwargs) return login_required_json(view)

    LoginRequiredJSONMixin的使用

    class EmailView(LoginRequiredJSONMixin, View): """添加邮箱""" def put(self, request): """实现添加邮箱逻辑""" # 判断用户是否登录并返回JSON pass

    二、Django发送邮件的配置

    1. Django发送邮件流程分析

    send_mall()方法介绍

    位置: 在django.core.mail模块提供了send_mail()来发送邮件。 方法参数: send_mail(subject, message, from_email, recipient_list, html_message=None) # subject 邮件标题 # message 普通邮件正文,普通字符串 # from_email 发件人 # recipient_list 收件人列表 # html_message 多媒体邮件正文,可以是html字符串

    2. 准备发邮件服务器

    1.点击进入《设置》界面

    2.点击进入《客户端授权密码》界面

    3.开启《授权码》,并完成验证短信

    4.填写《授权码》

    5.完成《授权码》设置

    6.配置邮件服务器

    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' # 指定邮件后端 EMAIL_HOST = 'smtp.163.com' # 发邮件主机 EMAIL_PORT = 25 # 发邮件端口 EMAIL_HOST_USER = 'itcast99@163.com' # 授权的邮箱 EMAIL_HOST_PASSWORD = 'python99' # 邮箱授权时获得的密码,非注册登录密码 EMAIL_FROM = '商城<itcast99@163.com>' # 发件人抬头

    三、发送邮箱验证邮件

    重要提示:

    发送邮箱验证邮件是耗时的操作,不能阻塞商城的响应,所以需要异步发送邮件。我们继续使用Celery实现异步任务。

    1. 定义和调用发送邮件异步任务

    1.定义发送邮件任务

    @celery_app.task(bind=True, name='send_verify_email', retry_backoff=3) def send_verify_email(self, to_email, verify_url): """ 发送验证邮箱邮件 :param to_email: 收件人邮箱 :param verify_url: 验证链接 :return: None """ subject = "商城邮箱验证" html_message = '<p>尊敬的用户您好!</p>' \ '<p>感谢您使用商城。</p>' \ '<p>您的邮箱为:%s 。请点击此链接激活您的邮箱:</p>' \ '<p><a href="%s">%s<a></p>' % (to_email, verify_url, verify_url) try: send_mail(subject, "", settings.EMAIL_FROM, [to_email], html_message=html_message) except Exception as e: logger.error(e) # 有异常自动重试三次 raise self.retry(exc=e, max_retries=3)

    2.注册发邮件的任务:main.py

    在发送邮件的异步任务中,我们用到了Django的配置文件。所以我们需要修改celery的启动文件main.py。在其中指明celery可以读取的Django配置文件。最后记得注册新添加的email的任务 # celery启动文件 from celery import Celery # 为celery使用django配置文件进行设置 import os if not os.getenv('DJANGO_SETTINGS_MODULE'): os.environ['DJANGO_SETTINGS_MODULE'] = 'meiduo_mall.settings.dev' # 创建celery实例 celery_app = Celery('meiduo') # 加载celery配置 celery_app.config_from_object('celery_tasks.config') # 自动注册celery任务 celery_app.autodiscover_tasks(['celery_tasks.sms', 'celery_tasks.email'])

    3.调用发送邮件异步任务

    # 赋值email字段 try: request.user.email = email request.user.save() except Exception as e: logger.error(e) return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '添加邮箱失败'}) # 异步发送验证邮件 verify_url = '邮件验证链接' send_verify_email.delay(email, verify_url) # 响应添加邮箱结果 return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '添加邮箱成功'})

    4.启动Celery

    $ celery -A celery_tasks.main worker -l info

    2. 生成邮箱验证链接

    1.定义生成邮箱验证链接方法

    def generate_verify_email_url(user): """ 生成邮箱验证链接 :param user: 当前登录用户 :return: verify_url """ serializer = Serializer(settings.SECRET_KEY, expires_in=constants.VERIFY_EMAIL_TOKEN_EXPIRES) data = {'user_id': user.id, 'email': user.email} token = serializer.dumps(data).decode() verify_url = settings.EMAIL_VERIFY_URL + '?token=' + token return verify_url

    2.配置相关参数

    # 邮箱验证链接

    EMAIL_VERIFY_URL = 'http://www.meiduo.site:8000/emails/verification/'

    3.使用邮箱验证链接

    verify_url = generate_verify_email_url(request.user)

    send_verify_email.delay(email, verify_url)

    四、验证邮箱后端逻辑

    1. 验证邮箱接口设计和定义

    1.请求方式

    选项

    方案

    请求方法

    GET

    请求地址

    /emails/verification/

    2.请求参数:查询参数

    参数名

    类型

    是否必传

    说明

    token

    string

    邮箱激活链接

    3.响应结果:HTML

    字段

    说明

    邮箱验证失败

    响应错误提示

    邮箱验证成功

    重定向到用户中心

    2. 验证链接提取用户信息

    def check_verify_email_token(token): """ 验证token并提取user :param token: 用户信息签名后的结果 :return: user, None """ serializer = Serializer(settings.SECRET_KEY, expires_in=constants.VERIFY_EMAIL_TOKEN_EXPIRES) try: data = serializer.loads(token) except BadData: return None else: user_id = data.get('user_id') email = data.get('email') try: user = User.objects.get(id=user_id, email=email) except User.DoesNotExist: return None else: return user

    3. 验证邮箱后端逻辑实现

    验证邮箱的核心:就是将用户的email_active字段设置为True

    class VerifyEmailView(View): """验证邮箱""" def get(self, request): """实现邮箱验证逻辑""" # 接收参数 token = request.GET.get('token') # 校验参数:判断token是否为空和过期,提取user if not token: return http.HttpResponseBadRequest('缺少token') user = check_verify_email_token(token) if not user: return http.HttpResponseForbidden('无效的token') # 修改email_active的值为True try: user.email_active = True user.save() except Exception as e: logger.error(e) return http.HttpResponseServerError('激活邮件失败') # 返回邮箱验证结果 return redirect(reverse('users:info'))

    celery发送验证邮件模板:

    链接:https://pan.baidu.com/s/1tUotBfVDsrBkYYFV53DvVA

    提取码:s8gr

     

    最新回复(0)