# 通知設計書 3-アカウント登録確認通知

## 概要

本ドキュメントは、ユーザー登録時にアカウント有効化リンクを含むメールを送信する機能の設計仕様を記載する。

### 本通知の処理概要

本通知は、新規ユーザーがアカウント登録フォームから登録を完了した際に、アカウントを有効化するためのリンクを含む確認メールを送信する機能である。

**業務上の目的・背景**：メールアドレスの実在性を確認し、不正アカウント登録を防止するための仕組みである。ユーザーが入力したメールアドレスが実際にアクセス可能であることを確認することで、スパムアカウントの作成を抑制し、正当なユーザーのみがシステムを利用できるようにする。ダブルオプトイン方式による確実なメールアドレス確認を実現している。

**通知の送信タイミング**：フロント画面のユーザー登録フォーム（/auth/register）で必要情報を入力し、フォームをPOST送信した際に送信される。バリデーション成功後、ユーザーデータとプロフィールデータのDB挿入完了時にメール送信が実行される。

**通知の受信者**：新規登録するユーザー本人。登録フォームで入力されたメールアドレス宛に送信される。

**通知内容の概要**：アカウント有効化URL（ユーザーID + キー付き）と、サイト名およびサイトURLが含まれるテキストメール。

**期待されるアクション**：受信者はメールに記載されたアカウント有効化URLにアクセスし、アカウントを有効化することが期待される。有効化しないとログインができない仕組みになっている。

## 通知種別

メール

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高 |
| リトライ | 無（例外発生時はcatch処理あり） |

### 送信先決定ロジック

登録フォームで入力されたメールアドレスに対して送信する。ただし、Zend_Validate_Db_NoRecordExistsによりusersテーブルに同一メールアドレスが存在しないことを事前に確認する。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | {registry.site.site.email} |
| 送信元名称 | {registry.site.site.name} |
| 件名 | {registry.site.site.name} Account Activation |
| 形式 | テキスト |

### 本文テンプレート

