본문 바로가기
BIG DATA/PYTHON

[PYTHON] Flask에서 이메일 인증 구현하기

by 라일리T 2025. 3. 4.

Flask에서 이메일 인증 구현하기

이전 글에서는 Flask에서 파일 업로드 기능을 이용해 프로필 사진을 추가하는 방법을 배웠습니다.
이번 글에서는 회원가입 시 이메일 인증 기능을 구현하는 방법을 알아보겠습니다.

Flask-Mail을 이용한 이메일 발송
이메일 인증 링크 생성
사용자가 이메일을 확인하고 계정을 활성화하는 과정 구현

 

 

[PYTHON] Flask에서 파일 업로드 및 프로필 사진 등록하기

Flask에서 파일 업로드 및 프로필 사진 등록하기이전 글에서는 사용자 프로필 페이지를 만들어보았습니다.이번 글에서는 Flask를 활용하여 파일 업로드 기능을 구현하고,사용자의 프로필 사진을

englishforkid.tistory.com

 


1. Flask-Mail 설치 및 설정

이메일을 보내기 위해 Flask-Mail 라이브러리를 사용합니다.

📌 Flask-Mail 설치

pip install flask-mail

📌 이메일 설정 (config.py)

MAIL_SERVER = "smtp.gmail.com"
MAIL_PORT = 587
MAIL_USE_TLS = True
MAIL_USERNAME = "your_email@gmail.com"  # 본인의 이메일 주소
MAIL_PASSWORD = "your_app_password"  # 앱 비밀번호
MAIL_DEFAULT_SENDER = "your_email@gmail.com"

✅ MAIL_SERVER → Gmail SMTP 서버 주소
✅ MAIL_PORT → TLS(보안 연결) 사용 시 587 포트
✅ MAIL_USERNAME / MAIL_PASSWORD → 본인의 Gmail 계정 사용
앱 비밀번호 생성 필요 (2단계 인증 활성화 시)

📌 구글 앱 비밀번호 생성 방법

  1. Google 계정 보안 설정으로 이동
  2. "2단계 인증"을 활성화
  3. "앱 비밀번호" 생성 후 복사하여 MAIL_PASSWORD에 입력

2. 이메일 인증 토큰 생성

📌 이메일 인증을 위한 토큰 생성 (utils.py)

from itsdangerous import URLSafeTimedSerializer
from flask import current_app

def generate_token(email):
    serializer = URLSafeTimedSerializer(current_app.config["SECRET_KEY"])
    return serializer.dumps(email, salt="email-confirmation")

def confirm_token(token, expiration=3600):
    serializer = URLSafeTimedSerializer(current_app.config["SECRET_KEY"])
    try:
        email = serializer.loads(token, salt="email-confirmation", max_age=expiration)
    except:
        return False
    return email

✅ generate_token(email) → 이메일을 토큰으로 변환
✅ confirm_token(token, expiration=3600) → 토큰을 해독 (1시간 내 유효)


3. 이메일 인증 링크 발송

📌 이메일 전송 함수 (mail_utils.py)

from flask_mail import Message
from flask import url_for
from app import mail

def send_verification_email(email):
    token = generate_token(email)
    confirm_url = url_for("confirm_email", token=token, _external=True)
    msg = Message("이메일 인증 요청", recipients=[email])
    msg.body = f"다음 링크를 클릭하여 이메일을 인증하세요: {confirm_url}"
    mail.send(msg)

✅ url_for("confirm_email", token=token, _external=True) → 이메일 인증 링크 생성
✅ msg.body → 이메일 본문에 인증 링크 포함


4. 회원가입 시 이메일 인증 요청

📌 회원가입 시 이메일 인증 추가 (app.py)

from flask_mail import Mail
from flask import Flask, request, redirect, url_for, render_template, flash
import sqlite3

app = Flask(__name__)
app.config.from_pyfile("config.py")
mail = Mail(app)

