# 機能設計書 59-メール送信

## 概要

本ドキュメントは、LEGACY CMSにおけるメール送信機能の設計を定義する。この機能は、システムからメーリングリスト購読者、特定ロールのユーザー、または個別ユーザーに向けてメールを送信するための機能である。

### 本機能の処理概要

**業務上の目的・背景**：CMSを利用したサイト運営において、購読者やユーザーへの情報配信は重要な機能である。この機能により、管理者はニュースレター、お知らせ、イベント情報などを効率的に配信できる。テキスト形式とHTML形式の両方をサポートし、ユーザーの設定に応じて適切な形式で送信することで、多様なメールクライアントに対応する。

**機能の利用シーン**：管理画面でメールを作成・編集後、「Send」ボタンをクリックして送信を実行する。送信前にはテストメール送信機能で内容を確認可能。送信先はメーリングリスト（グループ）、ユーザーロール、個別ユーザーから選択でき、添付ファイルも追加可能。

**主要な処理内容**：
1. 送信確認ダイアログの表示
2. メール内容のバリデーション
3. 送信前のメール情報更新
4. 宛先タイプ別の購読者/ユーザー取得
5. テキスト/HTML形式別のメール生成
6. 添付ファイルの追加
7. Zend_Mail経由でのメール送信
8. 送信ステータスの更新

**関連システム・外部連携**：Zend_Mailコンポーネントによるメール送信。SMTPサーバー設定はレジストリから取得。添付ファイルはassetsテーブル経由で管理。

**権限による制御**：メール送信にはACLで'mmail'および'mmailsend'リソースへのアクセス権限が必要。送信済みメールの再送信は不可。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | お問い合わせ画面 | 補助機能 | お問い合わせ内容をメール送信 |
| 6 | パスワードリセット画面 | 補助機能 | リセットリンクをメール送信 |
| 7 | ユーザー登録画面 | 補助機能 | アカウント有効化メールを送信 |
| 28 | 購読設定画面 | 主機能 | メール購読の設定を変更 |
| 65 | メール編集画面 | 主機能 | メールの編集・送信処理 |
| 67 | グループ管理画面 | 補助機能 | メールグループの管理 |
| 68 | グループ新規作成画面 | 主機能 | 新規グループの作成処理 |
| 69 | グループ詳細画面 | 主機能 | グループの詳細情報を表示 |
| 71 | ロール別メール画面 | 主機能 | ロール別メール送信設定 |
| 72 | ユーザー別メール画面 | 主機能 | ユーザー別メール送信設定 |

## 機能種別

データ処理 / 外部連携（SMTP）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | integer | Yes | メールID | 数値チェック |
| confirm | string | No | 送信確認フラグ（'1'で実行） | 値チェック |
| slave | integer | Yes | 宛先ID（グループ/ロール/ユーザーID） | NotEmpty |
| subject | string | Yes | 件名 | NotEmpty |
| text | string | No | テキスト本文 | allowEmpty |
| html | string | No | HTML本文 | allowEmpty |

### 入力データソース

- URLパラメータ（id, confirm）
- POSTデータ（slave, subject, text, html）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 結果メッセージ | HTML | 送信完了/エラーメッセージとCloseボタン |

### 出力先

- Ajaxダイアログ（dijit.Dialog）内にHTML形式で出力

## 処理フロー

### 処理シーケンス

