Flaskを用いたWebフォーラム開発:ユーザー認証機能の実装

Flask-Mailによるメール送信

設定ファイル config.py:

# メール設定
MAIL_HOST = "smtp.qq.com"
MAIL_PORT = 465
MAIL_TLS = False
MAIL_SSL = True
MAIL_DEBUG = True
MAIL_ACCOUNT = "your@qq.com"
MAIL_AUTH_CODE = "authorization_code"
MAIL_SENDER = "your@qq.com"

メール送信ハンドラ user_controller.py:

@user_bp.route("/send-testmail")
def send_test_email():
    msg = EmailMessage(
        title="テストメール",
        receivers=['recipient@example.com'],
        content="これはテストメールです"
    )
    email_client.send(msg)
    return "メール送信成功"

拡張機能初期化 exts.py:

from flask_mail import Mail

email_client = Mail()

アプリケーション統合 app.py:

from exts import email_client

email_client.init_app(application)

ユーザー登録機能

フォーム検証 forms.py:

from wtforms import Form, StringField, validators
from models import VerificationModel, UserProfile

class SignupForm(Form):
    user_name = StringField(validators=[validators.Length(min=3, max=20)])
    email_addr = StringField(validators=[validators.Email()])
    verification_code = StringField(validators=[validators.Length(min=4, max=4)])
    passphrase = StringField(validators=[validators.Length(min=6, max=20)])
    passphrase_confirm = StringField(validators=[validators.EqualTo("passphrase")])
    
    def validate_verification(self, field):
        code_input = field.data
        email = self.email_addr.data
        verification_record = VerificationModel.fetch_by_email(email)
        if not verification_record or verification_record.code.lower() != code_input.lower():
            raise validators.ValidationError("認証コードが不正です")
    
    def validate_email_addr(self, field):
        email = field.data
        if UserProfile.email_exists(email):
            raise validators.ValidationError("メールアドレスは既に登録されています")

ユーザーコントローラ user_controller.py:

from datetime import datetime
from flask import render_template, request, redirect, jsonify
from werkzeug.security import generate_password_hash
from .forms import SignupForm

@user_bp.route("/signup", methods=['GET', 'POST'])
def signup():
    if request.method == 'GET':
        return render_template("signup.html")
    else:
        form_data = SignupForm(request.form)
        if form_data.validate():
            new_user = UserProfile(
                email=form_data.email_addr.data,
                username=form_data.user_name.data,
                password=generate_password_hash(form_data.passphrase.data)
            )
            db_session.add(new_user)
            db_session.commit()
            return redirect(url_for("user.login"))
        return redirect(url_for("user.signup"))

@user_bp.route("/request-code", methods=['POST'])
def send_verification():
    email_addr = request.form.get("email")
    if not email_addr:
        return jsonify({"status": 400, "message": "メールアドレスが必要です"})
    
    charset = string.ascii_letters + string.digits
    new_code = ''.join(random.choices(charset, k=4))
    
    verification_msg = EmailMessage(
        title="認証コード通知",
        receivers=[email_addr],
        content=f"【フォーラム認証】認証コード: {new_code} (有効期限10分)"
    )
    email_client.send(verification_msg)
    
    VerificationModel.update_or_create(email_addr, new_code)
    return jsonify({"status": 200})

データモデル models.py:

class UserProfile(db.Model):
    __tablename__ = "users"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(100), nullable=False)
    password = db.Column(db.String(200), nullable=False)
    email = db.Column(db.String(100), nullable=False, unique=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class VerificationModel(db.Model):
    __tablename__ = "email_verifications"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    email = db.Column(db.String(100), nullable=False)
    code = db.Column(db.String(4), nullable=False)
    generated_at = db.Column(db.DateTime, default=datetime.utcnow)

タグ: flask ユーザー認証 Flask-Mail werkzeug WTForms

6月19日 18:35 投稿