# 通知設計書 2-ニュースレター購読解除通知

## 概要

本ドキュメントは、QuickerSiteシステムにおけるニュースレター購読解除通知機能の設計を記述する。購読者がニュースレターの購読を解除した際に、管理者に対して通知メールを送信する機能である。

### 本通知の処理概要

ニュースレター購読解除通知は、購読者がニュースレターの購読解除リンクをクリックした際に、設定された管理者宛に解除者の情報（メールアドレス・名前）を含む通知メールを送信する機能である。これにより、管理者は購読者の減少をリアルタイムで把握できる。

**業務上の目的・背景**：ニュースレター運営者が購読者の離脱状況を把握し、コンテンツ改善や運営方針の見直しに活用するため。購読者数の変動を監視することで、メールマーケティング施策の効果測定にも役立てることができる。

**通知の送信タイミング**：購読者がニュースレター内の購読解除リンク（[NL_UNSUBSCRIBELINK]）をクリックし、購読解除処理が正常に完了した直後に送信される。具体的には、tblNewsletterCategorySubscriberテーブルのbActiveがfalseに更新された後。

**通知の受信者**：ニュースレターカテゴリに設定されたsNotifEmail（通知メールアドレス）宛に送信される。このフィールドが空の場合は通知は送信されない。複数の管理者への通知が必要な場合は、カテゴリ設定で対応する。

**通知内容の概要**：購読解除者のメールアドレス、購読解除者の名前、購読解除されたニュースレターカテゴリ名。シンプルなテキスト形式で、迅速に状況を把握できる内容となっている。

**期待されるアクション**：管理者は通知を受け取り、必要に応じて購読解除の傾向分析や、購読者リストの管理を行う。特に大量解除が発生した場合は、コンテンツや配信頻度の見直しを検討する。

## 通知種別

メール

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 低 |
| リトライ | 無 |

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

1. 購読解除リクエストのキー（e）からtblNewsletterCategorySubscriberを検索
2. 該当購読者のiCategoryIDからtblNewsletterCategoryを取得
3. カテゴリのsNotifEmailが設定されている場合のみ送信
4. sNotifEmailが空またはnullの場合は通知をスキップ

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | システムデフォルト（customer.webmasterEmail） |
| 送信元名称 | システムデフォルト（customer.siteName） |
| 件名 | "Unsubscribe from email list '[カテゴリ名]': [解除者メールアドレス]" |
| 形式 | HTML |

### 本文テンプレート

