# 画面設計書 7-メールプレビュー画面

## 概要

本ドキュメントは、Ruby on Rails フレームワークにおけるメールプレビュー画面の画面設計を定義するものである。

### 本画面の処理概要

本画面は、Action Mailerで定義されたメールの内容をプレビュー表示する開発者向けデバッグ画面である。メールのヘッダー情報（From、To、CC、BCC、Subject等）とボディ（HTML/テキスト形式）をiframe内に表示し、添付ファイルのダウンロードやEMLファイルの取得も可能。

**業務上の目的・背景**：メール送信機能の開発において、実際にメールを送信せずにメールの見た目と内容を確認するために使用される。HTML形式とテキスト形式の切り替え、多言語対応の確認（I18n.locale切り替え）、添付ファイルの確認など、メール開発に必要な機能を一画面で提供する。

**画面へのアクセス方法**：開発環境において、メーラープレビュー一覧画面またはメーラー詳細画面からメールアクション名をクリックするか、直接 `/rails/mailers/preview/{preview_name}/{email_action}` にアクセスする。

**主要な操作・処理内容**：
1. プレビュークラスのcallメソッドを実行してMailオブジェクトを生成
2. メールヘッダー情報（From、To、CC、BCC、Date、Subject等）を表示
3. HTML/テキスト形式の切り替えUIを提供
4. I18n.localeによる多言語プレビュー切り替えを提供
5. 添付ファイルのダウンロードリンクを提供
6. EMLファイルとしてメール全体をダウンロード

**画面遷移**：
- 遷移元：メーラープレビュー一覧画面、メーラー詳細画面
- 遷移先：特になし（表示専用画面、ダウンロードアクションあり）

**権限による表示制御**：`ActionMailer::Base.show_previews` の設定に応じてアクセス制御が変わる。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 9 | Action Mailer | 主機能 | メールコンテンツのプレビュー生成・表示処理 |
| 23 | I18n | 補助機能 | ロケール切り替えによる多言語プレビュー表示 |
| 5 | Action View | 補助機能 | HTML/テキスト形式の切り替え表示 |
| 30 | Data Streaming | 補助機能 | EMLファイルダウンロード（send_data）処理 |

## 画面種別

詳細画面（メールプレビュー）

## URL/ルーティング

| HTTP メソッド | URL パターン | コントローラー#アクション | 備考 |
|--------------|--------------|--------------------------|------|
| GET | /rails/mailers/preview/{preview_name}/{email_action} | rails/mailers#preview | プレビュー表示 |
| GET | /rails/mailers/preview/{preview_name}/{email_action}.html | rails/mailers#preview | HTML形式 |
| GET | /rails/mailers/preview/{preview_name}/{email_action}.txt | rails/mailers#preview | テキスト形式 |
| GET | /rails/mailers/download/{preview_name}/{email_action} | rails/mailers#download | EMLダウンロード |

## 入出力項目

### 入力項目（URLパラメータ/クエリパラメータ）

| 項目名 | パラメータ名 | データ型 | 必須 | 説明 |
|--------|-------------|----------|------|------|
| プレビュー名 | path | String | Yes | メーラープレビュークラスの識別名 |
| メールアクション名 | path | String | Yes | プレビューメソッド名 |
| MIME形式 | part | String | No | text/html または text/plain |
| ロケール | locale | String | No | I18nロケール（ja、en等） |

### 出力項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| ヘッダー情報 | dl/dt/dd要素 | From、To、CC、BCC、Date、Subject等 |
| 添付ファイル | リンク | Base64エンコードされた添付ファイルのダウンロードリンク |
| 形式切り替え | select要素 | HTML/テキスト形式の切り替えUI |
| ロケール切り替え | select要素 | 多言語プレビュー用UI（複数ロケール時のみ） |
| 全ヘッダー表示 | details/summary要素 | 全メールヘッダーの展開表示 |
| EMLダウンロード | リンク | .emlファイルとしてダウンロード |
| メール本文 | iframe要素 | HTML/テキスト形式のメール本文 |

