# 通知設計書 1-ニュースレター配信

## 概要

本ドキュメントは、QuickerSiteシステムにおけるニュースレター配信機能の通知設計を記述する。この機能により、管理者はニュースレターを購読者に対して一斉配信することができる。

### 本通知の処理概要

ニュースレター配信は、登録された購読者に対してHTMLメール形式でニュースレターを一斉送信する機能である。管理画面から設定されたニュースレターテンプレートを使用し、受信者ごとに名前・メールアドレスの動的置換を行い、購読解除リンクを自動挿入してメールを送信する。

**業務上の目的・背景**：ウェブサイト運営者が購読者に対して定期的な情報発信（ニュース、キャンペーン、更新情報等）を行うため。メールマーケティングの基盤機能として、顧客エンゲージメント向上と情報伝達を目的としている。

**通知の送信タイミング**：管理者が管理画面（bs_newsletterMailingSend.asp）から「Send now!」ボタンをクリックした際に、指定された間隔で順次送信される。バッチ処理形式で、設定された送信間隔（デフォルト10件/15秒）に従って配信される。

**通知の受信者**：ニュースレターカテゴリに購読登録し、かつ有効（bActive=true）な購読者全員。受信者リストはtblNewsletterCategorySubscriberテーブルから取得され、重複メールアドレスは自動的に除外される。

**通知内容の概要**：ニュースレター本文（HTMLフォーマット）、動的置換された受信者名、購読解除リンク、カスタマイズされた件名・送信元情報。本文にはサイト定数の展開や画像トラッキング用ピクセルも含まれる。

**期待されるアクション**：受信者はニュースレターの内容を閲覧し、必要に応じて購読解除リンクから購読を解除する。管理者は配信完了後にレポート画面で開封率などの統計を確認できる。

## 通知種別

メール

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（バッチ形式）|
| 優先度 | 中 |
| リトライ | 無（エラー時はスキップ）|

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

1. 管理者がニュースレターMailingに紐づくカテゴリを選択
2. 選択されたカテゴリ（sCategory）に属する購読者をtblNewsletterCategorySubscriberから取得
3. bActive=trueの購読者のみを対象
4. 重複メールアドレスはDictionaryオブジェクトで管理し、同一メールアドレスへの二重送信を防止

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | sFromEmail（デフォルト: customer.webmasterEmail）|
| 送信元名称 | sFromName（デフォルト: customer.webmaster）|
| 件名 | sSubject（デフォルト: "Subject line"）|
| 形式 | HTML |

### 本文テンプレート

