# 機能設計書 67-メール配信管理

## 概要

本ドキュメントは、Ghost CMSにおけるメール配信管理機能の設計を記述する。この機能は、トランザクションメール（システムメール）の送信を管理するための基盤機能である。

### 本機能の処理概要

この機能では、パスワードリセット、招待メール、インポート完了通知などのトランザクションメールを、設定されたメールトランスポート（Mailgun、SMTP、direct等）を通じて送信する。

**業務上の目的・背景**：Ghost CMSでは、ユーザー認証、スタッフ招待、システム通知など様々な場面でメール送信が必要となる。この機能は、それらのメール送信を統一的なインターフェースで提供し、複数のメール配信サービスに対応する。

**機能の利用シーン**：
- スタッフユーザーへの招待メール送信
- パスワードリセットメール送信
- インポート処理完了通知
- セキュリティアラート通知

**主要な処理内容**：
1. メールメッセージの作成
2. 送信元アドレスの解決
3. トランスポート選択（Mailgun/SMTP/direct）
4. メール送信実行
5. エラーハンドリング

**関連システム・外部連携**：Mailgun API、SMTP サーバー

**権限による制御**：内部処理のため、直接的な権限制御は適用されない

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 51 | Mailgun設定 | 主機能 | Mailgun APIキー・ドメインの設定 |

## 機能種別

システム基盤 / 外部連携

## 入力仕様

### 入力パラメータ（send）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| subject | string | Yes | メール件名 | 空でないこと |
| html | string | Yes | メール本文（HTML） | 空でないこと |
| to | string | Yes | 宛先アドレス | メールアドレス形式 |
| from | string | No | 送信元アドレス | - |
| replyTo | string | No | 返信先アドレス | - |
| text | string | No | プレーンテキスト本文 | - |
| forceTextContent | boolean | No | テキスト生成抑制フラグ | - |

### 入力データソース

- 設定ファイル（mail設定）
- Settings テーブル（title）
- アプリケーションからの呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| response | object | 送信結果 |
| message | string | 結果メッセージ（direct時） |

### 出力先

- メールサービス（Mailgun/SMTP）
- ログ出力（エラー時）

## 処理フロー

### 処理シーケンス

```
1. メッセージ検証
   └─ subject, html, to の存在確認

2. メッセージ作成
   ├─ 送信元アドレス解決
   ├─ エンコーディング設定（base64）
   └─ ヘッダー設定

3. トランスポート固有設定
   └─ Mailgun: タグ付け、開封トラッキング設定

4. メール送信
   └─ nodemailer経由で送信

5. レスポンス処理
   ├─ direct: pending/errorsチェック
   └─ Mailgun: レスポンスをそのまま返却
```

### フローチャート

```mermaid
flowchart TD
    A[send呼び出し] --> B{必須項目確認}
    B -->|不足| C[EmailError投げる]
    B -->|OK| D[createMessage]
    D --> E[getFromAddress]
    E --> F{Mailgun?}
    F -->|Yes| G[タグ・トラッキング設定]
    F -->|No| H[そのまま続行]
    G --> I[sendMail実行]
    H --> I
    I --> J{成功?}
    J -->|Yes| K{direct?}
    J -->|No| L[EmailError投げる]
    K -->|Yes| M[handleDirectTransportResponse]
    K -->|No| N[response返却]
    M --> O{pending/errors?}
    O -->|あり| L
    O -->|なし| P[メッセージ返却]
    N --> Q[終了]
    P --> Q
    L --> Q
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 必須項目検証 | subject, html, toは必須 | send時 |
| BR-02 | 送信元デフォルト | from未指定時はdefaultFromEmailを使用 | getFromAddress時 |
| BR-03 | 送信者名デフォルト | name未指定時はサイトタイトルを使用 | getFromAddress時 |
| BR-04 | Mailgunタグ付け | Mailgun使用時はghost-email, transactional-emailタグを付与 | send時 |
| BR-05 | 開封トラッキング | email_track_opens設定に従う | Mailgun時 |
| BR-06 | siteIdタグ | hostSettings:siteIdがあればblog-{siteId}タグを追加 | getTags時 |

### 計算ロジック

ドメイン抽出: URLから正規表現 `/^https?://([^/:?#]+)(?:[/:?#]|$)/i` でホスト名を取得

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 設定取得 | settings | SELECT | title, email_track_opens取得 |

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

