# 通知設計書 49-Mail Error

## 概要

本ドキュメントは、ShopwareにおけるMailErrorEventの仕様を定義する設計書である。これはメール通知ではなく、メール送信エラー発生時に発火されるイベント通知であり、開発者がエラーハンドリング、ログ記録、アラート通知などを行うためのフックポイントを提供する機能について記載する。

### 本通知の処理概要

本イベントは、MailServiceがメール送信処理中にエラーを検出した際に発火されるシステムイベントである。SMTP接続エラー、テンプレートレンダリングエラー、バリデーションエラーなど、メール送信パイプラインの各段階で発生するエラーをキャプチャし、適切なエラーハンドリングを可能にする。

**業務上の目的・背景**：ECシステムにおいてメール送信の失敗は重大な問題となりうる（注文確認メールが届かない、パスワードリセットができないなど）。本イベントにより、エラー発生時に即座に管理者へ通知したり、代替手段を講じたり、詳細なエラーログを記録することが可能になる。

**通知の送信タイミング**：MailService::send()メソッド内で、各種エラーが発生した時点で発火される。具体的には、送信元メールアドレス未設定、テンプレートレンダリング失敗、SMTP送信失敗などの各エラー発生時。

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

**通知内容の概要**：例外オブジェクト（Throwable）、エラーメッセージ、テンプレート情報、テンプレートデータ、ログレベルが含まれる。

**期待されるアクション**：イベントリスナーはエラー情報を取得し、管理者への通知、詳細ログの記録、代替処理の実行などを行う。

## 通知種別

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

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| イベント方式 | 同期（EventDispatcher） |
| 発火タイミング | メール送信エラー発生時 |
| ログレベル | Error（デフォルト）またはWarning、Debug |

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

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

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

    public function onMailError(MailErrorEvent $event): void
    {
        $throwable = $event->getThrowable();
        $message = $event->getMessage();
        $template = $event->getTemplate();
        $logLevel = $event->getLogLevel();

        // エラーハンドリング、管理者通知、ログ記録など
    }
}
```

## イベントプロパティ

### イベントクラス

| プロパティ | 型 | 説明 | 変更可能 |
|-----------|-----|------|---------|
| context | Context | Shopwareコンテキスト | No（readonly） |
| logLevel | Level | ログレベル | No（readonly） |
| throwable | Throwable|null | 例外オブジェクト | No（readonly） |
| message | string|null | エラーメッセージ | No（readonly） |
| template | string|null | 問題のあったテンプレート | No（readonly） |
| templateData | array|null | テンプレートデータ | No（readonly） |

### ログレベル一覧

| レベル | 説明 | 発生ケース |
|--------|------|----------|
| Level::Error | 重大エラー | SMTP送信失敗、送信元未設定 |
| Level::Warning | 警告 | テンプレートレンダリング部分失敗、添付ファイル無効 |
| Level::Debug | デバッグ | デフォルト値（明示的に指定されない場合） |

## テンプレート変数

本イベントはメールテンプレートを使用しないため、該当なし。

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | エラー種別 | 発火条件 | 説明 |
|------------|----------|---------|------|
| MailService | 送信元未設定 | senderMail空 | core.basicInformation.email未設定 |
| MailService | 件名レンダリング失敗 | Twig例外 | 件名テンプレート処理失敗 |
| MailService | 本文レンダリング失敗 | Twig例外 | HTML/プレーンテキストレンダリング失敗 |
| MailService | 添付ファイル無効 | DataPart以外 | 不正な添付ファイル形式 |
| MailService | SMTP送信失敗 | 例外発生 | mailSender->send()失敗 |
| MailService | 本文空 | trim後空文字 | メール本文が空 |

## 処理フロー

### イベントフロー

```mermaid
flowchart TD
    A[MailService::send] --> B[送信元取得]
    B --> C{送信元空?}
    C -->|Yes| D[MailErrorEvent発火]
    C -->|No| E[件名レンダリング]
    E --> F{レンダリング失敗?}
    F -->|Yes| G[MailErrorEvent発火 Warning]
    F -->|No| H[本文レンダリング]
    H --> I{レンダリング失敗?}
    I -->|Yes| J[MailErrorEvent発火 Warning]
    I -->|No| K[本文空チェック]
    K --> L{本文空?}
    L -->|Yes| M[MailErrorEvent発火]
    L -->|No| N[MailSender::send]
    N --> O{送信失敗?}
    O -->|Yes| P[MailErrorEvent発火 Error]
    O -->|No| Q[MailSentEvent発火]
    D --> R[return null]
    G --> R
    J --> R
    M --> R
    P --> R
    Q --> S[return Email]
    R --> T[終了]
    S --> T
