# 通知設計書 8-メーリングリスト配信（グループ宛）

## 概要

本ドキュメントは、メーリングリスト（グループ）の購読者にメールを一斉配信する機能の設計仕様を記載する。

### 本通知の処理概要

本通知は、管理者がメーリングリスト機能を使用して、特定のメーリンググループに登録している購読者に対してメールを一斉配信する機能である。

**業務上の目的・背景**：ニュースレター、お知らせ、マーケティングメールなどを効率的に配信するための機能である。ユーザーは自身の興味に応じてメーリンググループに購読登録し、管理者は購読者に対して一斉にメールを送信できる。テキスト版とHTML版の両対応により、購読者のメール受信形式設定に応じた最適な形式で配信される。大量のメールを効率的に配信するため、BCCを使用した一斉送信が実装されている。

**通知の送信タイミング**：管理画面のメール送信確認ダイアログ（/admin/mail/send）を経てconfirm=1でPOSTリクエストした際に送信される。mail_type='G'の場合にグループ宛配信が実行される。

**通知の受信者**：指定されたメーリンググループに購読登録しているユーザー全員。mail_subscriptionsテーブルとusersテーブルを結合して購読者リストを取得する。

**通知内容の概要**：管理者が作成したメール本文（テキスト版またはHTML版）と添付ファイルが送信される。購読者のuser_mailformat設定に応じて適切な形式で配信される。

**期待されるアクション**：購読者はメールを受信し、内容を確認する。必要に応じて記載されたURLにアクセスするなどのアクションを行う。

## 通知種別

メール

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（BCC使用の一斉送信） |
| 優先度 | 中 |
| リトライ | 無 |

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

1. mail_subscriptionsテーブルから指定グループIDに購読登録しているユーザーを取得
2. usersテーブルと結合してメールアドレスと受信形式を取得
3. user_mailformatがtextのユーザーにはテキストメール、htmlのユーザーにはHTMLメールを送信
4. 両形式が設定されている場合は形式別に2回送信、片方のみの場合は全購読者に同一形式で送信

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | {registry.site.site.email} |
| 送信元名称 | {registry.site.site.name} |
| 宛先（To） | {registry.site.site.email}（グループ名表示） |
| 件名 | {mail_subject}（フォーム入力値） |
| 形式 | テキスト/HTML（購読者設定に応じて） |

### 本文テンプレート

本文はフォームから入力された内容がそのまま使用される。グループのデフォルトテンプレート（mgroup_text, mgroup_html）を初期値として使用可能。

