# 通知設計書 9-CallbackMailer#test_message

## 概要

本ドキュメントは、Rails ActionMailerフレームワークにおけるCallbackMailer#test_messageメソッドによるコールバック付きテストメール通知の設計を記述する。

### 本通知の処理概要

CallbackMailer#test_messageは、ActionMailerのbefore_deliver、after_deliver、around_deliverコールバック機能を実証するためのテスト用メーラーメソッドである。シンプルなテストメールを送信しながら、配信前後のコールバック処理を検証できる。

**業務上の目的・背景**：メール配信のライフサイクルにおいて、配信前の検証、配信後のログ記録、配信処理全体のラッピングなど、追加処理を行う必要がある場合に使用されるコールバック機能のテスト。本実装はテスト用であり、before_deliver/after_deliver/around_deliverコールバックの動作確認を主目的とする。

**通知の送信タイミング**：メーラーメソッドが呼び出され、deliver_nowまたはdeliver_laterで配信が実行された時点で送信される。before_deliverコールバックでabortが呼ばれた場合、送信は中止される。

**通知の受信者**：`test-receiver@test.com`宛に送信される。

**通知内容の概要**：件名「Test Subject」、本文「Test Body」のシンプルなテストメールが送信される。配信前後でコールバックが実行され、メーラーインスタンスへのアクセスが可能。

**期待されるアクション**：テスト用途では、コールバックが正しいタイミングで実行され、メーラーインスタンスやメッセージオブジェクトへのアクセスが可能であることを確認する。

## 通知種別

メール

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（deliver_now）/ 非同期（deliver_later） |
| 優先度 | 中（デフォルト） |
| リトライ | 配信メソッドに依存 |

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

メソッド内で固定値として`test-receiver@test.com`が指定されている。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | test-sender@test.com |
| 送信元名称 | （未設定） |
| 件名 | Test Subject |
| 形式 | text/plain |

### 本文テンプレート

```
Test Body
```

テンプレートファイル: なし（bodyオプションで直接指定）

### 添付ファイル

本メソッドでは添付ファイルは使用されない。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| （なし） | bodyオプションで直接指定 | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | `CallbackMailer.test_message.deliver_now` | before_deliverでabortされていない | コールバックテスト用 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| before_deliver で throw :abort | 配信をキャンセルし、after_deliverも実行しない |
| perform_deliveries = false | ActionMailerの設定で配信を無効化している場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[CallbackMailer.test_message 呼び出し] --> B[MessageDelivery オブジェクト生成]
    B --> C[deliver_now/deliver_later 呼び出し]
    C --> D[メーラーインスタンス生成]
    D --> E[test_message メソッド実行]
    E --> F[mail 呼び出し - Mail::Message 生成]
    F --> G[run_callbacks :deliver 開始]
    G --> H[before_deliver コールバック実行]
    H --> I{abort?}
    I -->|Yes| J[配信中止 - after_deliver スキップ]
    I -->|No| K[around_deliver コールバック開始]
    K --> L[message.deliver 実行]
    L --> M[around_deliver コールバック終了]
    M --> N[after_deliver コールバック実行]
    N --> O[終了]
    J --> O
