# 通知設計書 48-Mail Sent

## 概要

本ドキュメントは、ShopwareにおけるMailSentEventの仕様を定義する設計書である。これはメール通知ではなく、メール送信完了後に発火されるイベント通知であり、開発者が送信されたメールの情報をログ記録や後処理に使用するためのフックポイントを提供する機能について記載する。

### 本通知の処理概要

本イベントは、MailServiceがメールの送信を正常に完了した直後に発火されるシステムイベントである。このイベントは読み取り専用の性質を持ち、送信されたメールの内容（件名、受信者、本文）を取得できる。主にログ記録、監査、統計収集、外部システム連携などの後処理に使用される。

**業務上の目的・背景**：メール送信の監査ログ、送信統計の収集、CRMシステムへの連携、マーケティング分析など、送信されたメールの情報を活用する多くのユースケースがある。本イベントは、これらの後処理をメール送信パイプラインから分離し、疎結合なシステム設計を可能にする。

**通知の送信タイミング**：MailService::send()メソッド内で、MailSender::send()が正常に完了した直後に発火される。送信エラーの場合は発火されない。

**通知の受信者**：イベントリスナーとして登録されたPHPクラス。プラグインやカスタムコードからEventSubscriberとして登録する。

**通知内容の概要**：送信されたメールの件名、受信者リスト、本文（HTML/テキスト）、Contextオブジェクト、トリガーイベント名が含まれる。

**期待されるアクション**：イベントリスナーは送信情報を取得し、ログ記録、統計更新、外部APIへの通知などを行う。本イベントは読み取り専用のため、メール内容の変更は不可。

## 通知種別

イベント通知（システムイベント）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| イベント方式 | 同期（EventDispatcher） |
| 発火タイミング | メール送信成功後 |
| 伝播停止 | 意味なし（送信完了後） |

### イベントリスナー登録方法

```php
use Shopware\Core\Content\MailTemplate\Service\Event\MailSentEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class MyMailSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            MailSentEvent::class => 'onMailSent',
        ];
    }

    public function onMailSent(MailSentEvent $event): void
    {
        // 送信情報をログ記録
        $subject = $event->getSubject();
        $recipients = $event->getRecipients();
        $contents = $event->getContents();

        // ログ処理、統計更新など
    }
}
```

## イベントプロパティ

### イベントクラス

| プロパティ | 型 | 説明 | 変更可能 |
|-----------|-----|------|---------|
| subject | string | メール件名 | No（readonly） |
| recipients | array | 受信者リスト | No（readonly） |
| contents | array | 本文（text/html, text/plain） | No（readonly） |
| context | Context | Shopwareコンテキスト | No |
| eventName | string|null | トリガーイベント名 | No |

### recipients配列の構造

```php
[
    'customer@example.com' => 'Customer Name',
    'admin@example.com' => 'Admin Name',
]
```

### contents配列の構造

```php
[
    'text/html' => '<html>...</html>',
    'text/plain' => 'Plain text content...',
]
```

## テンプレート変数

本イベントはメールテンプレートを使用しないため、該当なし。（メール送信完了後のイベント）

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 発火条件 | 説明 |
|------------|----------------|---------|------|
| MailService | send()メソッド | 送信成功 | MailSender::send()成功後 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 送信失敗 | メール送信が失敗した場合はMailSentEventは発火されない |
| 前段イベントで停止 | MailBeforeSentEvent等で伝播停止された場合 |

## 処理フロー

### イベントフロー

```mermaid
flowchart TD
    A[MailService::send] --> B[MailBeforeValidateEvent発火]
    B --> C[バリデーション実行]
    C --> D[Emailオブジェクト作成]
    D --> E[MailBeforeSentEvent発火]
    E --> F{伝播停止?}
    F -->|Yes| G[return null]
    F -->|No| H[MailSender::send実行]
    H --> I{送信成功?}
    I -->|No| J[MailErrorEvent発火]
    I -->|Yes| K[MailSentEvent生成]
    K --> L[EventDispatcher::dispatch]
    L --> M[リスナー1: ログ記録]
    M --> N[リスナー2: 統計更新]
    N --> O[リスナー3: CRM連携]
    O --> P[return Email]
    J --> Q[return null]
    G --> Q
    P --> R[終了]
    Q --> R
```

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

### 参照テーブル一覧

本イベント自体はデータベースを参照しない。

### 更新テーブル一覧