```
Your account has been created. Before it can be used it must be activated.

To activate your account visit the link below:

{site_url}/auth/activate/id/{user_id}/key/{user_key}/

Regards,
{site_name}
{site_url}
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 添付ファイルは送信されない |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| site_name | サイト名 | registry.site.site.name | Yes |
| site_url | サイトURL | registry.site.site.url | Yes |
| user_id | ユーザーID | lastInsertId()で取得 | Yes |
| user_key | 有効化キー | md5(email + password)で生成 | Yes |
| user_email | 受信者メールアドレス | 入力フォームから | Yes |
| user_name | 受信者氏名 | 入力フォームから（first + last） | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | ユーザー登録フォーム送信 | 全バリデーション成功 | フロント画面の/auth/registerでフォームをPOST送信 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| メールアドレス重複 | 入力されたメールアドレスがusersテーブルに既に存在する場合 |
| エイリアス重複 | 入力されたエイリアスがusersテーブルに既に存在する場合 |
| バリデーションエラー | 必須項目の未入力、形式不正など |
| CAPTCHA認証失敗 | 画像認証コードが不正な場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ユーザー登録フォーム送信] --> B{バリデーションチェック}
    B -->|メールアドレス重複| C[エラーメッセージ表示]
    B -->|エイリアス重複| C
    B -->|CAPTCHA失敗| C
    B -->|バリデーション成功| D[ユーザーキー生成]
    D --> E[usersテーブルINSERT]
    E --> F[lastInsertId取得]
    F --> G[users_profilesテーブルINSERT]
    G --> H{メーリングリスト選択あり?}
    H -->|Yes| I[mail_subscriptionsテーブルINSERT]
    H -->|No| J[Zend_Mailインスタンス生成]
    I --> J
    J --> K[有効化URL生成]
    K --> L[メール本文設定]
    L --> M[送信元・送信先設定]
    M --> N[メール送信実行]
    N --> O{送信成功?}
    O -->|成功| P[完了画面表示]
    O -->|失敗| Q[例外メッセージ出力]
    C --> R[終了]
    P --> R
    Q --> R
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| users | メールアドレス重複チェック | Zend_Validate_Db_NoRecordExists |
| mail_groups | 公開メーリングリスト取得 | mgroup_open = 'Y' |

### テーブル別参照項目詳細

#### users（重複チェック用）

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| user_email | メールアドレス重複確認 | バリデーション時 |
| user_alias | エイリアス重複確認 | バリデーション時 |

#### mail_groups

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| mgroup_id | グループID | WHERE mgroup_open = 'Y' |
| mgroup_title | グループ名 | WHERE mgroup_open = 'Y' |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| users | INSERT | 新規ユーザー登録 |
| users_profiles | INSERT | プロフィール情報登録 |
| mail_subscriptions | INSERT | メーリングリスト購読登録（選択時） |

#### usersテーブルINSERT

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | user_alias | 入力値 | ユーザーエイリアス |
| INSERT | user_email | 入力値 | メールアドレス |
| INSERT | user_password | md5(site_key + password + salt) | ハッシュ化パスワード |
| INSERT | user_salt | ランダム生成文字列 | Salt |
| INSERT | user_key | md5(email + password) | 有効化キー |
| INSERT | user_date | NOW() | 登録日時 |
| INSERT | user_mailformat | 入力値 | メール受信形式 |
| INSERT | user_status | 'inactive' | 初期ステータス |

#### users_profilesテーブルINSERT

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | upro_userid | lastInsertId() | ユーザーID |
| INSERT | upro_first | 入力値 | 名 |
| INSERT | upro_last | 入力値 | 姓 |
| INSERT | upro_country | 入力値 | 国 |
| INSERT | upro_city | 入力値 | 市区町村（任意） |
| INSERT | upro_date | NOW() | 登録日時 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| メールアドレス重複 | usersテーブルに同一メールアドレスが存在 | エラーメッセージ「Invalid E-mail Address - entered e-mail address is associated with an existing account」を表示 |
| エイリアス重複 | usersテーブルに同一エイリアスが存在 | エラーメッセージ「Invalid Alias - entered alias is associated with an existing account」を表示 |
| CAPTCHA認証失敗 | 画像認証コードが一致しない | エラーメッセージ「Invalid Verification Code - you must enter the code exactly as displayed」を表示 |
| メール送信失敗 | SMTP接続エラー等 | Zend_Exceptionをcatchし、$e->messageを出力 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

配信時間帯の制限は設けられていない。24時間いつでも送信可能。

## セキュリティ考慮事項

- 有効化キーはmd5(email + password)で生成されており、予測困難性が低い可能性がある
- 有効化リンクに有効期限が設定されていないため、長期間有効なままとなる
- CAPTCHAによるbot対策が実装されている
- パスワードはMD5ハッシュ化され、サイトキーとSaltと連結してデータベースに保存される
- MD5は現在推奨されないハッシュアルゴリズムであり、セキュリティ強化の検討が必要
- メール送信エラー時に例外メッセージがそのまま出力される可能性がある

## 備考

- 本機能はZend Framework 1.x系のZend_Mailコンポーネントを使用している
- CAPTCHA画像は`/_captcha/images/`に生成される
- CAPTCHAフォントは`/_captcha/fonts/Envy Code R.ttf`を使用
- 新規ユーザーのステータスは'inactive'で登録され、有効化後に'active'に変更される
- メーリングリスト購読機能との連携あり

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、ユーザー登録に必要なデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | users テーブル | データベース | user_id, user_email, user_alias, user_key, user_status の構造 |
| 1-2 | users_profiles テーブル | データベース | upro_userid, upro_first, upro_last, upro_country の構造 |
| 1-3 | mail_groups テーブル | データベース | mgroup_id, mgroup_open の構造 |
| 1-4 | mail_subscriptions テーブル | データベース | msub_group, msub_user の構造 |

**読解のコツ**: ユーザー登録は複数テーブルに跨る処理のため、テーブル間の関係を先に把握する。

#### Step 2: エントリーポイントを理解する

処理の起点となるコントローラーとアクションを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AuthController.php | `application/modules/default/controllers/AuthController.php` | registerAction()メソッドがエントリーポイント |

**主要処理フロー**:
1. **行253**: `registerAction()`メソッド開始
2. **行255-265**: CAPTCHA設定
3. **行268-276**: 公開メーリングリスト取得
4. **行278**: POSTリクエスト判定
5. **行282-352**: バリデーション設定（メールアドレス、エイリアス、パスワード、国など）
6. **行356**: バリデーション + CAPTCHA検証
7. **行360-361**: Saltとユーザーキー生成
8. **行364-376**: ユーザーデータ作成・INSERT
9. **行378**: lastInsertId取得
10. **行381-391**: プロフィールデータ作成・INSERT
11. **行394-410**: メーリングリスト購読処理
12. **行412-429**: Zend_Mailでメール送信（try-catch）

#### Step 3: ユーザーキー生成ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AuthController.php | `application/modules/default/controllers/AuthController.php` | 行361の$ukey生成処理 |

**主要処理フロー**:
- **行361**: `$ukey = md5($input->email.$input->password);`
- email + passwordの単純な連結をMD5ハッシュ化

### プログラム呼び出し階層図

```
AuthController::registerAction()
    │
    ├─ Zend_Captcha_Image (CAPTCHA生成)
    │
    ├─ Zend_Registry::getInstance()->db->select() (メーリングリスト取得)
    │      └─ mail_groups
    │
    ├─ Zend_Filter_Input (バリデーション)
    │      ├─ Zend_Validate_Db_NoRecordExists (users.user_email)
    │      └─ Zend_Validate_Db_NoRecordExists (users.user_alias)
    │
    ├─ generatepassword() (Salt生成)
    │
    ├─ Zend_Registry::getInstance()->db->insert() (ユーザー登録)
    │      ├─ users
    │      ├─ users_profiles
    │      └─ mail_subscriptions (選択時)
    │
    └─ Zend_Mail (メール送信)
           ├─ setBodyText()
           ├─ setFrom()
           ├─ addTo()
           ├─ setSubject()
           └─ send()
```

### データフロー図

```
[入力]                    [処理]                    [出力]

フォームデータ ─────▶ バリデーション ─────────▶ エラー/続行判定
(email, alias,              │
password, など)             ▼
                     CAPTCHA検証
                           │
                           ▼
                     Salt生成 ─────────────▶ 8文字ランダム
                     ユーザーキー生成 ─────▶ md5(email+pass)
                           │
                           ▼
                     DB INSERT ────────────▶ users
                           │                users_profiles
                           │                mail_subscriptions
                           ▼
                     有効化URL生成
                     /auth/activate/id/{id}/key/{key}/
                           │
                           ▼
                     メール送信 ────────────▶ ユーザーメールアドレス
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AuthController.php | `application/modules/default/controllers/AuthController.php` | ソース | ユーザー登録処理のコントローラー |
| CMS_Controller_Action_Auth | `library/CMS/Controller/Action/Auth.php` | ソース | 認証系コントローラーの基底クラス |
| register.phtml | `application/modules/default/views/scripts/auth/register.phtml` | テンプレート | ユーザー登録フォームのビュー |
| Envy Code R.ttf | `_captcha/fonts/Envy Code R.ttf` | フォント | CAPTCHA画像用フォント |
