# 通知設計書 6-BaseMailer#attachment_with_content

## 概要

本ドキュメントは、Rails ActionMailerフレームワークにおけるBaseMailer#attachment_with_contentメソッドによる添付ファイル付きメール通知の設計を記述する。

### 本通知の処理概要

BaseMailer#attachment_with_contentは、通常の添付ファイル（ダウンロード用）を含むメールを送信するためのテスト用メーラーメソッドである。PDFファイルを添付ファイルとして含み、Content-Typeがmultipart/mixedとなるマルチパートメールを生成する。

**業務上の目的・背景**：請求書、レポート、契約書などのドキュメントをメールに添付して送信する場合に使用される。受信者はメールクライアントから添付ファイルをダウンロードできる。本実装はテスト用であり、attachments[]への代入による通常添付ファイル機能の動作確認を主目的とする。

**通知の送信タイミング**：メーラーメソッドが呼び出された時点で送信される。

**通知の受信者**：デフォルトでは`system@test.lindsaar.net`宛に送信される（BaseMailerのクラスデフォルト設定）。

**通知内容の概要**：invoice.pdfを添付ファイルとして含み、HTMLテンプレート（attachment_with_content.erb）の内容「Attachment with content」が本文として送信される。メール構造はmultipart/mixed > text/html + application/pdf となる。

**期待されるアクション**：受信者はメール本文を閲覧し、添付されたPDFファイルをダウンロードする。テスト用途では、通常添付ファイルの追加とmultipart/mixed構造が正しく生成されることを確認する。

## 通知種別

メール

## 送信仕様

### 基本情報

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

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

BaseMailerのクラスデフォルト設定として`system@test.lindsaar.net`が指定されている。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | jose@test.plataformatec.com |
| 送信元名称 | （未設定） |
| 件名 | Attachment with content（I18nデフォルト） |
| 形式 | multipart/mixed |

### 本文テンプレート

```
Attachment with content
```

テンプレートファイル: `actionmailer/test/fixtures/base_mailer/attachment_with_content.erb`

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| invoice.pdf | application/pdf | 常に添付 | 請求書PDFファイル |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| （なし） | 本テンプレートでは変数を使用しない | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | `BaseMailer.attachment_with_content` メソッド実行 | なし（常に送信） | メーラーメソッドの直接呼び出し |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| perform_deliveries = false | ActionMailerの設定で配信を無効化している場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[BaseMailer.attachment_with_content 呼び出し] --> B[MessageDelivery オブジェクト生成]
    B --> C[deliver_now/deliver_later 呼び出し]
    C --> D[メーラーインスタンス生成]
    D --> E[attachment_with_content メソッド実行]
    E --> F[attachments で添付ファイル設定]
    F --> G[mail hash メソッド呼び出し]
    G --> H[テンプレート attachment_with_content.erb 検索]
    H --> I[添付ファイルあり判定]
    I --> J[multipart/mixed 構造生成]
    J --> K[本文パート + 添付ファイルパート]
    K --> L[Mail::Message 生成]
    L --> M[配信処理]
    M --> N[終了]