## 表示項目

| No | 項目ID | 項目名 | データ型 | 取得元 | 備考 |
|----|--------|--------|----------|--------|------|
| 1 | smtp_from | SMTP-From | String | @email.smtp_envelope_from | Fromと異なる場合のみ表示 |
| 2 | smtp_to | SMTP-To | String | @email.smtp_envelope_to | To/CC/BCCと異なる場合のみ表示 |
| 3 | from | From | String | @email.header['from'] | 送信元アドレス |
| 4 | reply_to | Reply-To | String | @email.header['reply-to'] | 返信先（設定時のみ） |
| 5 | to | To | String | @email.header['to'] | 宛先 |
| 6 | cc | CC | String | @email.header['cc'] | CC（設定時のみ） |
| 7 | bcc | BCC | String | @email.header['bcc'] | BCC（設定時のみ） |
| 8 | date | Date | String | @email.header['date'] | 日時 |
| 9 | subject | Subject | String | @email.subject | 件名 |
| 10 | attachments | Attachments | Array | @attachments | 添付ファイル一覧 |
| 11 | inline_attachments | Inline Attachments | Array | @inline_attachments | インライン添付一覧 |

## イベント仕様

### 1-形式切り替え

**トリガー**: Format selectボックスの値を変更

**処理内容**:
1. refreshBody(false) JavaScript関数を実行
2. 選択されたMIMEタイプでiframeのsrcを更新
3. ブラウザの履歴を更新（history.replaceState）

**遷移先**: 同一画面（iframe内容が更新）

### 2-ロケール切り替え

**トリガー**: Locale selectボックスの値を変更

**処理内容**:
1. refreshBody(true) JavaScript関数を実行
2. 選択されたロケールでページ全体をリロード

**遷移先**: 同一画面（locale パラメータ付きでリロード）

### 3-EMLダウンロード

**トリガー**: "Download" リンクをクリック

**処理内容**:
1. downloadアクションにリクエスト
2. send_dataでメール全体を.emlファイルとして返却

**レスポンス**: {email_action}.eml ファイルのダウンロード

### 4-添付ファイルダウンロード

**トリガー**: 添付ファイル名リンクをクリック

**処理内容**:
1. Base64エンコードされたデータURLからダウンロード

**レスポンス**: 添付ファイルのダウンロード

## データベース更新仕様

### 操作別データベース影響一覧

本画面はデータベースアクセスを行わない（プレビュークラスの実装による）。

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | データベースアクセスなし |

## メッセージ仕様

| メッセージID | メッセージ種別 | 表示条件 | メッセージ内容 |
|-------------|---------------|---------|--------------|
| MSG-001 | 警告 | メールコンテンツが空の場合 | "You are trying to preview an email that does not have any content." |

## 例外処理

| 例外条件 | 動作 |
|---------|------|
| 指定されたメールアクションが存在しない | AbstractController::ActionNotFound例外を発生 |
| 指定されたMIMEタイプのパートが存在しない | AbstractController::ActionNotFound例外を発生 |
| プレビュークラスが見つからない | AbstractController::ActionNotFound例外を発生 |

## 備考

- 本画面は主に開発環境で使用される
- Content-Security-Policyが無効化されているため、iframeでのメール本文表示が可能
- 複数のI18n.available_localesがある場合のみロケール切り替えUIが表示される
- 添付ファイルはBase64エンコードされたdata:URLとしてリンクが生成される
- HTMLパートとテキストパートの両方を持つメールのみ形式切り替えUIが表示される

---

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

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

### 推奨読解順序

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

Mail::Messageオブジェクトの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | mail gem | 外部ライブラリ | Mail::Messageクラスのヘッダー、パート、添付ファイルの構造 |

**読解のコツ**:
- `header[name]`: 各種ヘッダーフィールドを取得
- `html_part` / `text_part`: マルチパートメールの各パート
- `attachments`: 添付ファイル一覧
- `find_first_mime_type`: 指定MIMEタイプのパートを検索

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

