# 画面設計書 56-メール通知（HTML - Zurb 2）

## 概要

本ドキュメントは、Symfony 8.1のTwig Bridgeが提供するZurb 2（Foundation for Emails 2）フレームワーク対応のHTML形式メール通知テンプレート（`zurb_2/notification/body.html.twig`）の画面設計書である。このテンプレートは、Zurb Foundation for Emails 2フレームワークのInkyマークアップ言語を使用してレスポンシブなHTMLメールを生成する。デフォルトテーマ（No.54）の実質的なレイアウト定義元であり、Symfonyのメール通知機能の中核テンプレートである。

### 本画面の処理概要

**業務上の目的・背景**：HTMLメールのレンダリングは、Webページとは異なりメールクライアントごとのHTML/CSS対応の差異が大きく、レスポンシブなメールレイアウトの構築は複雑な作業である。Zurb Foundation for Emails 2は、この課題を解決するために開発されたメール特化のフレームワークであり、Inkyと呼ばれる簡潔なマークアップ言語を使用してメールHTMLを生成する。本テンプレートは、Inkyマークアップと`inky_to_html`Twigフィルタを組み合わせることで、シンプルなコードからメールクライアント互換のHTMLテーブルレイアウトを自動生成する。さらに`inline_css`フィルタにより、`<style>`タグのCSSをHTML要素のインラインスタイルに変換し、メールクライアントでの表示互換性を向上させる。

**画面へのアクセス方法**：本テンプレートはWebブラウザでアクセスするものではなく、メールクライアントで受信・表示される。`NotificationEmail`クラスの`theme()`メソッドで`zurb_2`を指定するか、デフォルトテーマ（`default`テーマがこのテンプレートを継承）経由で使用される。

**主要な操作・処理内容**：
1. InkyマークアップからHTMLへの変換 - `{% apply inky_to_html|inline_css %}`ディレクティブにより、Inkyの`<container>`、`<row>`、`<columns>`、`<button>`、`<spacer>`等のマークアップがメール互換のHTMLテーブルに変換される
2. CSSインライン化 - `<style>`ブロック内のCSS（`main.css`と`local.css`）が各HTML要素のstyle属性にインラインで適用される
3. 重要度に応じたスタイル切替 - `importance`変数の値に基づいてコンテナの上部ボーダー色を切替える（urgent=赤、high=黄、その他=グレー）
4. メール件名と重要度ラベルの表示 - leadブロックで重要度ラベル（大文字）とメール件名を表示する
5. マルチフォーマットコンテンツ - Markdown、生HTML、プレーンテキストの3形式に対応したコンテンツ表示
6. CTAボタンの表示 - Inkyの`<button>`タグでアクションボタンを生成する
7. 例外通知の表示 - 例外スタックトレースが添付されている場合のメッセージ表示
8. フッターセクションの表示 - セカンダリラッパーでフッターテキストを表示する

**画面遷移**：メール内のCTAボタン（`<button href="...">`）をクリックすると、`action_url`で指定されたURLに遷移する。

**権限による表示制御**：`importance`変数がnullの場合、重要度ラベルは非表示になる。`footer_text`変数がnullの場合、フッターセクションは非表示になる。`NotificationEmail::markAsPublic()`で両変数をnullに設定でき、一般ユーザー向けの通知メールとして利用できる。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 41 | Notifier | 主機能 | Notifierコンポーネントからのメール通知トリガーによるZurb 2対応HTMLメールテンプレートのレンダリング |
| 40 | Mailer | 補助機能 | Mailerコンポーネントによるメール送信処理 |
| 42 | Mime | 補助機能 | MIMEメッセージとしてのHTMLメール本文構成 |
| 36 | Twig Bridge | 主機能 | Twig Bridgeのメール通知テンプレート（Zurb 2スタイル）によるHTMLレンダリング |

## 画面種別

メールテンプレート（HTML形式メール通知 - Zurb 2スタイル）

