# 通知設計書 109-verification_instructions_sent_to_secondary_email

## 概要

本ドキュメントは、GitLabの本人確認機能において、検証コードがセカンダリメールアドレスに送信されたことをプライマリメールアドレスに通知するメールの設計を記載するものです。

### 本通知の処理概要

本通知は、ユーザーがサインイン時の本人確認でセカンダリメールアドレスへの検証コード送信をリクエストした場合に、プライマリメールアドレスに対してその事実を通知するセキュリティアラートです。

**業務上の目的・背景**：GitLabでは、ユーザーが複数のメールアドレスをアカウントに登録できます。本人確認時に、ユーザーはセカンダリメールアドレスへの検証コード送信をリクエストできます。この機能を悪用してプライマリメール所有者の知らないうちにセカンダリメール経由でアカウントにアクセスされることを防ぐため、セカンダリメールへの検証コード送信時にはプライマリメールアドレスに通知が送信されます。

**通知の送信タイミング**：`resend_verification_code`アクションにおいて、ユーザーがセカンダリメールアドレスを指定して検証コードの再送信をリクエストし、かつそのセカンダリメールがプライマリメールと異なる場合に送信されます。

**通知の受信者**：ユーザーのプライマリメールアドレスです。

**通知内容の概要**：セカンダリメールアドレスに検証コードが送信されたこと、不正アクセスの可能性への注意喚起、パスワード変更と2FA設定の推奨、セカンダリメールアドレスの管理方法が含まれます。

**期待されるアクション**：受信者（アカウント所有者）は、自分自身がセカンダリメールへの送信をリクエストしたかを確認します。心当たりがない場合は、パスワード変更、2FA設定、不要なセカンダリメールの削除を行うことが推奨されます。

## 通知種別

メール通知

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（deliver_later） |
| 優先度 | 高（セキュリティアラート） |
| リトライ | Sidekiqのデフォルト設定に準拠 |

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

ユーザーのプライマリメールアドレス（`user.email`）に送信されます。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | GitLabのデフォルトメールアドレス |
| 送信元名称 | GitLab |
| 件名 | `Verification code sent to your secondary email address` |
| 形式 | HTML/テキスト（マルチパート） |
| 特殊ヘッダー | `X-Mailgun-Suppressions-Bypass: true` |

### 本文テンプレート

