34、Flask实战第34天:修改邮箱
修改邮箱页面布局
新建cms/cms_resetemail.html
{% extends 'cms/cms_base.html' %} {% block title %}修改邮箱-CMS管理系统{% endblock %} {% block page_title %}个人中心>>>修改邮箱{% endblock %} {% block head %} <style> .form-container{ width: 300px; } </style> {% endblock %} {% block main_content %} <form class="form-container"> <div class="form-group"> <div class="input-group"> <input type="email" class="form-control" placeholder="新的邮箱" name="email"> <div class="input-group-addon" style="cursor: pointer" id="get_captcha">获取验证码</div> </div> </div> <div class="form-group"> <div class="input-group"> <input type="text" class="form-control" placeholder="填写验证码" name="captcha"> </div> </div> <div class="form-group"> <div class="input-group"> <button type="submit" class="btn btn-primary" id="submit">提交修改</button> </div> </div> </form> {% endblock %}
创建一个视图,编辑cms.views.py
... class ResetEmailView(views.MethodView): decorators = [login_required] def get(self): return render_template('cms/cms_resetemail.html') def post(self): pass bp.add_url_rule('resetemail', view_func=ResetEmailView.as_view('resetemail'))
修改cms/cms_base.html中的"修改密码" 链接
<li><a href="{{ url_for('cms.resetemail') }}">修改邮箱</a></li>
完成布局如下
获取验证码
流程:
用户输入 新的邮箱,点击 获取验证码,可以通过get方法使用AJAX发送到后台
后台接收到用户的新的邮箱,生成6位数的随机验证码,通过flask-mail插件发送验证码到该邮箱
把 邮箱作为key,验证码作为value存入memcached中,生存周期为300s(5分钟)
首先来配置flask-mail
安装flask-mail
pip install flask-mail
在exts.py中带falsk-mail
... from flask_mail import Mail mail = Mail()
在主程序bbs.py中,把mail和app绑定
... from exts import mail mail.init_app(app)
在config.py配置邮箱的连接和发送者信息,这里我是用的QQ邮箱
#mail MAIL_SERVER = 'smtp.qq.com' MAIL_PORT = '465' MAIL_USE_SSL = True #使用SSL,端口号为465或587 MAIL_USERNAME = 'sellsa@qq.com' MAIL_PASSWORD = 'xxxxxxxxx' #注意,这里的密码不是邮箱密码,而是授权码 MAIL_DEFAULT_SENDER = 'sellsa@qq.com' #默认发送者
现在来的 cms.views写个视图函数来测试发送邮件
... from exts import mail from flask_mail import Message @bp.route('/test_email/') def test_email(): msg = Message('Flask项目测试邮件', #这是邮件主题 sender='sellsa@qq.com', recipients=['heboan@qq.com'], #发送给谁,这是个列表,可以有多个接收者 body='Hello, 这是一封测试邮件,这是邮件的正文') mail.send(msg) #发送 return 'success'
配置memecahced
因为我们要把验证码 存到 memcached中,所以这里先配置好它。
我在192.168.88.1服务器中安装memcached并且启动它
yum install -y memcached systemctl start memcached #查看端口进程 [root@c1 ~]# netstat -lntp|grep memcached tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 2904/memcached tcp6 0 0 :::11211 :::* LISTEN 2904/memcached
安装python-memecahced插件
pip install python-memcached
我们工具包utils下新建个文件xcache.py对memcached 来封装下
import memcache mc = memcache.Client(["192.168.88.1:11211"], debug=True) def set(key, value, timeout=300): return mc.set(key=key, val=value, time=timeout) def get(key): return mc.get(key) def delete(key): return mc.delete(key)
准备工作做好,我们可以写获取验证码的视图了,编辑cms.views.py
... from exts mail from flask_mail import Message from utils xcache import string, random @bp.route('/email_captcha/') @login_required def email_captcha(): #/cms/emai_capthcha/?email=xxxx@qq.com email = request.args.get('email') if not email: return xjson.json_params_error('请传递邮件参数!') #生成6位数的随机验证码 source = list(string.ascii_letters) source.extend(map(lambda x:str(x), range(0,10))) captcha = ''.join(random.sample(source, 6)) #发送邮件 msg = Message('BBS论坛更换邮箱验证码', recipients=[email], body='您的验证码:{},5分钟内有效'.format(captcha)) try: mail.send(msg) except Exception as err: print(err) return xjson.json_server_error(message='邮件发送失败') #验证码存入memcached xcache.set(email, captcha) return xjson.json_success(message='邮件发送成功')
AJAX请求,创建static/cms/js/resetemail.js
$(function () { $('#get_captcha').click(function (event) { event.preventDefault(); var email = $('input[name=email]').val(); if(!email){ xtalert.alertInfoToast('请输入邮箱'); return; } bbsajax.get({ 'url': '/cms/email_captcha/', 'data': { 'email': email }, 'success': function (data) { if (data['code'] === 200){ xtalert.alertSuccessToast(data['message']); }else{ xtalert.alertInfo(data['message']); } }, 'fail': function (error) { xtalert.alertNetworkError(); } }) }) });
在cms_resetemail.html中引入resetemail.js
{% block head %} ... <script src="{{ url_for('static', filename='cms/js/resetemail.js') }}"></script> {% endblock %}
完成修改邮箱功能
现在就剩下把验证码填上,然后把邮箱和验证码提交到服务器进行验证并做相应的处理,然后返回处理结果到前端就OK了。
需要RestEmailView的post请求,对于用户提交上来的邮箱和验证码,我们需要对它们进行form验证。所以,编辑cms/forms.py,写一个RestEmailForm
... from wtforms.validators import ValidationError from .models import CMSUser from utils import xcache class RestEmailForm(BaseForm): email = StringField(validators=[Email(message='邮箱格式错误'),InputRequired(message='请输入邮箱') ]) captcha = StringField(validators=[Length(min=6, max=6, message='验证码长度错误')]) def validate_email(self, field): user = CMSUser.query.filter_by(email=field.data).first() if user: raise ValidationError('该邮箱已存在') def validate_captcha(self, field): email = self.email.data captcha = field.data captcha_cache = xcache.get(email) #判断memcached中是否有对应的邮箱及验证码,小写进行比较,这样用户可以不区分大小写 if not captcha_cache or captcha.lower() != captcha_cache.lower(): raise ValidationError('邮箱验证码错误')
编辑RestEmailView的post请求
class ResetEmailView(views.MethodView): decorators = [login_required] def get(self): return render_template('cms/cms_resetemail.html') def post(self): resetemail_form = RestEmailForm(request.form) if resetemail_form.validate(): email = resetemail_form.email.data g.cms_user.email = email db.session.commit() return xjson.json_success('邮箱修改成功') else: message = resetemail_form.get_error() return xjson.json_params_error(message)
编辑resetemail.js,再写一个ajax的post请求,当点击"提交修改",就会触发
//提交修改 $(function () { $('#submit').click(function (event) { event.preventDefault(); var emailE = $('input[name=email]'); var captchaE = $('input[name=captcha]'); var email = emailE.val(); var captcha = captchaE.val(); bbsajax.post({ 'url': '/cms/resetemail/', 'data': { 'email': email, 'captcha': captcha }, 'success': function (data) { if (data['code'] === 200){ xtalert.alertSuccessToast(data['message']); emailE.val(''); captchaE.val(''); }else{ xtalert.alertInfo(data['message']); } }, 'fail': function (error) { xtalert.alertNetworkError(); } }) }) });
到此,修改邮箱功能完成