带烧瓶邮件的电子邮件验证

时间:2020-08-25 14:54:45

标签: python email flask

我希望使用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

2 个答案:

答案 0 :(得分:0)

解决方案是两阶段初始化,几乎所有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/

答案 1 :(得分:0)

与许多其他扩展一样,安装 mail 后,您需要在 __init__.py 文件中创建一个 flask-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()

上面,我已经导入了我们在 mail 文件中创建的 __init__.py。由于我们使用的是工厂函数,因此我从 Flask 导入 current_app,这将有助于访问应用程序的配置变量。这些变量是完成电子邮件支持所必需的。线程确保在执行电子邮件设置时不会减慢应用程序的速度。

我假设您想向已注册的用户发送电子邮件。因此,在 auth 包中,您需要创建一个辅助方法来将电子邮件发送给用户。

# 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')

这样,当调用 app/templates/email/ 视图函数时,您的电子邮件消息(见 register() 中的模板)将发送给新注册的用户。