```

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

### 参照テーブル一覧

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

### 更新テーブル一覧

本イベント自体はデータベースを更新しない。ただし、LogAwareインターフェース経由でlog_entryテーブルへの書き込みが行われる。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | ログレベル | 対処 |
|----------|---------|----------|------|
| 送信元未設定 | core.basicInformation.email空 | Error | 設定要確認 |
| 件名レンダリング | Twig例外 | Warning | テンプレート要確認 |
| 送信者名レンダリング | Twig例外 | Warning | テンプレート要確認 |
| 本文レンダリング | Twig例外 | Warning | テンプレート要確認 |
| 本文空 | 全本文空 | Error | テンプレート要確認 |
| 添付ファイル無効 | DataPart以外 | Warning | 添付データ要確認 |
| SMTP送信失敗 | TransportException等 | Error | SMTP設定要確認 |

### リトライ仕様

本イベントはリトライ対象外。エラー通知のため。

## 配信設定

### レート制限

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

### 配信時間帯

制限なし。エラー発生時に即座に発火。

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

- エラーログにセンシティブ情報（テンプレートデータ）が含まれる可能性があるため、ログ出力先に注意
- 例外オブジェクトにスタックトレースが含まれるため、本番環境での出力に注意
- テンプレート内容はgetLogData()では除外されない（要注意）

## 備考

- イベント名定数：MailErrorEvent::NAME = 'mail.sent.error'
- LogAwareインターフェース実装によりMonolog経由でログ出力
- FlowEventAware実装によりFlowビルダーでの利用も可能
- コンストラクタのlogLevelはnullの場合Level::Debugがデフォルト

---

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

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

### 推奨読解順序

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

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

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

**読解のコツ**: LogAware, ScalarValuesAware, FlowEventAwareを実装。throwable, message, template, templateDataは全てnullable。ログレベルはコンストラクタで指定、デフォルトはLevel::Debug。

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

MailServiceでの各エラー発火タイミングを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MailService.php | `src/Core/Content/Mail/Service/MailService.php` | mailError()メソッド（262-278行目）、各エラー発火箇所 |

**主要エラー発火箇所**:
1. **81-84行目**: 本文空エラー（mailError呼び出し）
2. **89-96行目**: 添付ファイル無効（Level::Warning）
3. **111-120行目**: SMTP送信失敗
4. **162-170行目**: 送信元未設定
5. **186-197行目**: 件名/送信者名レンダリング失敗（Level::Warning）
6. **212-219行目**: 本文レンダリング失敗（Level::Warning）

#### Step 3: mailError()ヘルパーメソッドを理解する

エラーイベント発火とログ出力の詳細を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | MailService.php | `src/Core/Content/Mail/Service/MailService.php` | mailError()（262-278行目） |

**処理内容**:
```php
private function mailError(
    string $errorMessage,
    Context $context,
    array $templateData,
    ?string $template = null,
    ?\Throwable $exception = null,
    Level $level = Level::Error
): void {
    $this->eventDispatcher->dispatch(
        new MailErrorEvent($context, $level, $exception, $errorMessage, $template, $templateData)
    );

    $this->logger->log($level, $errorMessage, array_merge([
        'template' => $template,
        'exception' => (string) $exception,
    ], $templateData));
}
```

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

```
MailService::send($data, $context, $templateData)
    │
    ├─ [エラー発生ポイント1] senderMail空
    │      └─ mailError('senderMail not configured...', Level::Error)
    │
    ├─ [エラー発生ポイント2] 件名レンダリング失敗
    │      └─ mailError('Could not render Mail-Subject...', Level::Warning)
    │
    ├─ [エラー発生ポイント3] 本文レンダリング失敗
    │      └─ mailError('Could not render Mail-Content...', Level::Warning)
    │
    ├─ [エラー発生ポイント4] 本文空
    │      └─ mailError('Mail body is null')
    │
    ├─ [エラー発生ポイント5] 添付ファイル無効
    │      └─ mailError('Invalid attachment...', Level::Warning)
    │
    └─ [エラー発生ポイント6] SMTP送信失敗
           └─ mailError('Could not send mail...')

    mailError()
        │
        ├─ new MailErrorEvent(
        │      $context,
        │      $level,
        │      $exception,
        │      $errorMessage,
        │      $template,
        │      $templateData
        │  )
        │
        ├─ eventDispatcher->dispatch(MailErrorEvent)
        │      │
        │      └─ EventSubscribers: onMailError()
        │
        └─ logger->log($level, $errorMessage, ...)
```

### データフロー図

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

エラー情報                       MailErrorEvent                       エラーハンドリング
  │                                  │                                    │
  ├─ errorMessage                    ├─ EventDispatcher                   ├─ getThrowable()
  ├─ exception                       │                                    ├─ getMessage()
  ├─ template                        ├─ Subscribers                       ├─ getTemplate()
  ├─ templateData                    │    └─ エラーハンドリング            └─ getLogLevel()
  └─ logLevel                        │
                                     └─ LogAware
                                          └─ Monolog経由ログ出力
```

### 関連ファイル一覧

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