## URL/ルーティング

本テンプレートはWebルーティングではなく、Twigテンプレートパスで参照される。

| パス | 説明 |
|-----|------|
| `@email/zurb_2/notification/body.html.twig` | Zurb 2テーマのHTMLメール通知テンプレート |

## 入出力項目

| 変数名 | 型 | 必須 | デフォルト値 | 説明 |
|--------|-----|------|-------------|------|
| email.subject | string | Yes | - | メール件名 |
| importance | string/null | No | `low` | 重要度（urgent/high/medium/low/null） |
| content | string | No | `''` | メール本文コンテンツ |
| markdown | bool | No | `false` | Markdown形式のコンテンツかどうか |
| raw | bool | No | `false` | HTMLをエスケープせずに出力するかどうか |
| action_url | string/null | No | `null` | CTAボタンのリンク先URL |
| action_text | string/null | No | `null` | CTAボタンのテキスト |
| exception | bool | No | `false` | 例外スタックトレースが添付されているかどうか |
| footer_text | string/null | No | `Notification email sent by Symfony` | フッターテキスト |

## 表示項目

| 表示セクション | Inky要素 | 変換後HTML | 説明 |
|---------------|---------|-----------|------|
| スペーサー（上部） | `<spacer size="32">` | テーブルベースのスペーサー | 上部マージン |
| ボディラッパー | `<wrapper class="body">` | テーブルラッパー | メール全体のラッパー |
| コンテナ | `<container class="body_{importance}">` | テーブルコンテナ（580px幅） | 重要度に応じたボーダー色付きコンテナ |
| 重要度ラベル | `<small><strong>` | `<small><strong>URGENT</strong></small>` | importance値を大文字で表示 |
| メール件名 | `<p class="lead">` | フォントサイズ20pxの段落 | メール件名 |
| コンテンツ本文 | Markdown/raw/nl2br | テキストコンテンツ | 3形式対応 |
| CTAボタン | `<button href="...">` | テーブルベースのボタン | アクションリンクボタン |
| 例外通知 | `<p><em>` | イタリック段落 | 例外添付通知 |
| フッター | `<wrapper class="secondary">` | セカンダリ背景のラッパー | フッターテキスト |

## イベント仕様

### 1-Inky変換とCSSインライン化

テンプレート全体が`{% apply inky_to_html|inline_css %}`ブロックで囲まれている。レンダリング時に以下の順序で変換が行われる：
1. Twigブロックのレンダリング（変数の展開、条件分岐の評価）
2. `inky_to_html`フィルタ - Inkyマークアップ（`<container>`、`<row>`、`<columns>`等）をメール互換のHTMLテーブルに変換
3. `inline_css`フィルタ - `<style>`タグ内のCSSを各HTML要素のstyle属性にインラインで適用

### 2-CSSの読み込み

`source()`関数を使用して2つのCSSファイルを`<style>`タグ内に直接挿入する：
- `@email/zurb_2/main.css` - Foundation for Emails 2のベースCSS（グリッド、タイポグラフィ、ボタン等、1786行）
- `@email/zurb_2/notification/local.css` - 通知固有のCSS（body_alert/body_warning/body_defaultの上部ボーダー色、20行）

### 3-重要度に応じたコンテナスタイル

`importance`変数の値に基づいてコンテナクラスが決定される：
- `urgent` -> `body_alert`（`border-top: 8px solid #ec5840` - 赤色）
- `high` -> `body_warning`（`border-top: 8px solid #ffae00` - 黄色）
- `medium`/`low`/null/その他 -> `body_default`（`border-top: 8px solid #aaaaaa` - グレー）

### 4-コンテンツ形式の分岐

`markdown`変数と`raw`変数の組み合わせで本文レンダリングが決定される：
- `markdown == true`: `content_markdown.html.twig`をインクルードし、`markdown_to_html`フィルタでMarkdownをHTMLに変換
- `raw == true`: `content|raw`でHTMLをエスケープせず出力
- それ以外: `content|nl2br`で改行をBRタグに変換