```html
<table width="580" cellspacing="0" cellpadding="20" align="center" style="border:6px solid #FFFFFF;font-family: Verdana; font-size: 8pt;">
  <tbody>
    <tr>
      <td height="150" bgcolor="#375C71" style="border-bottom:6px solid #FFFFFF;font-family: Verdana; font-size: 12pt; text-align: right;color:#D3E1E9">
        <em><strong>Newsletter</strong></em>
      </td>
    </tr>
    <tr>
      <td bgcolor="#efefef" style="border-bottom:6px solid #FFFFFF;font-family: Verdana; font-size: 8pt;">
        <p>Dear [NL_NAME],</p>
        <p>Your text here...</p>
        <p>Best regards,<br />[Webmaster名]</p>
      </td>
    </tr>
    <tr>
      <td bgcolor="#B8C3CF" style="font-family: Verdana; font-size: 7pt; text-align: center;">
        [NL_UNSUBSCRIBELINK]
      </td>
    </tr>
  </tbody>
</table>
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | ニュースレターは添付ファイルをサポートしない |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| [NL_NAME] | 購読者名 | tblNewsletterCategorySubscriber.sName | No |
| [NL_EMAIL] | 購読者メールアドレス | tblNewsletterCategorySubscriber.sEmail | No |
| [NL_UNSUBSCRIBELINK] | 購読解除リンク（HTMLアンカータグ） | 動的生成 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | 管理者による「Send now!」ボタンクリック | postback=true | bs_newsletterMailingSend.aspからの送信開始 |
| スケジュール | META REFRESH による自動リロード | iStart < total | 指定間隔で次のバッチを処理 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| bActive=false | 購読が無効化されている購読者には送信しない |
| 重複メールアドレス | 同一メールアドレスに対して同一配信で複数回送信しない |
| 全件送信完了 | rs.eof=trueの場合、配信を終了 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[管理者が送信ボタンクリック] --> B[セキュリティチェック]
    B --> C[ニュースレターMailing取得]
    C --> D[カテゴリ別購読者取得]
    D --> E{購読者あり?}
    E -->|Yes| F[送信間隔設定確認]
    E -->|No| G[配信完了]
    F --> H[購読者ループ開始]
    H --> I{bActive=true?}
    I -->|Yes| J{重複チェック}
    I -->|No| K[次の購読者へ]
    J -->|新規| L[ログレコード作成]
    J -->|重複| K
    L --> M[テンプレート変数置換]
    M --> N[newsletter.send実行]
    N --> O[送信済みリスト追加]
    O --> P{バッチ上限到達?}
    P -->|Yes| Q[META REFRESH で次バッチ]
    P -->|No| K
    K --> R{全件処理完了?}
    R -->|Yes| S[送信日時記録]
    R -->|No| H
    S --> G
    Q --> H
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| tblNewsletter | ニュースレターテンプレート情報 | 件名、本文、送信元設定 |
| tblNewsletterCategorySubscriber | 購読者リスト | メールアドレス、名前、購読キー |
| tblNewsletterMailing | 配信管理情報 | カテゴリ、ログ設定、送信日時 |

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

#### tblNewsletter

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| sName | ニュースレター名 | iId指定 |
| sValue | 本文テンプレート | iId指定 |
| sSubject | 件名 | iId指定 |
| sFromEmail | 送信元メールアドレス | iId指定 |
| sFromName | 送信元名 | iId指定 |
| sUnsubscribeText | 購読解除リンクテキスト | iId指定 |
| sBodyBGColor | 背景色 | iId指定 |
| sStyleLink | リンクスタイル | iId指定 |

#### tblNewsletterCategorySubscriber

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| sName | 購読者名 | iCategoryID指定、bActive=true |
| sEmail | 購読者メールアドレス | iCategoryID指定、bActive=true |
| sKey | 購読解除キー | iCategoryID指定、bActive=true |
| iId | 購読者ID | ログ記録用 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| tblNewsletterLog | INSERT | 配信ログ（開封トラッキング用） |
| tblNewsletterMailing | UPDATE | 送信日時の記録 |

#### 送信ログテーブル（tblNewsletterLog）

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | iSubscriberID | 購読者ID | ログ有効時のみ |
| INSERT | iMailingID | 配信ID | ログ有効時のみ |
| INSERT | bRead | false | 初期値（未開封） |
| INSERT | dWhen | null | 開封時に更新 |
| INSERT | sKey | generatePassword | トラッキング用キー |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 送信失敗 | SMTPサーバーエラー | On Error Resume Nextでスキップし次へ |
| テンプレートエラー | 変数置換失敗 | On Error Resume Nextで継続 |
| 宛先不正 | メールアドレス形式エラー | 事前検証なし、送信時エラーでスキップ |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | iInterval設定依存（デフォルト10件/15秒=40件/分） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

管理者が手動で開始するため、時間帯制限はシステム側では設定されていない。

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

- 管理者認証：secondAdmin.bNewsletterによるアクセス制御
- 購読解除キー：24文字のランダムキーで購読者を識別
- CSRF対策：QS_secCodeHiddenによるトークン検証
- XSS対策：サイト定数のtreatConstants関数による処理
- 個人情報：メールアドレス・名前はデータベースに保存、暗号化なし

## 備考

- 配信中にブラウザウィンドウを閉じると配信が中断される
- 大量配信時はサーバー負荷とSMTPサーバーのレート制限に注意
- ログ機能（bLog=true）を有効にすると開封トラッキングが可能
- 購読解除リンクは必須（sUnsubscribeTextが空の場合、保存時にエラー）

---

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

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

### 推奨読解順序

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

ニュースレター配信で使用されるクラスとデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | newsletter.asp | `asp/includes/newsletter.asp` | cls_newsletterクラスの構造、プロパティ定義（行2-34） |
| 1-2 | mail_message.asp | `asp/includes/mail_message.asp` | cls_mail_messageクラスのメール送信仕様（行2-175） |

**読解のコツ**: ASP/VBScriptのクラス定義では、Public/Privateキーワードでスコープが決まる。Class_Initializeが初期化処理。

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

配信処理の起点となるファイルを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | bs_newsletterMailingSend.asp | `asp/bs_newsletterMailingSend.asp` | 配信制御のメインロジック |

**主要処理フロー**:
1. **行4-5**: セキュリティチェックとオブジェクト初期化
2. **行12-18**: 送信間隔設定の取得
3. **行25-74**: メイン送信ループ
4. **行29-64**: 購読者ごとの処理
5. **行57**: newsletter.send呼び出し
6. **行65-71**: 配信完了処理

#### Step 3: ニュースレタークラスを理解する

テンプレート管理と送信処理の詳細。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | newsletter.asp | `asp/includes/newsletter.asp` | send関数（行139-170）がコア処理 |

**主要処理フロー**:
- **行139-143**: パラメータの文字列変換
- **行147-153**: テンプレート定数の展開（キャッシュ対応）
- **行156-159**: cls_mail_messageの初期化
- **行161-165**: テンプレート変数[NL_NAME]、[NL_EMAIL]の置換
- **行166**: 購読解除リンクの生成と置換
- **行168**: メール送信実行

#### Step 4: メール送信処理を理解する

実際のメール送信を担当するクラス。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | mail_message.asp | `asp/includes/mail_message.asp` | send関数（行14-174） |

**主要処理フロー**:
- **行16-17**: 件名・本文の定数展開とHTML整形
- **行37-51**: SMTPサーバー設定の取得
- **行53-172**: メールコンポーネント別の送信処理（CDO、Persits等）

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

```
bs_newsletterMailingSend.asp
    |
    +-- cls_newsletterMailing（配信管理）
    |      |
    |      +-- newsletter プロパティ -> cls_newsletter
    |
    +-- cls_newsletter.send(name, email, key)
           |
           +-- treatConstants() [テンプレート定数展開]
           |
           +-- cls_mail_message.send()
                  |
                  +-- wrapInHTML() [HTML整形]
                  |
                  +-- SMTPサーバー送信（CDO/Persits等）