@app.route("/register", methods=["GET", "POST"])
def register():
    if request.method == "POST":
        username = request.form["username"]
        email = request.form["email"]
        password = request.form["password"]

        conn = sqlite3.connect("users.db")
        cursor = conn.cursor()
        cursor.execute("INSERT INTO users (username, email, password, verified) VALUES (?, ?, ?, 0)", 
                       (username, email, password))
        conn.commit()
        conn.close()

        send_verification_email(email)
        flash("이메일 인증을 완료해야 로그인할 수 있습니다.")
        return redirect(url_for("login"))

    return render_template("register.html")

✅ 회원가입 시 verified = 0 (인증되지 않은 상태)
✅ 이메일을 발송하여 인증 요청


5. 이메일 인증 확인

📌 이메일 인증 처리 (app.py)

@app.route("/confirm/<token>")
def confirm_email(token):
    email = confirm_token(token)
    if not email:
        flash("인증 링크가 만료되었습니다.")
        return redirect(url_for("login"))

    conn = sqlite3.connect("users.db")
    cursor = conn.cursor()
    cursor.execute("UPDATE users SET verified = 1 WHERE email = ?", (email,))
    conn.commit()
    conn.close()

    flash("이메일 인증이 완료되었습니다! 이제 로그인할 수 있습니다.")
    return redirect(url_for("login"))

✅ 토큰 검증 후 verified = 1로 변경
✅ 만료된 링크는 다시 인증 요청하도록 처리


6. 로그인 시 인증 여부 확인

📌 로그인 시 이메일 인증 체크 (app.py)

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        email = request.form["email"]
        password = request.form["password"]

        conn = sqlite3.connect("users.db")
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM users WHERE email = ? AND password = ?", (email, password))
        user = cursor.fetchone()
        conn.close()

        if user:
            if user["verified"]:
                session["user"] = user["username"]
                return redirect(url_for("profile"))
            else:
                flash("이메일 인증을 완료해야 합니다.")
                return redirect(url_for("login"))
        else:
            flash("로그인 정보가 올바르지 않습니다.")
    
    return render_template("login.html")

✅ user["verified"] 값이 1이 아닐 경우 로그인 불가
✅ 이메일 인증이 완료된 사용자만 로그인 가능


7. 데이터베이스에 인증 상태 추가

📌 users 테이블에 이메일 인증 컬럼 추가 (update_db.py)

conn = sqlite3.connect("users.db")
cursor = conn.cursor()

cursor.execute("""
    ALTER TABLE users ADD COLUMN verified INTEGER DEFAULT 0;
""")

conn.commit()
conn.close()

위 코드를 실행하여 verified 컬럼을 추가합니다.

python update_db.py

✅ verified = 0 → 이메일 인증 전
✅ verified = 1 → 이메일 인증 완료


8. 결론

이번 글에서는 Flask에서 이메일 인증을 구현하는 방법을 배웠습니다.

Flask-Mail을 이용한 이메일 발송
토큰을 활용한 이메일 인증 링크 생성
사용자가 이메일을 확인하고 계정을 활성화하는 과정 구현

다음 글에서는 Flask에서 JWT(JSON Web Token)를 활용한 로그인 유지 방법을 배워보겠습니다! 🚀

 

 

 

[PYTHON] Flask를 이용한 간단한 웹 애플리케이션 만들기

Flask를 이용한 간단한 웹 애플리케이션 만들기 이전 글에서는 자동 이메일 발송 기능을 구현해 보았습니다.이제 Python을 활용하여 간단한 웹 애플리케이션을 만들어 보겠습니다.웹 애플리케이

englishforkid.tistory.com

 

 

[PYTHON] Flask로 로그인 기능 구현하기 (세션 활용)

Flask로 로그인 기능 구현하기 (세션 활용)이전 글에서는 Flask를 활용한 웹 애플리케이션 개발 및 데이터베이스 연동을 배웠습니다.이번 글에서는 사용자 로그인 기능을 구현해 보겠습니다.로그

englishforkid.tistory.com