```

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

### 参照テーブル一覧

本メソッドはデータベースを参照しない（テスト用メーラー）。

### 更新テーブル一覧

本メソッドはデータベースを更新しない。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| CallbackMailerError | test_raise_actionアクションで発生 | rescue_fromで捕捉 |
| 配信エラー | around_deliverで例外発生 | around_handles_errorがtrueの場合は抑制 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | ActiveJob設定に依存（deliver_later使用時） |
| リトライ間隔 | ActiveJob設定に依存 |
| リトライ対象エラー | StandardError |

## 配信設定

### レート制限

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

### 配信時間帯

制限なし

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

- テスト用メーラーのため、本番環境での使用は非推奨
- コールバック内でのエラーハンドリングを適切に実装する必要がある

## 備考

- before_deliverで`throw :abort`を呼ぶと配信が中止される
- after_deliverはメール配信後に呼ばれ、messageオブジェクトにアクセス可能
- around_deliverは配信処理全体をラップし、例外ハンドリングが可能
- rescue_fromでアクション処理中の例外を捕捉可能
- deliver_now!でも同様にコールバックが実行される

---

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

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

### 推奨読解順序

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

ActionMailerのコールバックシステムを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | callbacks.rb | `actionmailer/lib/action_mailer/callbacks.rb` | L1-37: コールバックモジュール全体 |

**読解のコツ**: ActiveSupport::Callbacksをincludeし、:deliverコールバックを定義している。skip_after_callbacks_if_terminated: trueにより、abortされた場合after_deliverは実行されない。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | callback_mailer.rb | `actionmailer/test/mailers/callback_mailer.rb` | L1-37: CallbackMailerクラス全体 |

**主要処理フロー**:
1. **L5-9**: クラス変数の定義（状態管理用）
2. **L11-13**: rescue_fromでCallbackMailerErrorを捕捉
3. **L15-17**: before_deliverコールバック - abort_before_deliverフラグでabort
4. **L19-21**: after_deliverコールバック - インスタンスを保存
5. **L23-28**: around_deliverコールバック - エラーハンドリング
6. **L30-32**: test_messageメソッド - シンプルなメール生成

#### Step 3: コールバック実行フローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | message_delivery.rb | `actionmailer/lib/action_mailer/message_delivery.rb` | L157-163: deliver_nowメソッド |
| 3-2 | message_delivery.rb | `actionmailer/lib/action_mailer/message_delivery.rb` | L145-151: deliver_now!メソッド |

**主要処理フロー**:
- **L158-160**: `processed_mailer.handle_exceptions do ... run_callbacks(:deliver) do`
- **L159-160**: run_callbacks(:deliver)内でbefore/around/after_deliverが実行

#### Step 4: テストケースで動作を確認する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | callbacks_test.rb | `actionmailer/test/callbacks_test.rb` | L31-39: after_deliverでメッセージアクセステスト |
| 4-2 | callbacks_test.rb | `actionmailer/test/callbacks_test.rb` | L47-55: before_deliverでabortテスト |
| 4-3 | callbacks_test.rb | `actionmailer/test/callbacks_test.rb` | L67-85: around_deliverエラーハンドリングテスト |

**主要処理フロー**:
- **L35-38**: after_deliver後にmessageオブジェクト（message_id, to）にアクセス可能を検証
- **L48-54**: abort_before_deliverでmessage_idがnil、after_deliverが実行されないことを検証
- **L68-71**: rescue_fromとaround_deliverの実行順序を検証

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

```
CallbackMailer.test_message.deliver_now
    │
    ├─ MessageDelivery#deliver_now
    │      │
    │      ├─ processed_mailer
    │      │      └─ CallbackMailer.new.process(:test_message)
    │      │             └─ test_message メソッド実行
    │      │                    └─ mail(from:, to:, subject:, body:)
    │      │
    │      └─ processed_mailer.handle_exceptions
    │             │
    │             └─ run_callbacks(:deliver)
    │                    │
    │                    ├─ [before_deliver]
    │                    │      └─ throw :abort if @@abort_before_deliver
    │                    │
    │                    ├─ [around_deliver] 開始
    │                    │      └─ @@around_deliver_instance = self
    │                    │
    │                    ├─ message.deliver (実際の配信)
    │                    │
    │                    ├─ [around_deliver] 終了
    │                    │      └─ rescue StandardError (オプション)
    │                    │
    │                    └─ [after_deliver]
    │                           └─ @@after_deliver_instance = self
    │
    └─ 配信完了（またはabortでスキップ）
```

### データフロー図

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

test_message 呼び出し   ───▶ mail() で Mail::Message 生成    ───▶ Mail::Message
                              │                                    (未配信)
                              ▼
                        ───▶ run_callbacks(:deliver) 開始
                              │
                              ├─ before_deliver
                              │      └─ abort_before_deliver?
abort_before_deliver    ───▶       │
  (クラス変数)                      ├─ true: throw :abort ───▶ 配信中止
                                    │                          after_deliver スキップ
                                    └─ false: 続行
                                           │
                                           ▼
                              ├─ around_deliver (ラップ)
                              │      │
                              │      ├─ 配信処理
                              │      │      └─ message.deliver
                              │      │             │
                              │      │             ▼
                              │      │      ───▶ 配信成功 ───▶ Mail::Message
                              │      │                         (配信済み)
                              │      │
                              │      └─ rescue (オプション)
                              │
                              └─ after_deliver
                                     └─ メッセージアクセス可能
                                           (message_id, to, etc.)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| callback_mailer.rb | `actionmailer/test/mailers/callback_mailer.rb` | ソース | コールバック付きテスト用メーラー |
| callbacks.rb | `actionmailer/lib/action_mailer/callbacks.rb` | ソース | コールバック機能定義 |
| message_delivery.rb | `actionmailer/lib/action_mailer/message_delivery.rb` | ソース | コールバック実行ロジック |
| callbacks_test.rb | `actionmailer/test/callbacks_test.rb` | テスト | コールバック機能テスト |