```

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

### 参照テーブル一覧

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

### 更新テーブル一覧

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

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| テンプレート未検出 | attachment_with_content.erbが存在しない場合 | ActionView::MissingTemplate例外 |
| mail後の添付追加 | mail()呼び出し後にattachments[]=を使用 | RuntimeError例外 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし

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

- 添付ファイルはBase64エンコードされるため、メールサイズが増大する（元ファイルの約1.37倍）
- 添付ファイルの内容検証は行われない（任意のバイナリデータを添付可能）
- 添付ファイルにはウイルスが含まれる可能性があるため、実運用ではスキャンを検討
- テスト用メーラーのため、本番環境での使用は非推奨

## 備考

- attachments[]への代入はmail()呼び出し前に行う必要がある
- ファイル拡張子からMIMEタイプが自動判定される（invoice.pdf -> application/pdf）
- 添付ファイルと本文の両方がある場合、multipart/mixedとなる
- 本文のみを:bodyオプションで指定することも可能

---

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

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

### 推奨読解順序

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

添付ファイル付きメールのMIME構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | base.rb | `actionmailer/lib/action_mailer/base.rb` | L756-773: attachmentsメソッドとLateAttachmentsProxy |

**読解のコツ**: mail()呼び出し前は@_message.attachmentsに直接アクセス、呼び出し後はLateAttachmentsProxyを介してアクセスし、追加操作は禁止される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | base_mailer.rb | `actionmailer/test/mailers/base_mailer.rb` | L58-61: attachment_with_contentメソッドの実装 |

**主要処理フロー**:
1. **L59**: `attachments["invoice.pdf"] = "This is test File content"` - 添付ファイルの設定
2. **L60**: `mail(hash)` - オプションのhashパラメータを渡してmailメソッド呼び出し

#### Step 3: Content-Type決定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | base.rb | `actionmailer/lib/action_mailer/base.rb` | L901-926: set_content_typeメソッド |

**主要処理フロー**:
- **L915-920**: `if m.has_attachments?` - 添付ファイルがある場合の分岐
- **L918-920**: `else ["multipart", "mixed", params]` - インライン以外の添付がある場合はmultipart/mixed

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | base_test.rb | `actionmailer/test/base_test.rb` | L126-131: 添付ファイルのテスト |
| 4-2 | base_test.rb | `actionmailer/test/base_test.rb` | L133-137: MIMEタイプ自動判定のテスト |
| 4-3 | base_test.rb | `actionmailer/test/base_test.rb` | L157-161: multipart/mixed構造のテスト |

**主要処理フロー**:
- **L127-130**: 添付ファイル数、ファイル名、内容の検証
- **L135-136**: MIMEタイプが拡張子から自動判定されることの検証
- **L159-160**: 添付ファイルがある場合にmultipart/mixedになることの検証

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

```
BaseMailer.attachment_with_content(hash)
    │
    ├─ ActionMailer::Base.method_missing
    │      └─ MessageDelivery.new(self, :attachment_with_content, hash)
    │
    └─ MessageDelivery#deliver_now
           │
           ├─ processed_mailer
           │      └─ BaseMailer.new.process(:attachment_with_content, hash)
           │             │
           │             └─ BaseMailer#attachment_with_content(hash)
           │                    │
           │                    ├─ attachments["invoice.pdf"] = "..."
           │                    │      └─ @_message.attachments["invoice.pdf"] = ...
           │                    │             └─ Mail::Message#attachments
           │                    │
           │                    └─ mail(hash)
           │                           │
           │                           ├─ collect_responses_from_templates
           │                           │      └─ attachment_with_content.erb
           │                           │
           │                           ├─ create_parts_from_responses
           │                           │      └─ 本文パート生成
           │                           │
           │                           └─ set_content_type
           │                                  └─ multipart/mixed (添付あり)
           │
           └─ message.deliver
```

### データフロー図

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

"This is test File content"    ───▶ attachments["invoice.pdf"]   ───▶ 添付ファイルパート
  (添付データ)                        │                                application/pdf
                                      ▼
attachment_with_content.erb    ───▶ collect_responses_from_templates
  (テンプレート)                      │
                                      ├─ render(template: ...)
                                      │    └─ "Attachment with content"
                                      │
                                      ▼
                               ───▶ create_parts_from_responses   ───▶ 本文パート
                                      │                                text/html
                                      │
                                      ▼
                               ───▶ set_content_type              ───▶ Mail::Message
                                      │                                multipart/mixed
                                      └─ has_attachments? = true
                                           └─ not all inline
                                                └─ multipart/mixed
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| base_mailer.rb | `actionmailer/test/mailers/base_mailer.rb` | ソース | テスト用メーラークラス定義 |
| base.rb | `actionmailer/lib/action_mailer/base.rb` | ソース | 添付ファイル処理ロジック |
| attachment_with_content.erb | `actionmailer/test/fixtures/base_mailer/attachment_with_content.erb` | テンプレート | メール本文テンプレート |
| base_test.rb | `actionmailer/test/base_test.rb` | テスト | 添付ファイル機能テスト |