コントローラーアクションの処理フローを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | mailers_controller.rb | `railties/lib/rails/mailers_controller.rb` | previewアクション内でのメールプレビュー処理を理解する |

**主要処理フロー**:
1. **36-37行目**: @email_actionをパスから取得
2. **39-41行目**: email_exists?チェック、@previewcallでメール生成
3. **42-43行目**: 添付ファイルとインライン添付の分離
4. **45-52行目**: partパラメータがある場合、指定MIMEタイプのパートを返却
5. **54-57行目**: パートパラメータがない場合、email.html.erbをレンダリング

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

HTML描画の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | email.html.erb | `railties/lib/rails/templates/rails/mailers/email.html.erb` | テンプレートの構造を理解する |

**主要処理フロー**:
- **1-60行目**: HTMLヘッダーとCSSスタイル
- **62-161行目**: メールヘッダー情報の表示（header要素）
- **117-128行目**: 形式切り替えUI（HTML/テキスト）
- **130-139行目**: ロケール切り替えUI（多言語対応）
- **141-156行目**: 全ヘッダー表示（detailsで折りたたみ）
- **163-170行目**: メール本文iframe
- **172-199行目**: refreshBody JavaScript関数

#### Step 4: ヘルパーメソッドを理解する

コントローラーで定義されたヘルパーメソッドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | mailers_controller.rb | `railties/lib/rails/mailers_controller.rb` | attachment_url、part_query、locale_queryを理解する |

**主要処理フロー**:
- **107-109行目**: `attachment_url` - Base64エンコードのデータURL生成
- **111-113行目**: `part_query` - パート指定クエリパラメータ生成
- **115-117行目**: `locale_query` - ロケール指定クエリパラメータ生成

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

```
ブラウザリクエスト (GET /rails/mailers/preview/{name}/{action})
    │
    ├─ around_action :set_locale
    │      └─ I18n.with_locale(params[:locale])
    │
    ├─ before_action :find_preview
    │      └─ @preview = ActionMailer::Preview.find(...)
    │
    └─ Rails::MailersController#preview
           │
           ├─ @email_action = File.basename(params[:path])
           │
           ├─ @preview.email_exists?(@email_action) チェック
           │
           ├─ @email = @preview.call(@email_action, params)
           │      │
           │      └─ プレビュークラスのメソッドを実行
           │             └─ Mail::Message オブジェクト生成
           │
           ├─ @attachments = attachments_for(@email).reject(&:inline?)
           │
           ├─ @inline_attachments = attachments_for(@email).select(&:inline?)
           │
           ├─ [params[:part] がある場合]
           │      │
           │      └─ 指定MIMEタイプのパートを plain/text で返却
           │
           └─ [params[:part] がない場合]
                  │
                  ├─ @part = find_preferred_part(html, text)
                  │
                  └─ render action: "email"
                         │
                         └─ email.html.erb テンプレート描画
```

### データフロー図

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

HTTPリクエスト ──▶ MailersController#preview
(GET /rails/mailers/preview/{name}/{action})
        │
        │ set_locale でロケール設定
        │
        │ find_preview でプレビュークラス取得
        │
        └──▶ @preview.call(@email_action)
                    │
                    └─ Mail::Message 生成
                           │
                           ├─ ヘッダー情報
                           │    ├─ from, to, cc, bcc
                           │    ├─ subject, date
                           │    └─ その他ヘッダー
                           │
                           ├─ パート情報
                           │    ├─ html_part
                           │    └─ text_part
                           │
                           └─ 添付ファイル
                                                              ↓
                                                    HTML ページ
                                                    (email.html.erb)
                                                         +
                                                    iframe（メール本文）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| mailers_controller.rb | `railties/lib/rails/mailers_controller.rb` | コントローラー | メーラープレビュー画面群のアクション定義 |
| email.html.erb | `railties/lib/rails/templates/rails/mailers/email.html.erb` | テンプレート | メールプレビューの描画テンプレート |
| preview.rb | `actionmailer/lib/action_mailer/preview.rb` | ソース | ActionMailer::Previewクラス定義 |