```
1. ACL権限チェック
   └─ 'mmail' + 'mmailsend'リソースへのアクセス権確認
2. 確認フラグチェック
   └─ confirm=1でなければ確認ダイアログ表示
3. バリデーション実行
   └─ Zend_Filter_Inputで入力検証
4. 送信ステータス確認
   └─ 既に送信済みでないことを確認
5. メール情報更新
   └─ updateMail()で最新内容を保存
6. 宛先タイプ判定
   └─ G(グループ)/R(ロール)/U(ユーザー)で分岐
7. 購読者/ユーザー取得
   └─ 宛先タイプに応じたリスト取得
8. メール形式判定
   └─ text/html両方、htmlのみ、textのみで分岐
9. メール生成・送信
   └─ Zend_Mailで形式別にメール作成・送信
10. 添付ファイル追加
    └─ attachments経由でファイル添付
11. 結果出力
    └─ 送信完了メッセージ表示
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{ACL権限チェック}
    B -->|権限あり| C{confirm=1?}
    B -->|権限なし| D[権限エラー画面へ]
    C -->|No| E[確認ダイアログ表示]
    C -->|Yes| F[バリデーション実行]
    F --> G{バリデーション成功?}
    G -->|No| H[エラーメッセージ表示]
    G -->|Yes| I{送信済み?}
    I -->|Yes| J["Mail Already Sent!" 表示]
    I -->|No| K[メール情報更新]
    K --> L{宛先タイプ判定}
    L -->|G: グループ| M[購読者リスト取得]
    L -->|R: ロール| N[ロール別ユーザー取得]
    L -->|U: ユーザー| O[個別ユーザー取得]
    M --> P[メール送信処理]
    N --> P
    O --> P
    P --> Q["Mail Sent" 表示]
    D --> R[終了]
    E --> R
    H --> R
    J --> R
    Q --> R
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-59-01 | 送信済み再送信不可 | 一度送信したメールは再送信できない | 常時 |
| BR-59-02 | 形式別送信 | テキスト/HTML両方ある場合、ユーザー設定に応じて分割送信 | グループ/ロール宛 |
| BR-59-03 | BCC送信 | 宛先はBCCで追加し、Toはサイトメールアドレス | 常時 |
| BR-59-04 | 添付ファイル | 全形式のメールに同一添付ファイルを追加 | 添付あり時 |

### 計算ロジック

計算ロジックは存在しない。

## データベース操作仕様

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| メール取得 | mail, users | SELECT (JOIN) | メール情報と著者情報を取得 |
| メール更新 | mail | UPDATE | 送信前に最新内容を保存 |
| 購読者取得 | mail_subscriptions, users | SELECT (JOIN) | グループ購読者を取得 |
| ユーザー取得 | users | SELECT | ロール/個別ユーザーを取得 |
| グループ取得 | mail_groups | SELECT | グループ情報を取得 |
| 添付取得 | attachments, assets | SELECT (JOIN) | 添付ファイル情報を取得 |

### テーブル別操作詳細

#### mail

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | mail_slave, mail_subject, mail_text, mail_html, mail_date | 送信前に最新化 | |
| UPDATE | mail_status | 'sent' | 送信完了時 |
| UPDATE | mail_sent | NOW() | 送信日時記録 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 権限エラー | 'mmail'/'mmailsend'アクセス権なし | error/privilegesへフォワード |
| - | バリデーションエラー | 必須項目未入力 | エラーメッセージ表示 |
| - | 送信済みエラー | 既に送信済みのメール | "Mail Already Sent!" 表示 |

### リトライ仕様

メール送信自体のリトライ機能は実装されていない。送信失敗時は例外がスローされる。

## トランザクション仕様

メール情報更新と送信処理は分離されており、明示的なトランザクション制御はない。送信成功後にステータスが更新される設計。

## パフォーマンス要件

- 大量購読者への一斉送信時は処理時間がかかる
- BCCを使用することで送信回数を最小化
- 形式別（テキスト/HTML）に分割送信するためグループ送信時は2回送信される場合あり

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

- CMS_Controller_Action_Adminを継承しており、管理者認証が必須
- ACLによる'mmail' + 'mmailsend'リソースアクセス制御
- Zend_Filter_Inputによる入力検証
- BCCによる宛先プライバシー保護

## 備考

- テスト送信機能（sendtestAction）で自分宛に事前確認可能
- 送信後はmail_statusが'sent'に更新され、以後編集・削除不可
- 936行目にtypo（$htmltmailは$htmlmailの誤り）あり

---

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

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

### 推奨読解順序

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

メール送信に関わるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Mail.php | `application/models/Mail.php` | メール、グループ、購読者のデータ構造 |

**読解のコツ**: mail_typeの値（G=グループ、R=ロール、U=ユーザー）が送信先決定の鍵。fetchSubscriptions、fetchUsersで宛先リストを取得。

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

コントローラの送信アクションを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MailController.php | `application/modules/admin/controllers/MailController.php` | sendActionメソッド（700-1158行目） |

**主要処理フロー**:
1. **700-702行目**: ACL権限チェック
2. **704-706行目**: レイアウト・ビュー無効化
3. **708-710行目**: confirm、idパラメータ取得
4. **712-750行目**: バリデーター定義
5. **763-770行目**: メール情報更新
6. **774-1107行目**: 宛先タイプ別送信処理
7. **774-885行目**: グループ（G）宛送信
8. **887-995行目**: ロール（R）宛送信
9. **997-1105行目**: ユーザー（U）宛送信

#### Step 3: テスト送信機能を理解する

本番送信前の確認機能を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | MailController.php | `application/modules/admin/controllers/MailController.php` | sendtestActionメソッド（512-695行目） |

**主要処理フロー**:
- **586-604行目**: テキスト形式でテストメール送信
- **606-624行目**: HTML形式でテストメール送信

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

```
Admin_MailController::sendAction()
    │
    ├─ ACL::isAllowed('mmail', 'mmailsend')
    │
    ├─ Zend_Filter_Input($filters, $validators, $_POST)
    │
    ├─ Mail::fetchMail($id)
    │
    ├─ Mail::updateMail($params)
    │
    ├─ Attachments::fetchAttachments($params)
    │
    ├─ [mail_type == 'G' の場合]
    │      ├─ Mail::fetchGroup($slave)
    │      ├─ Mail::fetchSubscriptions($params)
    │      └─ Zend_Mail::send()
    │
    ├─ [mail_type == 'R' の場合]
    │      ├─ Mail::fetchUsers($params)
    │      └─ Zend_Mail::send()
    │
    └─ [mail_type == 'U' の場合]
           ├─ Mail::fetchUsers($params)
           └─ Zend_Mail::send()
```

### データフロー図

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

POSTデータ ───▶ MailController     ───▶ メール送信
(id, confirm,      ::sendAction()
 subject, etc.)         │
                        ▼
                   Mail Model
                        │
    ┌───────────────────┼───────────────────┐
    ▼                   ▼                   ▼
mail_groups     mail_subscriptions      users
(グループ情報)    (購読者リスト)       (ユーザー情報)
    │                   │                   │
    └───────────────────┴───────────────────┘
                        │
                        ▼
                   Zend_Mail
                        │
                        ▼
                   SMTPサーバー
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MailController.php | `application/modules/admin/controllers/MailController.php` | コントローラ | メール送信アクションを提供 |
| Mail.php | `application/models/Mail.php` | モデル | メール、グループ、購読者データ操作 |
| Attachments.php | `application/models/Attachments.php` | モデル | 添付ファイル取得 |
| edit.phtml | `application/modules/admin/views/scripts/mail/edit.phtml` | ビュー | メール編集・送信画面 |
