# 通知設計書 18-ActionMailbox::Base#bounce_with

## 概要

本ドキュメントは、ActionMailboxのバウンスメール送信機能（非同期版）について、設計情報を記載するものである。

### 本通知の処理概要

ActionMailbox::Base#bounce_withは、受信メール処理において送信者に対してバウンスメール（拒否通知）を非同期で送信するためのメソッドである。受信メールの処理を拒否する際に、その理由を送信者に通知し、InboundEmailのステータスを「bounced」に変更する。

**業務上の目的・背景**：受信メールが何らかの理由で処理できない場合（認証失敗、権限不足、不正なフォーマット等）に、送信者にその旨を通知する必要がある。bounce_withはこのバウンス処理を標準化し、ActionMailerと統合された形でバウンスメールを送信する。非同期送信（deliver_later）により、受信メール処理のパフォーマンスに影響を与えない。

**通知の送信タイミング**：メールボックスのbefore_processingコールバックや処理ロジック内でbounce_withが呼び出された時点で、Active Jobキューに配信がエンキューされる。

**通知の受信者**：受信メールの送信者（From ヘッダーのアドレス）。

**通知内容の概要**：バウンス理由を説明するメール。ActionMailerで定義されたメーラークラスのアクションが使用される。

**期待されるアクション**：送信者がバウンスメールを受信し、メール送信の問題（認証、権限、フォーマット等）を認識して対応する。

## 通知種別

メール通知（Email - バウンスメール）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（deliver_later） |
| 優先度 | 中（Active Jobキューに依存） |
| リトライ | Active Job設定に依存 |

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

1. bounce_with(message)でActionMailerのメッセージオブジェクトを受け取る
2. InboundEmailステータスをbouncedに変更
3. message.deliver_laterで非同期送信をキューイング

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | アプリケーション定義のメーラーによる |
| 送信元名称 | アプリケーション定義のメーラーによる |
| 件名 | アプリケーション定義のメーラーによる |
| 形式 | アプリケーション定義のメーラーによる |

### 本文テンプレート例

```ruby
# UserRequiredMailer.missing(inbound_email)
class UserRequiredMailer < ApplicationMailer
  def missing(inbound_email)
    mail(
      to: inbound_email.mail.from,
      subject: "Unable to process your email"
    )
  end
end
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| アプリケーション定義 | - | - | メーラーアクションの実装による |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| message | ActionMailerメッセージオブジェクト | 呼び出し元で生成 | Yes |
| inbound_email | 受信メールオブジェクト | メールボックスのインスタンス変数 | 内部使用 |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| コールバック | before_processing | バリデーション失敗時 | 前処理での検証失敗 |
| 処理内 | process メソッド内 | 処理不可判定時 | メイン処理中の拒否 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| perform_deliveries = false | ActionMailer設定で配信無効 |
| messageがnil | メッセージオブジェクト未設定 |

## 処理フロー

### バウンス送信フロー

```mermaid
flowchart TD
    A[受信メール処理開始] --> B[before_processing コールバック]
    B --> C{検証成功?}
    C -->|No| D[bounce_with message 呼び出し]
    C -->|Yes| E[process メソッド実行]
    E --> F{処理可能?}
    F -->|No| D
    F -->|Yes| G[正常終了]
    D --> H[inbound_email.bounced!]
    H --> I[ステータス更新: bounced]
    I --> J[message.deliver_later]
    J --> K[Active Jobキューイング]
    K --> L[処理中断]
    L --> M{後続処理}
    M --> N[終了]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| action_mailbox_inbound_emails | 受信メール情報取得 | InboundEmail |

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

#### action_mailbox_inbound_emails

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | 識別子 | メールボックス処理対象 |
| status | 現在のステータス | ステータス確認用 |
| mail_blob_id | メール本文取得 | Active Storage参照 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| action_mailbox_inbound_emails | UPDATE | statusをbouncedに更新 |

