# 邮箱配置
MAIL_SERVER = "smtp.qq.com"
MAIL_USE_TLS = True
MAIL_PORT = 587
# 你个人的邮箱
MAIL_USERNAME = "[email protected]"
# 刚刚获取到的授权码填在这里
MAIL_PASSWORD = "xxxxxx"
# 你的邮箱名字可以和MAIL_USERNAME一样
MAIL_DEFAULT_SENDER = "[email protected]"
pip install flask-mail
from flask_mail import Message
@bp.route("/mail/test")
def mail_test():
# recipients是接收人,是一个数组可以给多人同时发送邮件
message = Message(subject="菜鸡学安全1111", recipients=['[email protected]'], body="这是一条测试邮件!!!")
mail.send(message)
return "邮件发送成功"
我这里使用蓝图,把其他接口放在auth.py中
auth.py
import random
from flask import Blueprint, render_template, jsonify
from exts import mail, db
from flask_mail import Message
from flask import request
import string
from models import EmailCaptchaModel
# /auth
bp = Blueprint("auth", __name__, url_prefix="/auth")
# 也就是前面已经定义好前缀,/auth/login
@bp.route("/login")
def login():
pass
@bp.route("/register")
def register():
# 验证用户提交的邮箱和验证码是否对应且正确
return render_template("register.html")
# bp.route: 如果没有指定methods参数,默认就是GET请求
@bp.route("/captcha/email")
def get_email_captcha():
# url传参数
# /captcha/[email protected]
email = request.args.get("email")
print(email)
# 6位,数字和字母的组成
source = string.digits*6
captcha = random.sample(source, 6)
# 列表变成字符串
captcha = "".join(captcha) # 965083
print(captcha)
# I/O 操作
message = Message(subject="菜鸡学安全", recipients=[email], body=f"您的验证码是:{captcha}")
mail.send(message)
# 使用数据库存储
email_captcha = EmailCaptchaModel(email=email, captcha=captcha)
db.session.add(email_captcha)
db.session.commit()
# RESTful API,这是一个格式
# {code:200/400/500, message: "xxx", data: {}}
return jsonify({"code":200, "message": "", "data": None})
# memcached 和redis 适合存储验证,这里扩展,这里暂用数据库来存储
@bp.route("/mail/test")
def mail_test():
# message = Message(subject="菜鸡学安全1111", recipients=['[email protected]'], body="你好我是开发,你好,面试邀请,请你及时确认。")
# mail.send(message)
return "邮件发送成功"
class EmailCaptchaModel(db.Model):
__tablename__ = "eamil_captcha"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
email = db.Column(db.String(100), nullable=False)
captcha = db.Column(db.String(100), nullable=False)
from flask import Flask
import config
from exts import db, mail
from models import UserModel
from blueprints.qa import bp as qa_bp
from blueprints.auth import bp as auth_bp
from flask_migrate import Migrate
from models import EmailCaptchaModel
app = Flask(__name__)
app.config.from_object(config)
# 创建app后,再与db 和app绑定
db.init_app(app)
# 初始化mail连接
mail.init_app(app)
migrate = Migrate(app, db)
# blueprint,用来做模块化的
# 蓝图,视图函数模块化,蓝图
# 注册蓝图
app.register_blueprint(qa_bp)
app.register_blueprint(auth_bp)
@app.route('/')
def hello_world(): # put application's code here
return 'Hello World!'
if __name__ == '__main__':
app.run()
register.js
// 绑定按钮操作,整个网页都加载完毕后才会在执行的
function bindEmailcaptchaClick(){
$("#captcha-btn").click(function (event){
//$this 就是点前按钮jequery对象
var $this = $(this);
// 阻止默认动作
event.preventDefault();
var email= $("input[name='email']").val();
$.ajax({
url: "/auth/captcha/email?email="+email,
method: "GET",
success: function (result){
var code = result['code'];
if(code == 200){
var countdown = 60;
//开始倒计时之前,就取消点击事件
$this.off("click");
var timer = setInterval(function (){
$this.text(countdown)
countdown -=1
if(countdown <=0){
//清掉定时器,就不倒计时了
clearInterval(timer)
$this.text("获取验证码");
bindEmailcaptchaClick();
// 重新绑定事件
}
},1000)
alert("邮件发送成功!")
}else{
alert(result['message'])
}
},
fail: function (error){
console.log(error);
}
})
});
}
$(function(){
bindEmailcaptchaClick();
})
{% extends "base.html" %}
{% block title %}菜鸡学安全-注册{% endblock %}
{% block head %}
<script src="{{ url_for('static', filename='jquery/jquery.3.6.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/register.js') }}"></script>
{% endblock %}
{% block body %}
<div class="row mt-4">
<div class="col"></div>
<div class="col">
<form method="POST" action="#">
<div class="form-group">
<label for="exampleInputEmail1">邮箱</label>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" name="email">
<small id="emailHelp" class="form-text text-muted">我们不会把邮箱用于其他用户</small>
</div>
<div class="form-group">
<label for="exampleInputEmail1">验证码</label>
<div class="input-group">
<input type="text" class="form-control" name="captcha">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="captcha-btn">获取验证码</button>
</div>
</div>
</div>
<div class="form-group">
<label for="exampleInputEmail1">用户名</label>
<input type="text" class="form-control" name="username">
</div>
<div class="form-group">
<label for="exampleInputPassword1">密码</label>
<input type="password" class="form-control" id="exampleInputPassword1" name="password">
</div>
<div class="form-group">
<label for="exampleInputPassword1">确认密码</label>
<input type="password" class="form-control" name="password_confirm">
</div>
<button type="submit" class="btn btn-primary btn-block">立即注册</button>
</form>
</div>
<div class="col"></div>
</div>
{% endblock %}
base.html
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{{ url_for('static',filename='/bootstrap/bootstrap.4.6.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static',filename='/css/init.css') }}">
{% block head %}{% endblock %}
<title>{% block title %}{% endblock %}title>
head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="#">菜鸡学安全a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon">span>
button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="/">首页 <span class="sr-only">(current)span>a>
li>
<li class="nav-item">
<a class="nav-link" href="#">发布问答a>
li>
<li class="nav-item ml-2">
<form class="form-inline my-2 my-lg-0" method="GET" action="#">
<input class="form-control mr-sm-2" type="search" placeholder="关键字" aria-label="Search" name="q">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">搜索button>
form>
li>
ul>
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#">登录a>
li>
<li class="nav-item">
<a class="nav-link" href="#">注册a>
li>
ul>
div>
div>
nav>
<div class="container">
{% block body %}{% endblock %}
div>
body>
html>
https://www.bilibili.com/video/BV17r4y1y7jJ