### 5-Twigブロックによるカスタマイズポイント

テンプレートは以下のTwigブロックを定義しており、子テンプレートで個別にオーバーライド可能：
- `style` - CSSスタイルのカスタマイズ
- `lead` - 件名・重要度表示のカスタマイズ
- `content` - 本文のカスタマイズ
- `action` - CTAボタンのカスタマイズ
- `exception` - 例外表示のカスタマイズ
- `footer` - フッターのカスタマイズ
- `footer_content` - フッターコンテンツのカスタマイズ

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

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

本テンプレートはメールのHTML生成のみを担当し、データベース操作は行わない。

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

## メッセージ仕様

| メッセージ種別 | 表示条件 | 表示形式 | 内容 |
|---------------|---------|---------|------|
| 重要度ラベル | `importance is not null` | `<small><strong>URGENT</strong></small>` 等 | 重要度を大文字で表示 |
| 例外通知メッセージ | `exception == true` | `<p><em>Exception stack trace attached.</em></p>` | 例外スタックトレースが添付されている旨の通知 |
| フッターテキスト | `footer_text is defined and footer_text is not null` | `<p><small>...</small></p>` | カスタマイズ可能なフッターテキスト |

## 例外処理

- `NotificationEmail`クラスのコンストラクタで`twig/cssinliner-extra`（`CssInlinerExtension`）および`twig/inky-extra`（`InkyExtension`）パッケージの存在を検証し、不足時に`LogicException`をスローする
- `markdown()`メソッドで`twig/markdown-extra`（`MarkdownExtension`）パッケージの存在を検証し、不足時に`LogicException`をスローする

## 備考

- Inkyマークアップ言語はZurb Foundation for Emails 2で採用されたDSLであり、`<container>`、`<row>`、`<columns>`、`<button>`、`<spacer>`等の独自タグをメール互換のHTMLテーブルに変換する
- Foundation for Emails 2のベースCSS（`main.css`）はMITライセンスで提供されている（v2.4.0ベース）
- CSSインライン化は、多くのメールクライアント（特にGmail）が`<style>`タグを無視するため、必須の処理である
- レスポンシブ対応は、596px以下のブレークポイントで`@media`クエリにより実現される
- `content_markdown.html.twig`は`{{ content|markdown_to_html }}`の1行のみで、`twig/markdown-extra`パッケージのフィルタを使用する
- デフォルトテーマ（No.54）はこのテンプレートを1行で継承しているため、実質的に同一のレイアウトが使用される

---

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

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

### 推奨読解順序

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

`NotificationEmail`クラスのコンテキスト変数とテンプレート解決の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | NotificationEmail.php | `src/Symfony/Bridge/Twig/Mime/NotificationEmail.php` | テンプレート変数のデフォルト値（行33-42）、`getHtmlTemplate()`（行168-175）、`theme()`メソッド（行152-157）を確認。重要度定数（行27-30）も確認する |

**読解のコツ**: `NotificationEmail`は`TemplatedEmail`を継承しており、`context()`メソッド（行180-195）で内部コンテキストと親コンテキストを分離管理している点に注意する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | body.html.twig（zurb_2） | `src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/notification/body.html.twig` | テンプレート本体（67行）。Inkyマークアップの全体構造を把握する |

**主要処理フロー**:
1. **行1**: `{% apply inky_to_html|inline_css %}` - Inky変換とCSSインライン化の開始
2. **行5-8**: `{% block style %}` - CSSファイルの読み込み（`source()`関数）
3. **行12**: `<spacer size="32">` - 上部スペーサー（32px）
4. **行13**: `<wrapper class="body">` - ボディラッパー
5. **行14**: `<container class="body_{{ ... }}">` - 重要度に応じたコンテナクラスの動的生成
6. **行16-17**: `<row><columns large="12" small="12">` - 12カラム全幅のコンテンツ領域
7. **行18-23**: `{% block lead %}` - 重要度ラベルとメール件名
8. **行25-31**: `{% block content %}` - マルチフォーマット対応コンテンツ
9. **行33-38**: `{% block action %}` - CTAボタン
10. **行40-45**: `{% block exception %}` - 例外通知
11. **行49-62**: `<wrapper class="secondary">` / `{% block footer %}` - フッターセクション
12. **行67**: `{% endapply %}` - Inky変換の終了