#### action_mailbox_inbound_emails更新詳細

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| UPDATE | status | "bounced" | bounced!メソッドで更新 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| メーラーエラー | メッセージ生成失敗 | 例外をログ出力、ステータスはbouncedのまま |
| 配信エラー | SMTPサーバー接続失敗 | Active Jobリトライ |
| ステータス更新エラー | DB接続失敗 | 例外発生、トランザクションロールバック |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Active Job設定に依存 |
| リトライ間隔 | Active Job設定に依存 |
| リトライ対象エラー | 配信エラー（SMTPエラー等） |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 設定なし（Active Jobキュー設定に依存） |
| 1日あたり上限 | 設定なし |

### 配信時間帯

制限なし

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

- バウンスメールに受信メールの詳細を含めすぎない（情報漏洩防止）
- 送信者アドレスのスプーフィングに注意（バウンスフラッド攻撃対策）
- レート制限の検討（大量バウンス時の負荷対策）

## 備考

- bounce_withはdeliver_laterを使用するため、処理は即座に戻る
- InboundEmailのステータスは先にbouncedに更新される
- 即時送信が必要な場合はbounce_now_with（No.19）を使用
- bounced!メソッドだけ呼ぶと、バウンスメールは送信されずステータスのみ更新される

---

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

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

### 推奨読解順序

#### Step 1: bounce_withメソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | base.rb | `actionmailbox/lib/action_mailbox/base.rb` | bounce_withメソッド |

**主要処理フロー**:
1. **行105-108**: `bounce_with(message)` - エントリーポイント
2. **行106**: `inbound_email.bounced!` - ステータスをbouncedに更新
3. **行107**: `message.deliver_later` - 非同期でメール送信

#### Step 2: InboundEmailのステータス管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | inbound_email.rb | `actionmailbox/app/models/action_mailbox/inbound_email.rb` | ステータス管理 |

**主要処理フロー**:
- `bounced!`メソッドでstatusカラムを"bounced"に更新
- ステータスは pending → processing → delivered/bounced/failed の遷移

#### Step 3: メールボックスの処理フローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | base.rb | `actionmailbox/lib/action_mailbox/base.rb` | perform_processing、コールバック |

**主要処理フロー**:
- **行83-94**: `perform_processing` - 処理のエントリーポイント
- **行84**: `instrument "process.action_mailbox"` - 計装イベント
- **行86-88**: `run_callbacks :process` - before/after_processingコールバック実行
- **行43-52**: ドキュメント - bounce_withの使用例

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

```
ActionMailbox::Base#bounce_with(message)
    │
    ├─ inbound_email.bounced! (行106)
    │      │
    │      └─ InboundEmail#bounced!
    │             └─ update!(status: :bounced)
    │                    └─ action_mailbox_inbound_emails.status = "bounced"
    │
    └─ message.deliver_later (行107)
           │
           └─ ActionMailer::MessageDelivery#deliver_later
                  │
                  └─ ActionMailer::MailDeliveryJob.perform_later
                         │
                         └─ Active Job キューイング
                                │
                                └─ (非同期) メール送信
```

### データフロー図

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

inbound_email ───────────▶ bounced! ───▶ status = "bounced"
                                │
                                └───▶ action_mailbox_inbound_emails更新

message ─────────────────▶ deliver_later ───▶ MailDeliveryJob
(ActionMailer::MessageDelivery)              │
                                             └───▶ Active Job キュー

                                             (非同期)
                                                │
                                                ▼
                                         ActionMailer::Base.deliver_mail
                                                │
                                                └───▶ SMTPサーバー
                                                       │
                                                       └───▶ 送信者にバウンスメール
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| base.rb | `actionmailbox/lib/action_mailbox/base.rb` | ソース | bounce_with, bounce_now_with |
| inbound_email.rb | `actionmailbox/app/models/action_mailbox/inbound_email.rb` | ソース | InboundEmailモデル |
| callbacks.rb | `actionmailbox/lib/action_mailbox/callbacks.rb` | ソース | before_processing等 |
| routing.rb | `actionmailbox/lib/action_mailbox/routing.rb` | ソース | メールルーティング |
| message_delivery.rb | `actionmailer/lib/action_mailer/message_delivery.rb` | ソース | deliver_later |
| mail_delivery_job.rb | `actionmailer/lib/action_mailer/mail_delivery_job.rb` | ソース | 配信ジョブ |
