通过flask-mail来发送邮件验证码和验证以及通过Celery来进行异步处理发送邮件的相关步骤
ps:本文章仅涉及基本的邮件的发送和验证码的缓存,不涉及前端及其他内容
一、通过flask-mail来发送邮件
1.1 在终端安装flask-mail包`
在pycharm的终端输入一下命令:
pip install flask-mail
1.2 配置邮件服务器
在Flask应用程序的配置文件中配置邮件服务器的相关信息,如SMTP服务器地址、端口号、用户名、密码等。这些信息将用于建立与邮件服务器的连接。
# 邮箱配置
MAIL_SERVER = "smtp.qq.com"
# 使用SSL加密协议来发送邮件
MAIL_USE_SSL = True
# 所用服务器的端口号,默认为465
MAIL_PORT = 465
# 发件人的用户名
MAIL_USERNAME = "xx.qq.com"
# 开启smtp服务时生成的授权码
MAIL_PASSWORD = "xx"
# 设置默认发件人
MAIL_DEFAULT_SENDER = "xx.qq.com"
然后将邮箱配置导入到app里(我将上述的邮箱配置全部保存到名为config.py的文件中了,后续的缓存配置以及celery配置也都保存在了这个文件中)
import config
# 绑定配置文件
app.config.from_object(config)
ps:我是通过qq邮箱来发送邮件的,因此MAIL_SERVER上写的是smtp.qq.com,如果用的是其他邮箱,需要将后面的服务器进行改变。
注意:由于密码是敏感信息,通常不建议在代码中明文存储密码,而是应该使用一些安全的方式来存储和处理密码,因此不建议将自己的邮箱密码暴露。以qq邮箱为例,可以将密码改为授权验证码,以此来保护账号安全。
打开qq邮箱,在设置中找到上图位置,开启服务,进入管理服务页面
点击生成授权码,将授权码输入到MAIL_PASSWORD里,flask-mail的基本配置就算完成。
1.3 发送邮件
1.3.1 创建Flask-Mail实例
发送邮件首先要创建一个flask-mail对象,在config.py中创建一个mail对象(也可以在其他文件中创建)
from flask_mail import Mail
mail = Mail()
在app.py中对mail进行初始化
from config import mail
mail.init_app(app)
初始化完成后,便可以进行发送邮件了
1.3.2 发送邮件
from flask_mail import Message
from config import mail
...
@bp.route("/captcha/email",methods=['GET','POST'])
def get_email_captcha():
message = Message(subject="主题",recipients=['目标获取地址'],body="邮件内容")
mail.send(message)
return "success"
通过上述代码,初步实现了邮件的发送,接下来再把生成随机四位数的验证码,以及从前端获取到邮箱地址加上去。
...
from flask import Blueprint, render_template, request
from flask_mail import Message
from config import mail
import random
...
@bp.route("/captcha/email",methods=['GET','POST'])
def get_email_captcha():
# 从前端获取目标邮箱地址
email = request.args.get("email")
# 生成四位数的随机验证码
source = string.digits*4
# 将验证码转换为字符串的形式
captcha = random.sample(source, 4)
captcha = "".join(captcha)
subject = "主题"
body = f"您的验证码为{captcha}"
message = Message(subject=subject,recipients=[email],body=body)
mail.send(message)
return "success"
二、缓存验证码
邮件的发送已经完成,但是无法将生成的验证码与邮箱进行一一对应的关心,将来在处理验证用户输入验证码是否正确时,无法进行验证,又由于验证码并不是特别重要,因此可以通过缓存来临时储存邮箱和验证码。我所会的缓存方法有两种,一种是通过建立一个数据库来进行缓存验证码,另一种是通过redis来缓存验证码。如果仅需要简单的发送验证码而不考虑效率的话,推荐使用建立一个数据库来解决,比起redis要简单很多。如果考虑效率以及接下来要用celery来进行异步处理的话,推荐使用redis。
两种方法都需要安装flask-caching来进行缓存验证码。
2.1 安装及创建cache实例
在终端输入以下命令:
pip install flask-caching
安装完成后要创建cache实例,与flask-mail相类似,在config.py中创建一个cache对象
from flask_mail import Mail
from flask_caching import Cache
mail = Mail()
cache = Cache()
然后在app.py中对cache进行初始化
from config import mail, cache
mail.init_app(app)
cache.init_app(app)
2.2 通过建立数据库来缓存验证码
2.2.1 建立数据库表
# 以下内容在终端输入来将创建数据库表
# flask db init 只需要执行一次
# flask db migrate 将orm模型生成迁移脚本
# flask db upgrade 将迁移脚本映射到数据库中
class EmailCaptchaModel(db.Model):
__tablename__ = 'email_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)
在自己创建的数据库中添加上面的表(我用的是flask-sqlachemy,如果使用其他方法连接数据库,请参考其他帖子来创建表以及进行下面操作)
2.1.2 验证码生成并发送完成后进行储存
from flask import Blueprint, render_template, request
from flask_mail import Message
from config import mail, cache
import random
...
@bp.route("/captcha/email",methods=['GET','POST'])
def get_email_captcha():
# 从前端获取目标邮箱地址
email = request.args.get("email")
# 生成四位数的随机验证码
source = string.digits*4
# 将验证码转换为字符串的形式
captcha = random.sample(source, 4)
captcha = "".join(captcha)
subject = "主题"
body = f"您的验证码为{captcha}"
message = Message(subject=subject,recipients=[email],body=body)
mail.send(message)
# 缓存验证码
cache.set(email, captcha, timeout=100)
# 将验证码存到数据库中
email_captcha = EmailCaptchaModel(email=email, captcha=captcha)
db.session.add(email_captcha)
db.session.commit()
return "success"
至此通过建立数据库表来缓存数据库已经完成
2.3 通过redis来缓存验证码
2.3.1 下载及安装redis
在pycharm上下载redis包
pip install redis
ps:如果要使用celery,最好在redis官网下载并配置好环境变量,不然不能使用celery的命令,也可以在pycharm的终端配置环境变量,可以参考其他帖子进行配置。
2.3.2 配置flask-caching缓存信息
在自己配置邮件服务器的地方配置flask-caching的缓存信息
# 缓存配置
CACHE_TYPE = "RedisCache"
# Redis服务器的主机名
CACHE_REDIS_HOST = "127.0.0.1"
# Redis服务器的端口号
CACHE_REDIS_PORT = 6379
配置好后就可以通过redis来缓存信息了
2.3.3 验证码生成并发送完成后进行储存
和通过建立数据库表的代码基本相同,少了的仅仅是将邮箱和验证码添加到数据库中的步骤:
from flask import Blueprint, render_template, request
from flask_mail import Message
from config import mail, cache
import random
...
@bp.route("/captcha/email",methods=['GET','POST'])
def get_email_captcha():
# 从前端获取目标邮箱地址
email = request.args.get("email")
# 生成四位数的随机验证码
source = string.digits*4
# 将验证码转换为字符串的形式
captcha = random.sample(source, 4)
captcha = "".join(captcha)
subject = "主题"
body = f"您的验证码为{captcha}"
message = Message(subject=subject,recipients=[email],body=body)
mail.send(message)
# 缓存验证码
cache.set(email, captcha, timeout=100)
return "success"
三、验证验证码
...
from flask import Blueprint, render_template, request
from config import cache, mail
...
@bp.route("/register", methods=['GET', 'POST'])
def register():
if request.method == 'GET':
return render_template("register_model.html")
else:
email = request.args.get("email")
captcha = request.args.get("captcha")
cache_captcha = cache.get(email)
if captcha != cache_captcha or not cache_captcha:
return "fail"
return "success"
以上便是简单的发送验证码及其验证
四、通过Celery来异步处理发送邮件
当多个用户同时发送邮件时,如果使用同步的方式进行邮件发送,那么每个邮件发送操作都需要等待前一个邮件发送完成后才能进行,这样就容易引起卡顿和延迟,因此可以通过Celery来进行异步处理。Celery是一个分布式任务队列框架,用于在异步任务处理中实现任务的调度和分发。它可以帮助你将耗时的任务放入队列中异步执行,从而提高应用程序的性能和响应速度。使用Celery可以将邮件发送任务放入任务队列中异步执行,而不是阻塞主线程。主线程可以继续处理其他请求,而邮件发送任务则在后台异步执行。这样可以提高应用程序的性能和响应速度。
4.1 安装Celery
pip install celery
4.2 配置Celery的信息
# Celery配置
# Celery任务队列的消息代理(如Redis)
CELERY_BROKER_URL = "redis://127.0.0.1:6379"
# Celery任务结果的存储后端(如Redis)
CELERY_RESULT_BACKEND = "redis://127.0.0.1:6379"
CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True
4.3 定义邮件发送任务
在项目中新建一个python文件,用来定义邮件发送任务,并输入以下代码
from flask_mail import Message
from config import mail
from celery import Celery
# 定义发送任务
def send_mail(recipient, subject, body):
message = Message(subject=subject, recipients=[recipient], body=body)
mail.send(message)
print("发送成功")
# 创建和配置Celery实例的函数
def make_celery(app):
celery = Celery(app.import_name, backend=app.config['CELERY_RESULT_BACKEND'], broker=app.config['CELERY_BROKER_URL'])
TaskBase = celery.Task
class ContextTask(TaskBase):
abstract = True
def __call__(self, *args, **kwargs):
with app.app_context():
return TaskBase.__call__(self, *args, **kwargs)
celery.Task = ContextTask
app.celery = celery
celery.task(name="send_mail")(send_mail)
return celery
4.3 创建make_celery对象
...
from my_celery import make_celery
...
# 构建celery
celery = make_celery(app)
4.4 将发送邮件改为Celery形式
from flask import Blueprint, render_template, request, current_app
from flask_mail import Message
from config import mail, cache
import random
...
@bp.route("/captcha/email",methods=['GET','POST'])
def get_email_captcha():
# 从前端获取目标邮箱地址
email = request.args.get("email")
# 生成四位数的随机验证码
source = string.digits*4
# 将验证码转换为字符串的形式
captcha = random.sample(source, 4)
captcha = "".join(captcha)
subject = "主题"
body = f"您的验证码为{captcha}"
# 通过celery来发送邮件
current_app.celery.send_task("send_mail", (email, subject, body))
# 缓存验证码
cache.set(email, captcha, timeout=100)
return "success"
4.5 运行Celery命令
要想运行Celery,需要下载一个第三方库
pip install gevent
安装完后运行并且在终端输入以下命令,便可以使用Celery:
celery -A app.celery worker -P gevent -l info
显示上图信息便表明连接完成。
ps:每次启动时都需要运行上述命令。