```html
email: [解除者メールアドレス]<br />
name: [解除者名]
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| [カテゴリ名] | ニュースレターカテゴリ名 | tblNewsletterCategory.sName（QS_nl.sName） | Yes |
| [解除者メールアドレス] | 購読解除者のメールアドレス | tblNewsletterCategorySubscriber.sEmail（rsE("sEmail")） | Yes |
| [解除者名] | 購読解除者の名前 | tblNewsletterCategorySubscriber.sName（rsE("sName")） | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| URLアクセス | 購読解除リンククリック | sNotifEmailが設定済み | process_unsubscribe.aspへのGETリクエスト |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| sNotifEmailが空 | カテゴリに通知先が設定されていない場合は送信しない |
| 既に購読解除済み | bActive=falseの場合はホームページへリダイレクト |
| 無効なキー | 24文字でない、または存在しないキーの場合は処理しない |
| カテゴリ不存在 | iCategoryIDに対応するカテゴリがない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[購読解除リンククリック] --> B{キー長=24文字?}
    B -->|No| C[ホームページへリダイレクト]
    B -->|Yes| D[購読者レコード検索]
    D --> E{レコード存在?}
    E -->|No| C
    E -->|Yes| F[カテゴリ情報取得]
    F --> G{カテゴリ存在?}
    G -->|No| C
    G -->|Yes| H[解除フィードバック表示準備]
    H --> I{既に解除済み?}
    I -->|Yes| C
    I -->|No| J[bActive=falseに更新]
    J --> K{sNotifEmail設定あり?}
    K -->|No| L[処理完了]
    K -->|Yes| M[cls_mail_message作成]
    M --> N[件名・本文設定]
    N --> O[メール送信]
    O --> L
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| tblNewsletterCategorySubscriber | 購読者情報の取得 | sKey、sEmail、sName、bActive |
| tblNewsletterCategory | カテゴリ情報・通知先取得 | sName、sNotifEmail、sUnsubscribeFB |

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

#### tblNewsletterCategorySubscriber

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| sKey | 購読者識別キー | クエリパラメータe=sKeyで検索 |
| sEmail | 解除者メールアドレス | 通知メール本文に使用 |
| sName | 解除者名 | 通知メール本文に使用 |
| bActive | 購読状態 | 解除済み判定に使用 |
| iCategoryID | カテゴリID | カテゴリ情報取得に使用 |

#### tblNewsletterCategory

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| sName | カテゴリ名 | 通知メール件名に使用 |
| sNotifEmail | 通知先メールアドレス | 送信先として使用 |
| sUnsubscribeFB | 購読解除フィードバック文 | ページ表示用 |
| sUnsubscribeFBTitle | フィードバックタイトル | ページ表示用 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| tblNewsletterCategorySubscriber | UPDATE | bActiveをfalseに更新 |

#### tblNewsletterCategorySubscriber更新

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| UPDATE | bActive | false（getSQLBoolean(false)） | 購読無効化 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 無効なキー | キー長が24文字でない | redirectToHP()でホームページへ |
| 購読者不存在 | sKeyに該当するレコードなし | redirectToHP()でホームページへ |
| カテゴリ不存在 | iCategoryIDに該当なし | redirectToHP()でホームページへ |
| 送信失敗 | SMTPエラー等 | On Error Resume Nextで無視 |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（購読解除イベントに依存） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

購読解除アクションに連動するため、24時間いつでも送信可能。

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

- 購読解除キー：24文字のランダム文字列で購読者を識別（総当たり攻撃対策）
- SQLインジェクション対策：cleanup関数でキーをサニタイズ、left関数で24文字に制限
- クロスサイトスクリプティング対策：quotrep関数でメールアドレス・名前をエスケープ
- 個人情報：解除者のメールアドレス・名前が管理者に通知される

## 備考

- 購読解除後も購読者レコードは削除されず、bActive=falseとして保持される
- 同一キーでの再度のアクセスはホームページへリダイレクト
- フィードバックページのカスタマイズはカテゴリ設定（sUnsubscribeFB、sUnsubscribeFBTitle）で可能
- フィードバックページでも[NL_NAME]、[NL_EMAIL]の置換が行われる

---

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

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

### 推奨読解順序

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

購読解除処理で使用されるデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | process_unsubscribe.asp | `asp/process_unsubscribe.asp` | 処理全体の流れ（行1-48） |

**読解のコツ**: このファイルは単一の処理フローで、includeされて実行される。条件分岐を追いながら読む。

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

購読解除URLアクセス時の処理起点。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | process_unsubscribe.asp | `asp/process_unsubscribe.asp` | 購読解除処理のメインロジック |

**主要処理フロー**:
1. **行2**: キー長チェック（24文字）
2. **行5**: 購読者レコード検索（sKey条件）
3. **行6-10**: レコード存在確認とカテゴリ取得
4. **行11-18**: フィードバック表示準備（変数置換）
5. **行21-26**: 購読状態チェックとbActive更新
6. **行27-34**: 通知メール送信処理

#### Step 3: 通知送信処理を理解する

管理者への通知メール送信の詳細。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | process_unsubscribe.asp | `asp/process_unsubscribe.asp` | 行27-34の通知送信部分 |
| 3-2 | mail_message.asp | `asp/includes/mail_message.asp` | メール送信クラス |

**主要処理フロー**:
- **行27**: sNotifEmailの存在チェック
- **行28-29**: cls_mail_messageインスタンス作成、宛先設定
- **行30-31**: 件名設定（カテゴリ名+解除者メール）
- **行32**: 本文設定（email + name）
- **行33**: send()メソッド呼び出し

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

```
default.asp (pageAction=unsubscribe)
    |
    +-- process_unsubscribe.asp
           |
           +-- db.execute() [購読者検索]
           |
           +-- cls_newslettercategory.pick() [カテゴリ取得]
           |
           +-- db.execute() [bActive更新]
           |
           +-- cls_mail_message
                  |
                  +-- send() [通知メール送信]
```

### データフロー図

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

購読解除リンク            process_unsubscribe.asp
(e=sKey)           ->     |
                          v
tblNewsletterCategory     キー検証・購読者取得
Subscriber         ->     |
(sKey, sEmail,            v
 sName, bActive)          カテゴリ情報取得
                          |
tblNewsletterCategory ->  v
(sName, sNotifEmail)      bActive=false更新    ->    tblNewsletterCategorySubscriber
                          |
                          v
                          通知メール送信       ->    管理者メールボックス
                          |                        (sNotifEmail宛)
                          v
                          フィードバック表示   ->    購読者ブラウザ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| process_unsubscribe.asp | `asp/process_unsubscribe.asp` | ソース | 購読解除処理・通知送信の実装 |
| mail_message.asp | `asp/includes/mail_message.asp` | ソース | メール送信クラス定義 |
| newsletter.asp | `asp/includes/newsletter.asp` | ソース | ニュースレタークラス（解除リンク生成） |
| begin.asp | `asp/begin.asp` | ソース | 共通初期化処理 |
| default.asp | `default.asp` | ソース | メインルーター（pageAction分岐） |