```

### データフロー図

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

管理画面                  bs_newsletterMailingSend.asp   メール送信
(iNewsletterMailingID) -> (カテゴリ別購読者取得)
                               |
tblNewsletterMailing    ->     |
(sCategory)                    v
                          購読者ループ処理
tblNewsletterCategory    ->    |
Subscriber                     v
(sName, sEmail, sKey)    newsletter.send()
                               |
tblNewsletter           ->     v
(sValue, sSubject等)     cls_mail_message.send()    -> 購読者メールボックス
                               |
                               v
                         tblNewsletterLog          -> 開封トラッキングDB
                         (INSERT)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| bs_newsletterMailingSend.asp | `asp/bs_newsletterMailingSend.asp` | ソース | 配信実行画面・メインコントローラ |
| newsletter.asp | `asp/includes/newsletter.asp` | ソース | ニュースレタークラス定義 |
| mail_message.asp | `asp/includes/mail_message.asp` | ソース | メール送信クラス定義 |
| bs_security.asp | `asp/bs_security.asp` | ソース | 管理者認証チェック |
| begin.asp | `asp/begin.asp` | ソース | 共通初期化処理 |
| bs_NewsletterList.asp | `asp/bs_NewsletterList.asp` | ソース | ニュースレター一覧画面 |
