AIが生成しがちな「いかにもAIっぽい」日本語の定型表現・水増し・空疎な形容を取り除き、読者の信頼を損なわない自然な文章に直す。記事・原稿・プレスリリース・告知・SNS投稿など、AIの支援を受けて書いた文章を公開前に点検するときに使う。「AI臭を消したい」「文章が機械っぽい」「人が書いたように直したい」などの依頼で使う。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
記者・研究者・報道機関のためのメールニュースレター運用を支援する。ニュースレターの新規立ち上げ、テンプレート設計、購読者リストの構築とセグメント化、配信、到達性(デリバラビリティ)の改善、エンゲージメント指標の分析、編集カレンダーの策定、特定電子メール法などのコンプライアンス対応までを扱う。
「メルマガを始めたい」「ニュースレターを作りたい」「開封率を上げたい」「配信停止の仕組みを整えたい」などの依頼で使う。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
실행 점수 미검증
설치 방법 보기설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
ジャーナリズム・研究領域でメールニュースレターを立ち上げ、運用するための実務的な手順とテンプレート集。 読者と直接の関係を築く独立記者、研究者、報道機関を想定する。配信の最終判断・本文の事実確認は運用者(記者)が行う。
注意:到達性の要件(Gmail・Yahoo等の送信者要件)や法令(特定電子メール法・個人情報保護法)の具体的な数値・条文は改定されることがある。重要な値は配信前に各サービスの最新ガイドラインと法令で確認すること。本スキルは一般的な手引きであり、法的助言ではない。
## ニュースレター戦略メモ
### 基本アイデンティティ
- **名称**:
- **タグライン**(一行で):
- **読者が得るもの**:[具体的な価値提案]
- **配信頻度**:[ ] 毎日 [ ] 週次 [ ] 隔週 [ ] 月次
### 想定読者
- 主たる読者:
- 読者の関心:
- 購読する理由:
- 読者がこの情報で何をするか:
### コンテンツの柱
1. [中核トピック1] - [頻度]
2. [中核トピック2] - [頻度]
3. [定例コーナー] - [頻度]
### 声・トーン
- フォーマル ↔ 会話的:[1-5]
- 硬い ↔ 軽い:[1-5]
- 取材報告 ↔ 個人的:[1-5]
### 成功指標(最初の6か月)
- 購読者数の目標:
- 目標開封率:
- 目標クリック率:
## [ニュースレター名] - 第[XX]号
**日付**:[日付]
**件名**:[件名]
**プレビューテキスト**:[受信箱で見える冒頭50〜90文字]
---
### 冒頭のつかみ
[読み進めたくなる2〜3文]
### メイン記事
[主たる内容。多くのニュースレターで300〜600語相当(日本語なら600〜1,200字程度が目安)]
### サブ項目(あれば)
- **クイックヒット1**:[リンク付きの短信]
- **クイックヒット2**:[リンク付きの短信]
### 定例コーナー
[週次コラム、データ一点、おすすめ など]
### 結び
[個人的なひとこと、行動喚起、次号の予告]
---
**配信停止** | **配信設定の変更** | **知人に転送**
言語属性は ja とし、フッターに送信者表示(特定電子メール法)と配信停止リンクを必ず含める。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{newsletter_name}}</title>
<style>
/* メールクライアント向けのリセット */
body { margin: 0; padding: 0; width: 100%; }
table { border-collapse: collapse; }
img { border: 0; display: block; }
/* レスポンシブなコンテナ */
.container {
max-width: 600px;
margin: 0 auto;
font-family: "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Yu Gothic", Meiryo, sans-serif;
font-size: 16px;
line-height: 1.7;
color: #333;
}
/* ダークモード対応 */
@media (prefers-color-scheme: dark) {
.container { background-color: #1a1a1a; color: #e0e0e0; }
a { color: #6db3f2; }
}
/* モバイル向け */
@media only screen and (max-width: 480px) {
.container { padding: 15px !important; }
h1 { font-size: 22px !important; }
}
</style>
</head>
<body>
<table role="presentation" width="100%">
<tr>
<td align="center" style="padding: 20px;">
<div class="container">
<!-- ヘッダー -->
<table width="100%">
<tr>
<td style="padding-bottom: 20px; border-bottom: 2px solid #333;">
<h1 style="margin: 0;">{{newsletter_name}}</h1>
<p style="margin: 5px 0 0; color: #666;">{{issue_date}}</p>
</td>
</tr>
</table>
<!-- 本文 -->
<table width="100%">
<tr>
<td style="padding: 30px 0;">
{{content}}
</td>
</tr>
</table>
<!-- フッター(送信者表示+配信停止) -->
<table width="100%">
<tr>
<td style="padding-top: 20px; border-top: 1px solid #ddd; font-size: 13px; color: #666;">
<p>このメールは {{newsletter_name}} にご登録いただいた方にお送りしています。</p>
<p>発行者:{{sender_name}}/連絡先:{{sender_contact}}</p>
<p>
<a href="{{unsubscribe_url}}">配信停止</a> |
<a href="{{preferences_url}}">配信設定の変更</a>
</p>
</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</body>
</html>
from dataclasses import dataclass, field
from datetime import datetime
from typing import List, Dict, Optional
from enum import Enum
import hashlib
class SubscriberStatus(Enum):
ACTIVE = "active" # 配信中
UNSUBSCRIBED = "unsubscribed" # 配信停止
BOUNCED = "bounced" # 不達(バウンス)
COMPLAINED = "complained" # 苦情(迷惑メール報告)
@dataclass
class Subscriber:
email: str
name: Optional[str] = None
subscribed_at: datetime = field(default_factory=datetime.now)
status: SubscriberStatus = SubscriberStatus.ACTIVE
tags: List[str] = field(default_factory=list)
custom_fields: Dict = field(default_factory=dict)
@property
def hash_id(self) -> str:
"""配信停止リンク用の一意なIDを生成する。"""
return hashlib.md5(self.email.encode()).hexdigest()[:12]
@dataclass
class NewsletterIssue:
subject: str
preview_text: str
html_content: str
plain_text: str
scheduled_at: Optional[datetime] = None
sent_at: Optional[datetime] = None
issue_number: int = 0
# 指標
sent_count: int = 0 # 送信数
delivered_count: int = 0 # 到達数
opened_count: int = 0 # 開封数
clicked_count: int = 0 # クリック数
bounced_count: int = 0 # 不達数
unsubscribed_count: int = 0 # 配信停止数
@property
def open_rate(self) -> float:
if self.delivered_count == 0:
return 0.0
return (self.opened_count / self.delivered_count) * 100
@property
def click_rate(self) -> float:
if self.delivered_count == 0:
return 0.0
return (self.clicked_count / self.delivered_count) * 100
class NewsletterManager:
"""ニュースレター運用の中核操作。"""
def __init__(self, name: str):
self.name = name
self.subscribers: List[Subscriber] = []
self.issues: List[NewsletterIssue] = []
def add_subscriber(self, email: str, name: str = None,
tags: List[str] = None) -> Subscriber:
"""新規購読者を追加する(ダブルオプトインの確認待ちを想定)。"""
sub = Subscriber(
email=email.lower().strip(),
name=name,
tags=tags or []
)
self.subscribers.append(sub)
return sub
def segment_subscribers(self, tags: List[str] = None,
min_engagement: float = None) -> List[Subscriber]:
"""条件に合う購読者を抽出する。"""
active = [s for s in self.subscribers
if s.status == SubscriberStatus.ACTIVE]
if tags:
active = [s for s in active
if any(t in s.tags for t in tags)]
return active
def calculate_engagement_score(self, subscriber: Subscriber) -> float:
"""購読者のエンゲージメントを0〜100で採点する。"""
# 実装では購読者ごとの開封・クリックを追跡する
return 50.0 # 仮の値
from datetime import datetime, timedelta
def clean_subscriber_list(manager: NewsletterManager,
inactive_threshold_days: int = 180) -> dict:
"""非アクティブな購読者を特定して処理する。"""
cutoff = datetime.now() - timedelta(days=inactive_threshold_days)
results = {
'total': len(manager.subscribers),
'active': 0,
'inactive': [],
'bounced': [],
'unsubscribed': []
}
for sub in manager.subscribers:
if sub.status == SubscriberStatus.BOUNCED:
results['bounced'].append(sub.email)
elif sub.status == SubscriberStatus.UNSUBSCRIBED:
results['unsubscribed'].append(sub.email)
elif sub.status == SubscriberStatus.ACTIVE:
# 直近のエンゲージメントを確認
engagement = manager.calculate_engagement_score(sub)
if engagement < 10: # 極端に低い
results['inactive'].append(sub.email)
else:
results['active'] += 1
return results
def run_reengagement_campaign(inactive_subscribers: List[str]) -> None:
"""非アクティブ層に再エンゲージ(呼び戻し)施策を送る。"""
# 「最近お届けできていません」といった呼び戻しメールを送る
# 2回試みて反応がなければ削除対象とする
pass
補足:再エンゲージ施策はリスクが高い。休眠購読者はアクティブ層に比べ苦情(迷惑メール報告)を出す割合が高く、施策一回で苦情率を押し上げて到達性を損なうことがある(後述の「到達性」を参照)。
## 推奨セグメント
### エンゲージメント別
- **VIP**:開封率 80%超、ほぼ毎回クリック
- **エンゲージ層**:開封率 40〜80%
- **ライト層**:開封率 10〜40%
- **離反予備軍**:90日間開封なし
- **休眠**:180日間開封なし
### 関心別(タグベース)
- 登録時に選んだトピックの好み
- クリックした記事の傾向
- アンケート・投票への回答
### 流入元別
- オーガニック(サイトからの登録)
- 紹介(知人からの転送)
- SNS
- 会員登録・ペイウォール経由
## 効く件名の型
### ニュース・報道向け
- **速報型**:「速報:[端的なニュース]」
- **数字型**:「[X]で分かった[テーマ]の要点」
- **問いかけ型**:「なぜ[主体]は[行動]したのか」
- **直球型**:「[テーマ]:いま押さえるべきこと」
### 分析・論説向け
- **見立て型**:「[出来事]の本当の構図」
- **逆張り型**:「[テーマ]をめぐる通説の誤り」
- **内側型**:「[業界]の関係者が知る[テーマ]」
### 避けるべきもの
- 全角・半角の大文字連打や過度な装飾
- 過剰な記号(!!! など)
- 中身が伴わない釣り見出し
- 迷惑メール判定を招きやすい語(「無料」「至急」「今すぐ」等の多用)
- 本文と食い違うプレビューテキスト
import random
from typing import List, Tuple
def ab_test_subject_lines(subscribers: List[Subscriber],
subject_a: str,
subject_b: str,
test_percentage: float = 0.2) -> dict:
"""
全配信の前に、購読者の一部で2つの件名をテストする。
"""
test_size = int(len(subscribers) * test_percentage)
test_group = random.sample(subscribers, test_size)
# テスト群を二分する
half = len(test_group) // 2
group_a = test_group[:half]
group_b = test_group[half:]
remaining = [s for s in subscribers if s not in test_group]
return {
'group_a': {
'subject': subject_a,
'subscribers': group_a,
'size': len(group_a)
},
'group_b': {
'subject': subject_b,
'subscribers': group_b,
'size': len(group_b)
},
'remaining': {
'subscribers': remaining,
'size': len(remaining),
'note': 'テスト期間後、勝った件名でこの群に配信する'
},
'test_duration_hours': 4
}
到達性は法域に依存しない汎用知識として重要。送信ドメイン認証(SPF/DKIM/DMARC)と苦情率の管理が要となる。
## 到達性のためのDNSレコード
### SPFレコード
v=spf1 include:_spf.{{esp_sending_domain}} ~all
### DKIM
- 利用する配信サービス(ESP)で鍵を生成する
- 公開鍵をTXTレコードとして登録する
- 送信メールに署名が付与されることを確認する
- 鍵長は1024ビット以上とする
### DMARC
v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com
### 配信前チェックリスト
- [ ] SPF・DKIM・DMARC を設定済み
- [ ] 送信ドメインのウォームアップ済み(少量から徐々に増やす)
- [ ] リストが清潔(ハードバウンスを除去済み)
- [ ] 配信停止リンクが機能する
- [ ] フッターに発行者の表示(特定電子メール法)がある
- [ ] テスト配信が受信箱に届く(迷惑メールに入らない)
大量送信者は、Gmail と Yahoo が2024年2月に導入した認証・配信停止の要件を満たす必要がある。Microsoft Outlook も2025年5月に同様の要件を採用した。2025年11月以降、Gmail は非準拠のメールを一時保留ではなく恒久エラー(5xx)で拒否するようになっており、要件を満たさないニュースレターはハードバウンスする。これらは日本から日本の読者に送る場合でも、受信側が Gmail・Yahoo メール等であれば適用される。
対象となる送信者。 「大量送信者」とは、Gmail 宛てに1日5,000通を超えて送る送信者を指す。5,000という閾値は送信サブドメインごとではなく、**主ドメイン単位(全サブドメインの合計)**で数える。transactional.example.com から1日2,500通、news.example.com から1日2,500通を送る報道機関は閾値を超えている。
必須要件:
p=none。 本番運用では、整合が取れたら p=quarantine または p=reject へ移行する。From: ヘッダの組織ドメインと整合していればよい(両方は不要)。緩和的整合(relaxed alignment)で構わない。List-Unsubscribe ヘッダと、List-Unsubscribe-Post: List-Unsubscribe=One-Click ヘッダを含める。HTTPS エンドポイントはログイン不要で2日以内に配信停止を処理する必要がある。本文中にも目に見える配信停止リンクを置く。運用上の含意:
評判の良い配信サービス(ESP)の多くは、送信ドメインを認証すれば認証・ヘッダ・TLS を自動で処理する。運用者の責任として残るのは苦情率と配信停止の挙動の二つで、再エンゲージ施策と速やかなリスト衛生管理がここに効く。休眠購読者の呼び戻しが危険なのは、彼らがアクティブ層の5〜10倍の割合で苦情を出すため。下手な呼び戻し施策一回で苦情率が0.3%を超え、送信ドメイン全体で拒否を招くことがある。
参考:
support.google.com/mail/answer/81126support.google.com/a/answer/14229414senders.yahooinc.com/best-practices/## 配信前に
### コンテンツのチェック
- [ ] 迷惑メール判定を招く語を多用していない
- [ ] テキストと画像の比率が適切(おおむねテキスト主体)
- [ ] リンク先がすべて信頼できるドメイン
- [ ] URL短縮サービスを使っていない(完全なリンクを使う)
- [ ] プレーンテキスト版を同梱している
### 技術的なチェック
- [ ] From アドレスが送信ドメインと一致している
- [ ] 返信先(Reply-To)アドレスを監視している
- [ ] プリヘッダ(プレビュー)テキストを設定している
- [ ] 画像に代替テキスト(alt)がある
- [ ] リンク切れがない
from dataclasses import dataclass
@dataclass
class NewsletterAnalytics:
"""ニュースレターのパフォーマンスを継続的に追跡する。"""
issue: NewsletterIssue
def summary(self) -> dict:
return {
'issue_number': self.issue.issue_number,
'sent': self.issue.sent_count,
'delivered': self.issue.delivered_count,
'delivery_rate': self._pct(self.issue.delivered_count,
self.issue.sent_count),
'opens': self.issue.opened_count,
'open_rate': self.issue.open_rate,
'clicks': self.issue.clicked_count,
'click_rate': self.issue.click_rate,
'click_to_open': self._pct(self.issue.clicked_count,
self.issue.opened_count),
'unsubscribes': self.issue.unsubscribed_count,
'unsubscribe_rate': self._pct(self.issue.unsubscribed_count,
self.issue.delivered_count),
}
def _pct(self, numerator: int, denominator: int) -> float:
if denominator == 0:
return 0.0
return round((numerator / denominator) * 100, 2)
# ベンチマーク(報道系ニュースレターの目安)
BENCHMARKS = {
'open_rate': {'good': 40, 'excellent': 55}, # 開封率
'click_rate': {'good': 4, 'excellent': 8}, # クリック率
'unsubscribe_rate': {'acceptable': 0.5, 'concerning': 1.0}, # 配信停止率
}
注意:Apple の「メールプライバシー保護」など開封トラッキングを無効化する仕組みが普及しており、開封率は実態より高く出たり比較しづらくなったりしている。開封率単独に頼らず、クリック率・返信・購読継続率も併せて見る。
国内外の主要サービス。料金体系・機能は変わるため、選定時に各社の最新情報を確認する。
| プラットフォーム | 向いている用途 | 料金体系 | 主な特徴 |
|---|---|---|---|
| Substack | 書き手主体・有料購読 | 売上シェア | 決済機能を内蔵 |
| note(ノート) | 国内向け・記事と一体運用 | 無料+手数料 | 国内最大級の読者基盤・有料配信 |
| theLetter | 国内のニュースレター特化 | 無料+手数料 | 日本語UI・有料配信に対応 |
| Ghost | 出版社・会員制 | 定額 | CMS を内蔵 |
| beehiiv | 成長重視 | フリーミアム | 紹介(リファラル)機能 |
| Kit(旧 ConvertKit) | クリエイター | 購読者数課金 | 自動化(オートメーション) |
| Mailchimp / Benchmark Email | 小規模組織 | 段階課金 | テンプレートが扱いやすい |
補足:国内の報道機関では、自社CMSや既存の会員基盤に配信機能を組み込む選択肢もある。送信ドメイン認証と特定電子メール法対応を自前で担保できるかが判断材料になる。
日本で広告・宣伝の要素を含むメール(ニュースレターも内容によっては該当しうる)を送る場合、特定電子メールの送信の適正化等に関する法律(特定電子メール法)が関係する。基本はオプトイン原則(あらかじめ同意した相手にのみ送る)。
## 特定電子メール法の基本(配信前に最新を確認)
- [ ] オプトイン:あらかじめ受信者の同意を得ている(同意の記録を保存)
- [ ] 送信者表示:本文に発行者(送信者)の氏名・名称を表示している
- [ ] 連絡先表示:苦情・問い合わせを受け付けられる住所・URL・メール等を表示している
- [ ] オプトアウトの明示:配信停止の方法(リンク等)を分かりやすく示している
- [ ] 配信停止の尊重:停止の通知を受けたら以後送信しない(速やかに反映)
- [ ] 送信者情報を偽らない(From・経路情報の偽装をしない)
- [ ] 購入・名簿業者から入手したリストへ無断送信しない
※ 報道機関による純粋な報道・編集コンテンツが「特定電子メール(広告宣伝メール)」に当たるかは内容次第。
購読導線や有料案内・広告を含む場合は同法の対象になりうる。判断に迷う場合は最新の総務省・
消費者庁のガイドラインを確認し、必要なら法務に相談する。これは法的助言ではない。
購読者のメールアドレス・氏名は個人情報にあたる。**個人情報の保護に関する法律(個人情報保護法)**にもとづき適切に扱う。
## 個人情報の取扱いチェック
- [ ] 利用目的を特定し、登録時に明示している(プライバシーポリシーへの導線)
- [ ] 同意は明示的に取得する(事前にチェックを入れた状態にしない)
- [ ] 取得した情報を目的外に使わない・無断で第三者提供しない
- [ ] 安全管理措置を講じている(アクセス制限・委託先管理=配信サービスの選定含む)
- [ ] 本人からの開示・訂正・利用停止・削除の求めに応じる体制がある
- [ ] 同意の記録を保存している
EU 在住者に配信する場合は **GDPR(EU一般データ保護規則)**が及びうる。
- [ ] 明示的な同意の取得(事前チェック不可)
- [ ] プライバシーポリシーへの明確なリンク
- [ ] 簡単な配信停止手段
- [ ] 求めに応じたデータのエクスポート
- [ ] 求めに応じたデータの削除
- [ ] 同意の記録の保存
本スキルは claude-skills-journalism(by Joe Amditis, MIT License, © 2025 Joe Amditis,
https://github.com/jamditis/claude-skills-journalism )の journalism-core/newsletter-publishing を
原典の構成(設計フレームワーク・テンプレート・送信用データ構造・購読者管理・件名最適化・到達性・分析・プラットフォーム比較・法令対応)に沿って日本語化し、
米国の CAN-SPAM 法・GDPR 中心の記述を日本の特定電子メール法および個人情報保護法に再構成したものです。
送信ドメイン認証(SPF/DKIM/DMARC)や Gmail・Yahoo 等の到達性要件は法域に依存しない汎用知識として保持し、
プラットフォーム比較は国内サービス(note・theLetter 等)を補って再構成、米国固有の参照は該当箇所を置き換えています。
原典の著作物本文は転載していません。原作者の公認・推奨を受けたものではありません。
MIT ライセンス全文は配布元リポジトリの LICENSE を参照。
아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
AIが生成しがちな「いかにもAIっぽい」日本語の定型表現・水増し・空疎な形容を取り除き、読者の信頼を損なわない自然な文章に直す。記事・原稿・プレスリリース・告知・SNS投稿など、AIの支援を受けて書いた文章を公開前に点検するときに使う。「AI臭を消したい」「文章が機械っぽい」「人が書いたように直したい」などの依頼で使う。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
取材・調査・データ報道で使える無料データ源(API)のカタログ。政府統計(e-Stat)、地域経済(RESAS)、気象(気象庁)、法令(e-Gov)、企業開示(EDINET)、書誌・国会会議録(国立国会図書館)、地理空間(国土地理院)、汎用の国際API(GDELT・Open-Meteo・Wayback等)を用途別に整理し、登録要否・利用条件・選び方を示す。「無料のデータ源が欲しい」「このテーマのAPIは?」「公的データをプログラムで取りたい」といった依頼で使う。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
データ報道(データジャーナリズム)の手順を支援する。データセットの分析、グラフや地図の作成、雑然としたデータのクリーニング、統計の算出、データに基づく記事の構築に使う。「e-Statのデータを分析したい」「人口あたりで比較したい」「グラフが誤解を招かないか確認したい」「統計から記事を組み立てたい」などの依頼で使う。記者・編集者・調査担当向け。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
取材で集めた資料(開示文書・記事・SNS・反訳など)をデジタルアーカイブ化し、AIで要約・分類・エンティティ抽出・関係づけ(知識グラフ化)して横断検索できる調査基盤を作るための手引き。「取材資料を整理したい」「大量の開示文書をデータベース化したい」「人物・組織・出来事の関係を可視化したい」「調査報道のアーカイブを作りたい」などの依頼で使う。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
発言・記事・SNS投稿などの主張を体系的にファクトチェックする。主張の抽出、検証可能な命題への分解、根拠の収集、当事者への確認、判定(レーティング)、記録、訂正対応までを支援する。掲載前の裏取り、ファクトチェック記事の作成、編集部の検証手順づくりに使う。「ファクトチェックして」「この発言は本当か」「裏取りの手順を」などの依頼で使う。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
テキスト・記事・ウェブページの内容を、厳密な検証方法論にもとづいてファクトチェックする。検証可能な主張を抽出し、信頼できる一次情報・公的データ・検証機関と突き合わせ、各主張の真偽と確からしさ(確信度)、情報源の信頼度スコアを評価し、根拠つきの検証レポートにまとめる。「この主張を検証して」「記事をファクトチェックして」「情報源の信頼性を見て」「真偽を判定して」「誤情報か確かめて」などの依頼で使う。付属の references(信頼できる情報源/検証方法論)を参照する検証重視版。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.