はじめに
本記事では、FastAPIを使用して、PostgreSQLにユーザー情報を保存し、**AWS SES(Simple Email Service)**を利用して招待メールを送信するシステムを構築する方法を解説します。システム設計から実装までを丁寧に説明し、初心者にも理解できるように構成しています。
必要な環境の準備
使用する技術スタック | 説明 |
---|---|
FastAPI | Pythonで書かれたWebフレームワーク。非同期処理に強く、軽量で高性能。 |
PostgreSQL | 信頼性の高いオープンソースのリレーショナルデータベース。 |
AWS SES | メール送信サービス。大規模なメール送信に対応。 |
必要なパッケージ
まず、必要なパッケージをインストールします。
pip install fastapi uvicorn psycopg2 sqlalchemy boto3
使用する技術スタック | 説明 |
---|---|
FastAPI | APIの作成に使用。 |
uvicorn | ASGIサーバー。FastAPIを起動するために必要。 |
psycopg2 | PostgreSQLとPythonを接続するためのライブラリ。 |
SQLAlchemy | ORM(Object Relational Mapper)としてデータベースとやり取り。 |
boto3 | AWSサービス(SES)を操作するためのライブラリ。 |
PostgreSQLのセットアップ
PostgreSQLは事前にインストールしておく必要があります。以下のコマンドでデータベースを作成します。
CREATE DATABASE user_registration;
データベース設計(PostgreSQL)
ユーザー情報と招待トークンを管理するために、2つのテーブルを設計します。
ユーザーテーブル(users)
カラム名 | データ型 | 説明 |
---|---|---|
id | INTEGER | ユーザーの一意のID(主キー)。 |
VARCHAR(255) | ユーザーのメールアドレス(ユニーク)。 | |
name | VARCHAR(255) | ユーザー名。 |
is_active | BOOLEAN | アクティブかどうかを示すフラグ(招待を受けた後に有効化)。 |
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(255),
is_active BOOLEAN DEFAULT FALSE
);
招待トークンテーブル(invitation_tokens)
カラム名 | データ型 | 説明 |
---|---|---|
id | INTEGER | トークンの一意のID(主キー)。 |
VARCHAR(255) | 招待されたメールアドレス。 | |
token | VARCHAR(255) | 招待トークン。 |
is_used | BOOLEAN | トークンが使用済みかどうかを示すフラグ。 |
CREATE TABLE invitation_tokens (
id SERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL,
token VARCHAR(255) NOT NULL,
is_used BOOLEAN DEFAULT FALSE
);
データベース接続設定
まずはSQLAlchemyを使ってデータベース接続を設定します。
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base
DATABASE_URL = "postgresql://user:password@localhost/user_registration"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
ユーザーモデルとトークンモデル
SQLAlchemyでテーブルモデルを定義します。
from sqlalchemy import Column, Integer, String, Boolean
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True, index=True)
email = Column(String, unique=True, index=True)
name = Column(String)
is_active = Column(Boolean, default=False)
class InvitationToken(Base):
__tablename__ = 'invitation_tokens'
id = Column(Integer, primary_key=True, index=True)
email = Column(String)
token = Column(String)
is_used = Column(Boolean, default=False)
FastAPIのルート設計
APIは以下の2つに分離します。
- 招待メール送信API: ユーザーのメールアドレスを受け取り、AWS SESを使って招待メールを送信する
- ユーザー登録API: 招待メールのリンクに含まれるトークンを使い、ユーザー登録を完了する
招待メール送信と新規ユーザー登録の流れ
1. 招待メール送信の流れ
このセクションでは、フロントエンドからユーザーのメールアドレスを送信し、バックエンドで処理して招待メールを送信する流れを説明します。
Step 1: フロントエンドからリクエストを送信
- フロントエンド(例:ReactやVue.jsなどのクライアントアプリケーション)で、ユーザーのメールアドレスを収集し、APIエンドポイント
/invite
にPOSTリクエストとして送信します。 - このリクエストには、ユーザーのメールアドレスが含まれます。
Step 2: FastAPIサーバーでトークン生成と保存
- サーバー側で、FastAPIはこのリクエストを受け取ります。
- FastAPIのエンドポイント
/invite
は、受け取ったメールアドレスに基づいて新しい招待トークンを生成します。トークンは通常、UUID形式を使用して一意の値を生成します。- 例:
token = str(uuid.uuid4())
- 例:
- このトークンとメールアドレスをinvitation_tokensテーブルに保存します。保存されるデータには、以下の情報が含まれます:
- メールアドレス
- 招待トークン
- トークンの使用ステータス(
is_used=False
)
Step 3: AWS SESでメール送信
- トークンが生成され、データベースに保存されたら、次にAWS SES(Simple Email Service)を使用して、ユーザーに招待メールを送信します。
- メールには、トークンを含んだリンクが記載されており、ユーザーがそのリンクをクリックすると登録画面に誘導されます。
- 例:
https://example.com/register?token=<generated_token>
- 例:
- AWS SESは、Boto3ライブラリを通じてメールを送信します。
2. 新規ユーザー登録の流れ
招待を受け取ったユーザーが、登録を完了する流れです。
Step 1: 招待メールを受け取ったユーザーがリンクをクリック
- ユーザーは、送られた招待メール内のリンクをクリックします。このリンクには、トークンがクエリパラメータとして含まれています。
- 例:
https://example.com/register?token=<generated_token>
- 例:
Step 2: トークンを持ってAPIエンドポイントにリクエストを送信
- ユーザーは、登録画面で名前やパスワードなどの必要情報を入力し、登録リクエストをバックエンドの
/register
エンドポイントに送信します。このリクエストには、招待トークンも含まれています。
Step 3: FastAPIでトークンを検証
- サーバー側では、受け取ったトークンをデータベース(invitation_tokensテーブル)で確認します。
- トークンが存在し、かつ未使用であることを確認します(
is_used=False
)。 - トークンが有効な場合、usersテーブルにユーザー情報を保存し、ユーザー登録を完了します。
- 登録完了後、該当のトークンを使用済み(
is_used=True
)に更新します。
このセクションのまとめ
招待メール送信の流れ
- フロントエンドからユーザーのメールアドレスをAPIに送信。
- FastAPIで招待トークンを生成し、データベースに保存。
- AWS SESを使ってユーザーに招待メールを送信。
新規ユーザー登録の流れ
- ユーザーがメール内のリンクをクリック。
- トークンを使用してFastAPIにリクエストを送信。
- FastAPIでトークンを検証し、ユーザーを登録。トークンを使用済みにする。
このようにFastAPIとPostgreSQL、SESを使ったシンプルかつセキュアなユーザー招待と登録システムが構築できます。
AWS SESを用いたメール送信
AWS SESの設定はAWSコンソール上で行います。SESを使用するためには、ドメインの検証やメールアドレスの確認が必要です。
boto3を使ってSESにメールを送信する関数を実装します。
コード例(FastAPIエンドポイント /invite
の処理):
from fastapi import FastAPI, HTTPException, Depends
from sqlalchemy.orm import Session
from models import InvitationToken
import uuid
import boto3
app = FastAPI()
# データベースセッションの依存関係
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
# SESの設定
ses = boto3.client('ses', region_name='us-west-2')
@app.post("/invite")
def send_invitation(email: str, db: Session = Depends(get_db)):
# トークンの生成
token = str(uuid.uuid4())
# データベースに保存
invitation_token = InvitationToken(email=email, token=token, is_used=False)
db.add(invitation_token)
db.commit()
# 招待メールの送信
send_email_with_ses(email, token)
return {"message": "Invitation sent"}
def send_email_with_ses(email, token):
# メールの内容を構築
response = ses.send_email(
Source='your-email@example.com',
Destination={'ToAddresses': [email]},
Message={
'Subject': {'Data': 'You are invited to register'},
'Body': {
'Text': {
'Data': f"Click the link to register: https://example.com/register?token={token}"
}
}
}
)
return response
この関数はSESを使って指定したメールアドレスに招待メールを送信します。
ユーザー登録API
コード例(FastAPIエンドポイント /register
の処理):
from fastapi import FastAPI, HTTPException, Depends
from sqlalchemy.orm import Session
from models import User, InvitationToken
from database import get_db
@app.post("/register")
def register_user(name: str, email: str, token: str, db: Session = Depends(get_db)):
# トークンの検証
invitation_token = db.query(InvitationToken).filter(InvitationToken.token == token).first()
if not invitation_token or invitation_token.is_used:
raise HTTPException(status_code=400, detail="Invalid or used token")
# ユーザーの作成
new_user = User(name=name, email=email, is_active=True)
db.add(new_user)
db.commit()
# トークンを使用済みに更新
invitation_token.is_used = True
db.commit()
return {"message": "User registered successfully"}
まとめ
この記事では、FastAPI、PostgreSQL、AWS SESを使用して、ユーザー招待メールを送信し、ユーザーを登録するAPIの構築方法を解説しました。API設計を分かりやすくするため、機能ごとに分離して説明し、SESを用いたメール送信も丁寧に解説しました。