#### HTML版（verification_instructions_sent_to_secondary_email.html.haml）
```
Verification code sent to your secondary email address

We received a request to access your GitLab account with your secondary email address {user_secondary_email}.

If you have not tried to sign into your account, we recommend changing your password and setting up Two-Factor Authentication to keep your account safe.

To stop using this email with your GitLab account, remove it in your account settings.
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 本通知には添付ファイルはありません |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| @user_secondary_email | セカンダリメールアドレス | 引数として渡される | Yes |
| @password_link | パスワード変更ヘルプページURL | help_page_url(...) | Yes |
| @two_fa_link | 2FAトラブルシューティングURL | help_page_url(...) | Yes |
| @account_settings_link | アカウント設定ページURL | profile_account_url | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | resend_verification_code | secondary_email != primary_email | セカンダリメールへの検証コード送信時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| secondary_email == primary_email | セカンダリメールがプライマリと同じ場合 |
| secondary_email.blank? | セカンダリメールが指定されていない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ユーザーが検証コード再送信をリクエスト] --> B{セカンダリメール指定?}
    B -->|No| C[プライマリメールに送信]
    B -->|Yes| D[fetch_confirmed_user_secondary_email]
    D --> E{確認済みセカンダリメール?}
    E -->|No| F[プライマリメールに送信]
    E -->|Yes| G[セカンダリメールに検証コード送信]
    G --> H{secondary_email != primary_email?}
    H -->|No| I[終了]
    H -->|Yes| J[send_notification_to_primary_email]
    J --> K[Notify.verification_instructions_sent_to_secondary_email]
    K --> L[deliver_later]
    L --> I
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| users | ユーザー情報の取得 | |
| emails | セカンダリメールの確認状態チェック | |

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

#### users

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | ユーザーID | |
| email | プライマリメールアドレス | |

#### emails

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| email | セカンダリメールアドレス | user_id = ? AND confirmed_at IS NOT NULL |
| confirmed_at | 確認済みフラグ | |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | 本通知では更新処理なし |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 送信失敗 | SMTP接続エラー等 | Sidekiqによるリトライ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Sidekiqデフォルト（25回） |
| リトライ間隔 | 指数バックオフ |
| リトライ対象エラー | 一時的なネットワークエラー、SMTP接続エラー等 |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | GitLab全体のメール送信レート制限に準拠 |
| 1日あたり上限 | GitLab全体のメール送信レート制限に準拠 |

### 配信時間帯

特に制限なし（セキュリティ上、即時送信が必要）

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

- セカンダリメールは確認済み（confirmed）のもののみ使用可能
- プライマリメール所有者への通知により、不正アクセスの早期検知が可能
- パスワード変更と2FA設定を推奨するメッセージが含まれる
- アカウント設定ページへのリンクにより、不要なセカンダリメールの削除が容易

## 備考

- この通知は検証コード自体は含まない（検証コードはセカンダリメールに送信される）
- プライマリメールとセカンダリメールが同じ場合は送信されない
- 確認済みでないセカンダリメールへの送信はブロックされる

---

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

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

### 推奨読解順序

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

通知送信のトリガーとなる処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | verifies_with_email.rb | `app/controllers/concerns/verifies_with_email.rb` | resend_verification_code、send_notification_to_primary_email |

**主要処理フロー**:
1. **38-86行目**: resend_verification_code - メイン処理
2. **48行目**: fetch_confirmed_user_secondary_email - セカンダリメール取得
3. **80-81行目**: send_notification_to_primary_email呼び出し条件
4. **197-199行目**: send_notification_to_primary_email実装

#### Step 2: メーラーを理解する

通知メールの生成処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | identity_verification.rb | `app/mailers/emails/identity_verification.rb` | verification_instructions_sent_to_secondary_emailメソッド |

**主要処理フロー**:
- **27-45行目**: verification_instructions_sent_to_secondary_email
- **28行目**: validate_single_recipient_in_email!
- **30-33行目**: テンプレート変数の設定
- **35-39行目**: ヘッダーの設定

#### Step 3: ビューテンプレートを理解する

メール本文のテンプレートを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | verification_instructions_sent_to_secondary_email.html.haml | `app/views/notify/verification_instructions_sent_to_secondary_email.html.haml` | HTML形式の本文テンプレート |
| 3-2 | verification_instructions_sent_to_secondary_email.text.erb | `app/views/notify/verification_instructions_sent_to_secondary_email.text.erb` | テキスト形式の本文テンプレート |

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

```
VerifiesWithEmail#resend_verification_code
    │
    ├─ find_verification_user
    │
    ├─ send_rate_limited?(user)
    │
    ├─ fetch_confirmed_user_secondary_email(user, email_params[:email])
    │      └─ user.emails.confirmed.find_by_email(email)
    │
    ├─ send_otp_with_email / lock_and_send_verification_instructions
    │      └─ send_verification_instructions_email
    │             └─ Notify.verification_instructions_email
    │
    └─ send_notification_to_primary_email（secondary != primary の場合）
           │
           └─ Notify.verification_instructions_sent_to_secondary_email(primary_email, secondary_email)
                  │
                  ├─ validate_single_recipient_in_email!
                  │
                  ├─ @user_secondary_email, @password_link, @two_fa_link, @account_settings_link設定
                  │
                  └─ mail_with_locale
                         └─ deliver_later
```

### データフロー図

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

secondary_email         VerifiesWithEmail                 セカンダリメールに
（ユーザー指定）   ───▶  #resend_verification_code    ───▶ 検証コード送信
                                   │
                                   │                      ───▶  プライマリメールに
                                   │                            セキュリティ通知送信
primary_email           ───▶       │
（user.email）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| verifies_with_email.rb | `app/controllers/concerns/verifies_with_email.rb` | ソース | 通知送信のトリガー |
| identity_verification.rb | `app/mailers/emails/identity_verification.rb` | ソース | 本人確認メーラー |
| verification_instructions_sent_to_secondary_email.html.haml | `app/views/notify/verification_instructions_sent_to_secondary_email.html.haml` | テンプレート | HTML本文テンプレート |
| verification_instructions_sent_to_secondary_email.text.erb | `app/views/notify/verification_instructions_sent_to_secondary_email.text.erb` | テンプレート | テキスト本文テンプレート |