本イベント自体はデータベースを更新しない。リスナーの実装によりlog_entryテーブル等への書き込みが行われる可能性がある。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| リスナー例外 | イベントリスナー内で例外発生 | 例外伝播（メール送信自体は完了済み） |

### リトライ仕様

本イベントはリトライ対象外。送信完了後の通知のため。

## 配信設定

### レート制限

本イベントにレート制限なし。

### 配信時間帯

制限なし。メール送信完了時に即座に発火。

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

- 送信されたメール本文にセンシティブ情報が含まれる可能性があるため、ログ出力時は注意
- 受信者情報の取り扱いに注意（個人情報保護）
- 外部システム連携時は適切な認証・暗号化を行う

## 備考

- イベント名定数：MailSentEvent::EVENT_NAME = 'mail.sent'
- LogAwareインターフェース実装によりMonolog経由でログ出力可能（Level::Info）
- FlowEventAware実装によりFlowビルダーでの利用も可能

---

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

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

### 推奨読解順序

#### Step 1: イベントクラスを理解する

イベントクラスの構造とインターフェースを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MailSentEvent.php | `src/Core/Content/MailTemplate/Service/Event/MailSentEvent.php` | イベント名（20行目）、コンストラクタ（26-32行目）、getter群 |

**読解のコツ**: LogAware, ScalarValuesAware, FlowEventAwareを実装。subject, recipients, contentsは全てreadonly。送信完了後の読み取り専用イベント。

#### Step 2: イベント発火箇所を理解する

MailServiceでのイベント発火タイミングを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MailService.php | `src/Core/Content/Mail/Service/MailService.php` | send()メソッド内（123-129行目）でのイベント発火 |

**主要処理フロー**:
1. **110行目**: mailSender->send($mail) - 実際の送信
2. **123行目**: MailSentEvent生成
3. **124行目**: subject - $data['subject']
4. **125行目**: recipients - $data['recipients']
5. **126行目**: contents - ['text/html' => $mail->getHtmlBody(), 'text/plain' => $mail->getTextBody()]
6. **128行目**: eventName - $templateData['eventName']
7. **129行目**: eventDispatcher->dispatch()

#### Step 3: ログデータ出力を理解する

LogAwareインターフェースの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | MailSentEvent.php | `src/Core/Content/MailTemplate/Service/Event/MailSentEvent.php` | getLogData()（86-94行目）、getLogLevel()（96-99行目） |

**ログデータ構造**:
```php
[
    'eventName' => $this->eventName,
    'subject' => $this->subject,
    'recipients' => $this->recipients,
    'contents' => $this->contents,
]
```

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

```
MailService::send($data, $context, $templateData)
    │
    ├─ MailBeforeValidateEvent dispatch
    │
    ├─ dataValidator->validate()
    │
    ├─ createMail() - Emailオブジェクト作成
    │
    ├─ MailBeforeSentEvent dispatch
    │
    ├─ mailSender->send($mail) - 実際の送信
    │      │
    │      └─ [成功時のみ続行]
    │
    ├─ new MailSentEvent(
    │      $data['subject'],
    │      $data['recipients'],
    │      ['text/html' => ..., 'text/plain' => ...],
    │      $context,
    │      $eventName
    │  )
    │
    └─ eventDispatcher->dispatch(MailSentEvent)
           │
           ├─ EventSubscriber A: onMailSent()
           │      └─ ログ記録
           │
           ├─ EventSubscriber B: onMailSent()
           │      └─ 統計更新
           │
           └─ EventSubscriber C: onMailSent()
                  └─ CRM連携
```

### データフロー図

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

送信完了メール情報               MailSentEvent                        読み取り専用データ
  │                                  │                                    │
  ├─ subject                         ├─ EventDispatcher                   ├─ getSubject()
  ├─ recipients                      │                                    ├─ getRecipients()
  └─ contents                        ├─ Subscribers                       └─ getContents()
     (html/plain)                    │    └─ 後処理のみ
                                     │
                                     └─ LogAware
                                          └─ Monolog経由ログ出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MailSentEvent.php | `src/Core/Content/MailTemplate/Service/Event/MailSentEvent.php` | ソース | イベントクラス定義 |
| MailService.php | `src/Core/Content/Mail/Service/MailService.php` | ソース | イベント発火箇所 |
| BusinessEventRegistry.php | `src/Core/Framework/Event/BusinessEventRegistry.php` | ソース | イベント登録 |
| LogAware.php | `src/Core/Framework/Log/LogAware.php` | インターフェース | ログ出力インターフェース |