#### Step 3: CSSスタイルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | main.css | `src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/main.css` | Foundation for Emails 2ベースCSS。グリッドシステム（large-1〜large-12）、ボタン、タイポグラフィ、レスポンシブ対応（@media max-width: 596px） |
| 3-2 | local.css | `src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/notification/local.css` | 通知固有CSS。body_alert（赤#ec5840）、body_warning（黄#ffae00）、body_default（グレー#aaaaaa）の上部ボーダー |

#### Step 4: Markdownコンテンツ変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | content_markdown.html.twig | `src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/notification/content_markdown.html.twig` | 1行のみ。`{{ content|markdown_to_html }}`でMarkdownをHTMLに変換 |

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

```
NotificationEmail::send()
    |
    +-- Mailer（メール送信処理）
    |       |
    |       +-- BodyRenderer（テンプレートレンダリング）
    |               |
    |               +-- Twig Environment
    |                       |
    |                       +-- body.html.twig（zurb_2）
    |                       |       |
    |                       |       +-- {% apply inky_to_html|inline_css %}
    |                       |       |       |
    |                       |       |       +-- InkyExtension（Inkyマークアップ -> HTMLテーブル変換）
    |                       |       |       +-- CssInlinerExtension（CSS -> インラインスタイル変換）
    |                       |       |
    |                       |       +-- source('@email/zurb_2/main.css')（1786行）
    |                       |       +-- source('@email/zurb_2/notification/local.css')（20行）
    |                       |       +-- content_markdown.html.twig（Markdown時）
    |                       |
    |                       +-- NotificationEmail::getContext()
    |                               |
    |                               +-- importance, content, action_url, action_text,
    |                                   exception, markdown, raw, footer_text
```

### データフロー図

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

NotificationEmail                   body.html.twig (zurb_2)             レスポンシブ
├── importance                       |                                  HTMLメール
├── content                          +-- Twigレンダリング               ├── テーブルベースレイアウト
├── markdown/raw                     |   (変数展開、条件分岐)           ├── インラインCSS
├── action_url/text                  |                                  ├── 重要度ボーダー
├── exception                        +-- Inky変換                       ├── CTAボタン
├── footer_text                      |   (container/row/columns         ├── フッター
└── email.subject                    |    -> table/tr/td)               └── レスポンシブ対応
                                     |
                                     +-- CSSインライン化
main.css (1786行)                    |   (style -> inline style)
local.css (20行)                     |
                                     +---> 最終HTMLメール本文
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| body.html.twig（zurb_2） | `src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/notification/body.html.twig` | テンプレート | Zurb 2テーマHTMLメールレイアウト本体（67行） |
| body.html.twig（default） | `src/Symfony/Bridge/Twig/Resources/views/Email/default/notification/body.html.twig` | テンプレート | デフォルトテーマ（本テンプレートを継承、1行） |
| content_markdown.html.twig | `src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/notification/content_markdown.html.twig` | テンプレート | Markdownコンテンツ変換（1行） |
| main.css | `src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/main.css` | スタイルシート | Foundation for Emails 2ベースCSS（1786行） |
| local.css | `src/Symfony/Bridge/Twig/Resources/views/Email/zurb_2/notification/local.css` | スタイルシート | 通知固有CSS（20行） |
| NotificationEmail.php | `src/Symfony/Bridge/Twig/Mime/NotificationEmail.php` | ソース | 通知メールクラス（281行） |
