我希望使用flask-mail将电子邮件验证添加到我的web应用程序中,在阅读文档后,我似乎必须使用以下命令创建一个Mail实例:
app = Flask(__name__)
mail = Mail(app)然后导入应用程序和邮件实例。
但是,我当前的代码在一个函数中创建了Flask和Mail实例,如下所示:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config["SECRET_KEY"] = "9OLWxND4o83j4K4iuopO"
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///db.sqlite"
db.init_app(app)
login_manager = LoginManager()
login_manager.login_view = "auth.login"
login_manager.init_app(app)
from .models import User
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint)
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
return app上面的代码在我的__init__.py文件中。我不能将Mail实例导入到我注册用户的其他文件中,因为实际上还没有定义一个用户,它只在一个函数中。基本代码来自本教程:https://www.digitalocean.com/community/tutorials/how-to-add-authentication-to-your-app-with-flask-login,现在我在其中添加了电子邮件验证功能。要运行web应用程序,我在Python REPL中输入db.create_all(app=create_app()),这将创建我的sqlite数据库,并且create_all()函数是唯一被调用的时候。然后我在我的powershell终端中输入Flask run。
发布于 2020-08-25 23:34:21
解决方案是两阶段初始化,几乎所有Flask扩展都支持:
from flask import Flask
from flask_mail import Mail
mail = Mail()
def create_app():
app = Flask(__name__)
...
mail.init_app(app)
...这允许您从另一个模块导入mail。
我最近刚刚实现了电子邮件验证,我遵循了这个旧的,但仍然有效的教程:
http://www.patricksoftwareblog.com/confirming-users-email-address/
发布于 2021-04-21 02:05:58
与许多其他扩展一样,在安装flask-mail之后,您需要在__init__.py文件中创建一个mail对象。使用如下所示的结构,使用蓝图,您可以在flask应用程序中添加电子邮件支持。
project_folder
| --- app.py
| --- config.py
| --- app/
| --- email.py
| --- models.py
| --- __init__.py
| --- main/
| --- __init__.py
| --- routes.py
| --- email.py
| --- auth/
| --- __init__.py
| --- routes.py
| --- templates/
| --- auth/
| --- register.html在应用程序工厂中创建mail对象:
# app/__init.py
from flask import Flask
from flask_mail import Mail
# ...
mail = Mail()
# ...
def create_app():
app = Flask(__name__)
# ...
mail.init_app(app)
# ...创建一个电子邮件模块,该模块将处理应用程序的所有电子邮件支持需求,如下所示:
# app/email.py
from threading import Thread
from flask import current_app
from flask_mail import Message
from app import mail
def send_async_email(app, msg):
with app.app_context():
mail.send(msg)
def send_email(subject, sender, recipients, text_body, html_body):
msg = Message(subject, sender=sender, recipients=recipients)
msg.body = text_body
msg.html = html_body
Thread(target=send_async_email,
args=(current_app._get_current_object(), msg)).start()上面,我已经导入了我们在__init__.py文件中创建的mail。因为我们使用的是工厂函数,所以我从flask导入了current_app,这将有助于访问应用程序的配置变量。这些变量是完成电子邮件支持所必需的。线程化可确保应用程序在执行电子邮件设置时不会变慢。
我假设你想发送一封电子邮件给一个已经注册的用户。因此,在auth包中,您将需要创建一个helper方法来向用户发送电子邮件。
# app/auth/email.py
from flask import render_template, current_app
from app.email import send_email
def send_congrats_email(user):
send_email('[Congrats] You are registered'),
sender=current_app.config['ADMINS'][0],
recipients=[user.email],
text_body=render_template('email/reset_password.txt',
user=user),
html_body=render_template('email/reset_password.html',
user=user)在您的auth/routes.py中,创建一个用于注册的视图函数:
# app/auth/routes.py
from app.auth.email import send_congrats_email
@bp.route('/register', methods=['GET', 'POST'])
def register():
if current_user.is_authenticated:
return redirect(url_for('main.index'))
form = RegistrationForm()
if form.validate_on_submit():
user = User(username=form.username.data, email=form.email.data)
user.set_password(form.password.data)
db.session.add(user)
db.session.commit()
send_congrats_email(user)
flash('Check your email for our congrats message')
return redirect(url_for('auth.login'))
return render_template('auth/register.html', title='Register',
form=form)确保在config模块中设置了电子邮件配置:
import os
from dotenv import load_dotenv
basedir = os.path.abspath(os.path.dirname(__file__))
load_dotenv(basedir, '.env')
class Config(object):
# Database configuration
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL?ssl=require') or \
'sqlite:///' + os.path.join(basedir, 'app.db')
SQLALCHEMY_TRACK_MODIFICATIONS = False
# Form protection
SECRET_KEY = os.environ.get('SECRET_KEY')
# Email configuration
MAIL_SERVER = os.environ.get('MAIL_SERVER')
MAIL_PORT = int(os.environ.get('MAIL_PORT') or 25)
MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS') is not None
MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
ADMINS = os.environ.get('ADMINS')这样,当调用register()视图函数时,您的电子邮件消息(在app/templates/email/中的模板中可以看到)将发送给新注册的用户。
发布于 2022-01-31 21:59:57
我最近遇到了同样的问题,我决定通过为(我的)电子邮件库创建一个Flask扩展来解决它。这个扩展(Flask-Redmail)非常类似于Flask-Mail,但它的功能更丰富,并且依赖于一个经过良好测试和健壮的库,称为Red Mail。
我在这里写下了我是如何做到的:https://flask-redmail.readthedocs.io/en/latest/cookbook.html#verification-email
简而言之,您需要做的是:
为了实现这些,我建议使用:
用于创建唯一tokens
接下来,我将演示如何做到这一点。为您的应用程序创建文件(即app.py):
from flask import Flask
from flask_redmail import RedMail¨
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
email = RedMail()
db = SQLAlchemy()
login_manager = LoginManager()
def create_app():
app = Flask(__name__)
# Configure the sender
app.config["EMAIL_HOST"] = "localhost"
app.config["EMAIL_PORT"] = 587
app.config["EMAIL_USER"] = "me@example.com"
app.config["EMAIL_PASSWORD"] = "<PASSWORD>"
# Set some other relevant configurations
app.config["SECRET_KEY"] = "GUI interface with VBA"
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app_data.db"
email.init_app(app)
db.init_app(app)
login_manager.init_app(app)
# Import and set the blueprints/routes
...创建用户类并将登录名设置为models.py
from app import db, login_manager
from flask_login import UserMixin
@login_manager.user_loader
def load_user(user_id):
return User.query.filter_by(id=user_id).first()
class User(UserMixin, db.Model):
__tablename__ = 'user'
email = db.Column(db.String, primary_key=True)
password = db.Column(db.String, nullable=False)
verified = db.Column(db.Boolean, default=False)然后是路径,例如作为views.py
from flask import request, current_app, abort, render_template, BluePrint
# Import your custom instances and models
from app import email, db
from models import User
auth_page = Blueprint('auth', __name__)
@auth_page.route("/create-user", methods=["GET", "POST"])
def create_user():
if request.method == "GET":
return render_template("create_user.html")
elif request.method == "POST":
# Now we create the user
# Getting form data (what user inputted)
data = request.form.to_dict()
email = data["email"]
password = data["password"]
# Verifying the user does not exist
old_user = User.query.filter_by(id=email).first()
if old_user:
abort(403)
# Encrypt the password here (for example with Bcrypt)
...
# Creating the user
user = User(
email=email,
password=password,
verified=False
)
db.session.add(user)
db.session.commit()
# Create a secure token (string) that identifies the user
token = jwt.encode({"email": email}, current_app.config["SECRET_KEY"])
# Send verification email
email.send(
subject="Verify email",
receivers=email,
html_template="email/verify.html",
body_params={
"token": token
}
)然后我们创建电子邮件正文。默认情况下,Flask-Redmail会从应用程序的Jinja环境中查找HTML模板。只需创建文件templates/email/verify.html即可完成此操作
<h1>Hi,</h1>
<p>
in order to use our services, please click the link below:
<be>
<a href={{ url_for('verify_email', token=token, _external=True) }}>verify email</a>
</p>
<p>If you did not create an account, you may ignore this message.</p>最后,我们创建一个路由来处理验证:
@auth_page.route("/vefify-email/<token>")
def verify_email(token):
data = jwt.decode(token, current_app.config["SECRET_KEY"])
email = data["email"]
user = User.query.filter_by(email=email).first()
user.verified = True
db.session.commit()请注意,您需要在存储User类的位置执行templates/create_user.html和models.py。
一些相关链接:
有关Red Mail的更多信息:
https://stackoverflow.com/questions/63581599
复制相似问题