#### settings

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | key='title' | サイトタイトル | settingsCacheを経由 |
| SELECT | key='email_track_opens' | 開封トラッキング設定 | settingsCacheを経由 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | EmailError（400） | RecipientError | 宛先エラーを返却 |
| - | EmailError（500） | その他の送信エラー | サーバーエラーを返却 |
| - | EmailError | 必須項目不足 | IncompleteMessageDataエラー |

### リトライ仕様

標準のリトライ機能はなし（呼び出し元で実装）

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

データベース操作を伴わないため、トランザクション制御は不要

## パフォーマンス要件

- Mailgun使用時はメトリクス記録（mailgun-send-transactional-mail）
- 送信時間とステータスコードを記録

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

- メール設定は設定ファイルで管理
- 送信元アドレスはemailAddressサービスで検証
- APIキーは設定ファイルに保存（環境変数推奨）

## 備考

- ニュースレター配信は別のemail-serviceを使用
- この機能はトランザクションメール専用

---

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

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

### 推奨読解順序

#### Step 1: サービス構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.js | `ghost/core/core/server/services/mail/index.js` | エクスポート構造 |
| 1-2 | ghost-mailer.js | `ghost/core/core/server/services/mail/ghost-mailer.js` | メインクラス |

**読解のコツ**: GhostMailerクラスがトランスポートを抽象化している。nodemailerの使い方を理解する。

**主要処理フロー（index.js）**:
- **6-9行目**: EmailContentGeneratorの初期化
- **12行目**: GhostMailerのエクスポート
- **14行目**: utils.generateContentのエクスポート

#### Step 2: メイン処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ghost-mailer.js | `ghost/core/core/server/services/mail/ghost-mailer.js` | GhostMailerクラス |

**主要処理フロー**:
- **22-25行目**: getDomain - ドメイン抽出
- **32-51行目**: getFromAddress - 送信元アドレス解決
- **62-77行目**: createMessage - メッセージオブジェクト作成
- **79-91行目**: createMailError - エラーオブジェクト作成
- **93-108行目**: コンストラクタ - トランスポート初期化
- **124-150行目**: send - メイン送信処理
- **152-176行目**: sendMail - 実際の送信とメトリクス
- **178-196行目**: handleDirectTransportResponse - directレスポンス処理
- **198-207行目**: getTags - Mailgunタグ生成

#### Step 3: 送信元アドレス解決を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ghost-mailer.js | `ghost/core/core/server/services/mail/ghost-mailer.js` | getFromAddress関数 |

**主要処理フロー**:
- **33-36行目**: デフォルトアドレスの取得
- **39行目**: emailAddress.service.getAddressFromStringの呼び出し
- **42-45行目**: 送信者名のデフォルト設定

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

```
ghost-mailer.js
    │
    └─ GhostMailer
           │
           ├─ constructor()
           │      └─ nodemailer(transport, options)
           │
           └─ send(message)
                  │
                  ├─ createMessage(message)
                  │      └─ getFromAddress(from, replyTo)
                  │             └─ emailAddress.service
                  │
                  ├─ getTags()（Mailgun時）
                  │
                  └─ sendMail(messageToSend)
                         │
                         └─ transport.sendMail()
                                │
                                ├─ 成功 → metrics.metric()
                                └─ 失敗 → createMailError()
```

### データフロー図

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

message ───────────▶ send() ──────────────▶ 送信結果
 │                        │
 ├─ subject              ├─ createMessage()
 ├─ html                 │      └─ getFromAddress()
 ├─ to                   │
 └─ from (optional)      ├─ sendMail()
                         │      └─ transport.sendMail()
config ────────────▶ │
 │                        │
 └─ mail設定             └─ handleDirectTransportResponse()
                               （direct時）
                                    │
                                    ▼
                               メール配信サービス
                               (Mailgun/SMTP/direct)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ghost-mailer.js | `ghost/core/core/server/services/mail/ghost-mailer.js` | ソース | メインクラス |
| index.js | `ghost/core/core/server/services/mail/index.js` | ソース | エクスポート |
| email-address-parser.js | `ghost/core/core/server/services/email-address/email-address-parser.js` | ソース | アドレスパース |
| email-content-generator.js | `ghost/core/core/server/services/lib/email-content-generator.js` | ソース | コンテンツ生成 |
| @tryghost/nodemailer | node_modules | 外部ライブラリ | nodemailerラッパー |
