# 通知設計書 11-ParamsMailer#invitation

## 概要

本ドキュメントは、ActionMailerのパラメータ化されたメーラー機能を使用した招待メール通知について、設計情報を記載するものである。

### 本通知の処理概要

ParamsMailer#invitationは、ActionMailerのParameterizedモジュールを活用したテスト用メーラーである。招待者（inviter）と被招待者（invitee）のパラメータを受け取り、プロジェクトへの招待メールを送信する機能を提供する。

**業務上の目的・背景**：本メーラーは、ActionMailerのパラメータ化機能のテスト・デモンストレーション用として設計されている。パラメータ化されたメーラーを使用することで、メーラーのアクションメソッドに引数を渡す代わりに、`params`ハッシュを通じてデータを共有でき、コードの重複を削減し、メンテナンス性を向上させる。実際のアプリケーションでは、新規メンバーをプロジェクトやチームに招待する際のメール送信に使用される。

**通知の送信タイミング**：アプリケーションコードから`ParamsMailer.with(inviter: ..., invitee: ...).invitation`が呼び出された時点でメールが生成され、`deliver_now`または`deliver_later`によって送信される。

**通知の受信者**：パラメータ`invitee`に指定された値が宛先となる。`default to: Proc.new { @invitee }`により、before_actionコールバックで設定された`@invitee`インスタンス変数がToヘッダーに設定される。

**通知内容の概要**：件名「Welcome to the project!」とともに、招待者の名前を含むプレーンテキストメッセージ「So says {inviter}」が送信される。

**期待されるアクション**：受信者は招待メールを確認し、プロジェクトへの参加手続きを行うことが期待される。

## 通知種別

メール通知（Email）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（deliver_now）または非同期（deliver_later） |
| 優先度 | 中（アプリケーション設定による） |
| リトライ | Active Jobの設定に依存（deliver_later使用時） |

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

1. `ParamsMailer.with(inviter: xxx, invitee: yyy)`でパラメータを設定
2. `before_action`コールバックで`params[:invitee]`を`@invitee`に代入
3. `default to: Proc.new { @invitee }`により、Toヘッダーが動的に設定される

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | `params[:inviter]`（動的に設定） |
| 送信元名称 | 設定なし |
| 件名 | Welcome to the project! |
| 形式 | テキスト（text/plain） |

### 本文テンプレート