```
{mail_text または mail_html の内容}
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| {asset_name}.{asset_extension} | 各種 | メールに添付ファイルが設定されている場合 | Attachmentsモデルで取得した添付ファイル |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| mail_subject | メール件名 | フォーム入力（POST） | Yes |
| mail_text | テキスト本文 | フォーム入力（POST） | No |
| mail_html | HTML本文 | フォーム入力（POST）+ html_entity_decode | No |
| mgroup_title | グループ名 | mail_groups.mgroup_title | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | 送信ボタン押下 | confirm=1かつ管理者権限ありかつmail_type='G'かつメール未送信 | 管理画面の/admin/mail/send/id/{id}/confirm/1/にPOST |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 権限不足 | 操作者にmmailまたはmmailsend権限がない場合 |
| メールID未指定 | URLパラメータにidが含まれていない場合 |
| 確認未完了 | confirm=1でない（初回表示時）場合 |
| 送信済みメール | mail_status='sent'の場合 |
| バリデーションエラー | 宛先または件名が未入力の場合 |
| mail_type不一致 | mail_type='G'でない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[送信リクエスト] --> B{権限チェック}
    B -->|権限なし| C[権限エラー画面]
    B -->|権限あり| D{confirm=1?}
    D -->|No| E[確認ダイアログ表示]
    D -->|Yes| F{バリデーションチェック}
    F -->|エラー| G[エラーメッセージ表示]
    F -->|成功| H[メール情報取得]
    H --> I{mail_status = sent?}
    I -->|Yes| J[送信済みエラー表示]
    I -->|No| K[メール情報更新]
    K --> L{mail_type = G?}
    L -->|No| M[他の配信タイプ処理]
    L -->|Yes| N[グループ情報取得]
    N --> O{text & html 両方あり?}
    O -->|Yes| P[テキスト購読者取得/送信]
    P --> Q[HTML購読者取得/送信]
    O -->|htmlのみ| R[全購読者にHTML送信]
    O -->|textのみ| S[全購読者にテキスト送信]
    Q --> T[完了メッセージ表示]
    R --> T
    S --> T
    C --> U[終了]
    E --> U
    G --> U
    J --> U
    T --> U
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| mail | メール情報取得 | Mailモデル経由 |
| mail_groups | グループ情報取得 | Mailモデル経由 |
| mail_subscriptions | 購読者リスト取得 | Mailモデル経由 |
| users | 購読者メールアドレス取得 | JOIN |
| assets | 添付ファイル情報取得 | Attachmentsモデル経由 |

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

#### mail

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| mail_id | メール識別 | WHERE mail_id = ? |
| mail_type | 配信タイプ判定 | ='G'の場合グループ配信 |
| mail_slave | グループID | グループ情報取得に使用 |
| mail_subject | メール件名 | Mail::fetchMail() |
| mail_text | テキスト本文 | Mail::fetchMail() |
| mail_html | HTML本文 | Mail::fetchMail() |
| mail_status | 送信ステータス | Mail::fetchMail() |

#### mail_groups

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| mgroup_id | グループID | WHERE mgroup_id = mail_slave |
| mgroup_title | グループ名（To表示用） | Mail::fetchGroup() |

#### mail_subscriptions + users

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| user_email | 送信先メールアドレス | JOIN ON user_id = msub_user |
| user_alias | 送信先表示名 | WHERE msub_group = ? |
| user_mailformat | メール受信形式 | text/html判定 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| mail | UPDATE | メール内容の更新（送信前に最新内容を保存） |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 権限エラー | mmailまたはmmailsend権限がない | 権限エラー画面（privileges）にフォワード |
| 宛先未入力 | slaveパラメータが空 | エラーメッセージ「To is required」を表示 |
| 件名未入力 | subjectパラメータが空 | エラーメッセージ「Subject is required」を表示 |
| 送信済み | mail_status='sent' | エラーメッセージ「Mail Already Sent!」を表示 |
| メール送信失敗 | SMTP接続エラー等 | Zend_Mailが例外をスロー |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

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

### 配信時間帯

配信時間帯の制限は設けられていない。24時間いつでも送信可能。

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

- BCCを使用しているため、購読者同士のメールアドレスは相互に見えない
- 管理者権限（mmail + mmailsend）による操作制限あり
- 確認ダイアログによる誤操作防止機能あり
- 添付ファイルは$syspathからの相対パスで取得されるため、パストラバーサルのリスクに注意
- HTML本文にはhtml_entity_decodeが適用されるため、XSS攻撃のリスクを含む可能性
- 大量送信時のSMTPサーバー負荷に注意

## 備考

- 本機能はZend Framework 1.x系のZend_Mailコンポーネントを使用している
- BCCを使用した一斉送信のため、メールサーバーの制限により分割送信が必要な場合がある
- テキスト版とHTML版の両方が設定されている場合、購読者の設定に応じて適切な形式で送信
- 送信完了後のmail_status更新処理が実装されていない（要確認）
- 送信設定はレジストリ（`$registry->mail`）で管理されるトランスポート設定に依存する

---

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

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

### 推奨読解順序

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

まず、メーリングリスト配信に必要なデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | mail テーブル | データベース | mail_id, mail_type, mail_slave の構造 |
| 1-2 | mail_groups テーブル | データベース | mgroup_id, mgroup_title の構造 |
| 1-3 | mail_subscriptions テーブル | データベース | msub_group, msub_user の構造 |
| 1-4 | users テーブル | データベース | user_email, user_mailformat の構造 |

**読解のコツ**: mail_type='G'はグループ配信、mail_slaveがグループIDを示す。

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

処理の起点となるコントローラーとアクションを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MailController.php | `application/modules/admin/controllers/MailController.php` | sendAction()メソッドがエントリーポイント |

**主要処理フロー**:
1. **行700**: `sendAction()`メソッド開始
2. **行702**: 権限チェック（mmail AND mmailsend）
3. **行710**: confirm=1かつID存在チェック
4. **行752-771**: メール情報取得・更新
5. **行774**: mail_type='G'判定
6. **行776**: グループ情報取得
7. **行778-885**: text/html両方、htmlのみ、textのみの3パターンで送信処理

#### Step 3: Mailモデルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Mail.php | `application/models/Mail.php` | fetchSubscriptions(), fetchGroup()メソッド |

**主要処理フロー**:
- **行230-243**: fetchSubscriptions() - 購読者リスト取得
- **行290-304**: fetchGroup() - グループ情報取得

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

```
Admin_MailController::sendAction()
    │
    ├─ ACL権限チェック (mmail AND mmailsend)
    │
    ├─ Zend_Filter_Input (バリデーション)
    │
    ├─ Mail::fetchMail() (メール情報取得)
    │
    ├─ Attachments::fetchAttachments() (添付ファイル取得)
    │
    ├─ Mail::updateMail() (メール情報更新)
    │
    ├─ Mail::fetchGroup() (グループ情報取得)
    │
    ├─ Mail::fetchSubscriptions() (購読者リスト取得)
    │      └─ format='text' または 'html' でフィルタ
    │
    └─ Zend_Mail (一斉メール送信)
           ├─ setBodyText() または setBodyHtml()
           ├─ addTo() (サイトメールアドレス + グループ名)
           ├─ setSubject()
           ├─ setFrom()
           ├─ addBcc() (購読者をBCCで追加 - ループ)
           ├─ createAttachment() (ループ)
           └─ send()
```

### データフロー図

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

フォームデータ ─────▶ 権限チェック ──────────▶ エラー/続行判定
(slave, subject,            │
text, html)                 ▼
                     mail_type判定
                           │
                           ▼
                     グループ情報取得
                           │
                           ▼
                     購読者リスト取得
                     (format別にフィルタ)
                           │
              ┌────────────┴────────────┐
              ▼                          ▼
         text購読者                 html購読者
         テキストメール             HTMLメール
              │                          │
              └────────────┬─────────────┘
                           ▼
                     BCC一斉送信 ────────▶ 購読者メールアドレス
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MailController.php | `application/modules/admin/controllers/MailController.php` | ソース | メール送信処理のコントローラー |
| Mail.php | `application/models/Mail.php` | ソース | メール・購読者情報の取得モデル |
| Attachments.php | `application/models/Attachments.php` | ソース | 添付ファイル情報の取得モデル |
| CMS_Controller_Action_Admin | `library/CMS/Controller/Action/Admin.php` | ソース | 管理画面コントローラーの基底クラス |
| edit.phtml | `application/modules/admin/views/scripts/mail/edit.phtml` | テンプレート | メール編集画面のビュー |