```
So says {inviter}
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 本メーラーには添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| @inviter | 招待者 | params[:inviter] | Yes |
| @invitee | 被招待者 | params[:invitee] | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | ParamsMailer.with(...).invitation | パラメータが正しく設定されていること | アプリケーションコードからの呼び出し |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| perform_deliveries = false | ActionMailer設定で配信が無効化されている場合 |
| パラメータ不正 | inviterまたはinviteeが未設定の場合、エラーが発生 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ParamsMailer.with params 呼び出し] --> B[Parameterized::Mailer生成]
    B --> C[invitation メソッド呼び出し]
    C --> D[MessageDelivery生成]
    D --> E{deliver_now or deliver_later?}
    E -->|deliver_now| F[同期処理]
    E -->|deliver_later| G[Active Jobキューイング]
    F --> H[before_action実行]
    G --> H
    H --> I[params展開: @inviter, @invitee設定]
    I --> J[default値評価: to, from設定]
    J --> K[mail メソッド実行]
    K --> L[テンプレートレンダリング]
    L --> M[Mail::Message生成]
    M --> N[deliver.action_mailer計装イベント]
    N --> O[メール送信]
    O --> P[送信完了]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| なし | - | 本メーラーはデータベースを直接参照しない |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | 本メーラーはデータベースを更新しない |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| パラメータ未設定 | params[:inviter]またはparams[:invitee]がnil | 呼び出し元で適切なパラメータを設定する |
| テンプレートエラー | ブロック内のrender処理失敗 | テンプレートを確認・修正する |
| 配信エラー | SMTPサーバー接続失敗等 | rescue_fromで例外処理、またはリトライ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Active Job設定に依存（deliver_later時） |
| リトライ間隔 | Active Job設定に依存 |
| リトライ対象エラー | Net::SMTPError等の一時的なエラー |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 設定なし（SMTPサーバーの制限に依存） |
| 1日あたり上限 | 設定なし |

### 配信時間帯

制限なし

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

- メールアドレスは個人情報として扱い、ログ出力時は適切にマスキングする
- メール本文に機密情報を含める場合は、暗号化やセキュアな配信方法を検討する
- deliver_later使用時はジョブキューのセキュリティを確保する

## 備考

- 本メーラーはActionMailerのParameterizedモジュールのテスト・デモ用途で作成されている
- 実運用ではApplicationMailerを継承し、適切なdefault設定を行うことが推奨される
- before_actionコールバックでパラメータを展開することで、複数のアクションで共通のセットアップを再利用可能

---

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

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

### 推奨読解順序

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

パラメータ化されたメーラーのパラメータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | parameterized.rb | `actionmailer/lib/action_mailer/parameterized.rb` | Parameterizedモジュールの全体像、params属性の定義（行92-98） |

**読解のコツ**: ActionMailer::Parameterizedモジュールはincludedブロック内で`params`アクセサを定義している。この`params`は通常のRailsコントローラのparamsとは異なり、メーラー固有のハッシュである。

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

ParamsMailerクラスの構造と呼び出し方を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | params_mailer.rb | `actionmailer/test/mailers/params_mailer.rb` | メーラークラス定義、before_actionコールバック、default設定 |

**主要処理フロー**:
1. **行3**: `ActionMailer::Base`を継承したParamsMailerクラス定義
2. **行4**: `before_action`でparams[:inviter]とparams[:invitee]を@inviter、@inviteeに展開
3. **行6**: `default to: Proc.new { @invitee }, from: -> { @inviter }`で動的なデフォルト値設定
4. **行8-12**: `invitation`メソッドでメール本文をブロック形式で定義

#### Step 3: Parameterizedモジュールの仕組みを理解する

withメソッドからMessageDelivery生成までの流れを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | parameterized.rb | `actionmailer/lib/action_mailer/parameterized.rb` | withメソッド、Mailerクラス、MessageDeliveryクラス |

**主要処理フロー**:
- **行106-108**: `with(params)`メソッドでParameterized::Mailerインスタンスを生成
- **行111-128**: Parameterized::Mailerクラスがmethod_missingでアクションメソッドをインターセプト
- **行130-152**: Parameterized::MessageDeliveryがparamsを保持しつつメール処理を実行

#### Step 4: ActionMailer::Baseの基本動作を理解する

mailメソッドの動作とメッセージ生成プロセスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | base.rb | `actionmailer/lib/action_mailer/base.rb` | mailメソッドの実装、デフォルト値の適用 |

**主要処理フロー**:
- **行645-656**: processメソッドで`process.action_mailer`計装イベントを発火
- **行865-898**: mailメソッドでヘッダー設定、テンプレートレンダリング、Mail::Message生成
- **行593-598**: deliver_mailでメール配信時に`deliver.action_mailer`計装イベントを発火

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

```
ParamsMailer.with(inviter: x, invitee: y)
    │
    ├─ ActionMailer::Parameterized::ClassMethods#with (行106-108)
    │      └─ Parameterized::Mailer.new(self, params) (行107)
    │
    └─ Parameterized::Mailer#method_missing (行117-123)
           └─ Parameterized::MessageDelivery.new (行119)
                  │
                  ├─ #deliver_now または #deliver_later
                  │      └─ #processed_mailer (行137-141)
                  │             ├─ mailer.params = @params
                  │             └─ mailer.process @action, *@args
                  │
                  └─ ActionMailer::Base#process (行645-656)
                         ├─ instrument("process.action_mailer")
                         └─ before_action コールバック実行
                                └─ ParamsMailer#invitation (行8-12)
                                       └─ mail(subject: ...) (行865-898)
                                              └─ Mail::Message生成
```

### データフロー図

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

params[:inviter] ─────┬───▶ before_action ───▶ @inviter ─┬───▶ from ヘッダー
                      │                                   │
                      │                                   └───▶ 本文「So says {inviter}」
                      │
params[:invitee] ─────┴───▶ before_action ───▶ @invitee ─────▶ to ヘッダー

subject: "Welcome to the project!" ──────────────────────────▶ subject ヘッダー

                                    mail() ──────────────────▶ Mail::Message
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| params_mailer.rb | `actionmailer/test/mailers/params_mailer.rb` | ソース | ParamsMailerクラス定義 |
| parameterized.rb | `actionmailer/lib/action_mailer/parameterized.rb` | ソース | Parameterizedモジュール |
| base.rb | `actionmailer/lib/action_mailer/base.rb` | ソース | ActionMailer基底クラス |
| message_delivery.rb | `actionmailer/lib/action_mailer/message_delivery.rb` | ソース | メッセージ配信ラッパー |
| log_subscriber.rb | `actionmailer/lib/action_mailer/log_subscriber.rb` | ソース | ログ出力購読者 |
