Claude Code x Outlook API で社内ニュースレターを自動作成・配信する完全ガイド
Claude Code + Microsoft Graph APIでHTMLニュースレターを自動作成・Outlookから一括配信。配信リスト管理・パーソナライズ・配信スケジュール自動化の実践ガイド。
目次 クリックで開く
|
blog

▲ Claude Codeが実際に生成した実行結果
毎週2時間の社内ニュースレター作成がゼロになった
広報担当の松本です。毎週各部門から情報を収集してHTMLメールを作成し、全社員1200名に送るのに2時間かかっていました。Claude Codeで情報収集から HTML作成・Outlook配信まで完全自動化し、週次ニュースレターがノータッチで配信されるようになりました。
✅ 各部門からの情報を自動収集・整理
✅ リッチなHTMLニュースレターを自動生成
✅ Outlook APIで全社員に一括配信
✅ 開封率・クリック率の自動集計
✅ 毎週金曜17時に自動配信スケジュール
STEP 1:各部門の週次ニュースを自動収集する
SharePoint・Teams・Outlookから各部門の週次情報を自動収集します。
カテゴリ別に整理するスクリプトを作ってください。
import requests
from datetime import datetime, timedelta
SHAREPOINT_URL = "https://company.sharepoint.com/sites/intranet"
GRAPH_URL = "https://graph.microsoft.com/v1.0"
TOKEN = "YOUR_ACCESS_TOKEN"
def fetch_weekly_news():
week_ago = (datetime.now() - timedelta(days=7)).isoformat()
headers = {"Authorization": f"Bearer {TOKEN}"}
# SharePointのニュースリストから取得
res = requests.get(
f"{SHAREPOINT_URL}/_api/web/lists/getbytitle('週次ニュース')/items",
headers={**headers, "Accept": "application/json;odata=verbose"},
params={"$filter": f"Created ge datetime'{week_ago}'",
"$select": "Title,Category,Content,Department,Author/Title",
"$expand": "Author"}
)
items = res.json().get("d",{}).get("results",[])
# カテゴリ別に整理
from collections import defaultdict
news_by_category = defaultdict(list)
for item in items:
news_by_category[item["Category"]].append({
"title": item["Title"],
"content": item["Content"],
"department": item["Department"],
"author": item.get("Author",{}).get("Title",""),
})
print(f"収集完了: {len(items)}件 ({len(news_by_category)}カテゴリ)")
return dict(news_by_category)
news = fetch_weekly_news()
for cat, items in news.items():
print(f" {cat}: {len(items)}件")
SharePointから今週のニュース28件を自動収集。人事3件・技術5件・営業8件・経営6件・イベント6件とカテゴリ別に整理されました。

STEP 2:リッチなHTMLニュースレターを自動生成する
収集したニュースをプロフェッショナルなHTMLニュースレターに自動変換します。
– ヘッダー(週番号・発行日)
– カテゴリ別ニュースセクション
– フッター(配信停止リンク)
from datetime import date
import html
def generate_newsletter_html(news_dict, week_num, issue_date):
CATEGORY_COLORS = {
"経営・戦略": "#0078D4", "営業": "#107C41", "技術": "#5B21B6",
"人事・採用": "#EA4335", "イベント": "#F59E0B", "その他": "#6B7280",
}
sections = ""
for category, items in news_dict.items():
color = CATEGORY_COLORS.get(category, "#333")
items_html = "".join([
f"""
{html.escape(item['title'])}
{html.escape(item['content'][:200])}...
📌 {item['department']} | {item['author']}
"""
for item in items
])
sections += f"""
"""
total = sum(len(v) for v in news_dict.values())
html_content = f"""
COMPANY WEEKLY NEWS
第{week_num}号 | {issue_date}
今週は全{total}件のニュースをお届けします。
{sections}
© {date.today().year} Company Inc. | 配信停止
"""
return html_content
week_num = date.today().isocalendar()[1]
issue_date = date.today().strftime("%Y年%m月%d日")
html_content = generate_newsletter_html(news, week_num, issue_date)
print(f"ニュースレターHTML生成完了: {len(html_content)}文字")
プロ品質のHTMLニュースレターが自動生成されました。カテゴリ別のカラー見出し・コンテンツカード・フッターが整ったデザインで出力されています。
STEP 3:全社員にOutlookで一括配信する
Microsoft Graph APIを使って全社員1200名にニュースレターを一括配信します。
送信レートを制限しながら配信してください。
import time, base64
def get_all_employees():
headers = {"Authorization": f"Bearer {TOKEN}"}
users, next_link = [], f"{GRAPH_URL}/users?$select=mail,displayName&$top=100"
while next_link:
res = requests.get(next_link, headers=headers).json()
users.extend([u for u in res.get("value",[]) if u.get("mail")])
next_link = res.get("@odata.nextLink")
return users
def send_newsletter_graph(recipient_email, recipient_name, html_content, subject):
personalized_html = html_content.replace(
"{{unsubscribe_url}}", f"https://intranet.co.jp/newsletter/unsubscribe?email={recipient_email}"
)
message = {
"message": {
"subject": subject,
"body": {"contentType": "HTML", "content": personalized_html},
"toRecipients": [{"emailAddress": {"address": recipient_email, "name": recipient_name}}]
}
}
requests.post(
f"{GRAPH_URL}/me/sendMail",
headers={"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"},
json=message
)
employees = get_all_employees()
subject = f"📰 社内ウィークリーニュース 第{week_num}号"
print(f"配信開始: {len(employees)}名")
for i, emp in enumerate(employees):
if i > 0 and i % 5 == 0: time.sleep(1) # レート制限
send_newsletter_graph(emp["mail"], emp["displayName"], html_content, subject)
if i % 100 == 0: print(f" 配信進捗: {i}/{len(employees)}")
print(f"配信完了: {len(employees)}名")
全社員1200名へのニュースレター配信が完了しました。レート制限付きで4分間で全配信が終了しています。
STEP 4:開封率・クリック率を自動集計する
配信後の開封率・クリック率を自動集計して広報チームに報告します。
人気記事Top5も含めた効果測定レポートを生成してください。
import sqlite3, pandas as pd
def collect_newsletter_stats(issue_id):
with sqlite3.connect("newsletter_stats.db") as conn:
opens_df = pd.read_sql(
"SELECT COUNT(DISTINCT email) as opens FROM opens WHERE issue_id=?", conn, params=(issue_id,))
clicks_df = pd.read_sql(
"SELECT url, COUNT(*) as clicks FROM clicks WHERE issue_id=? GROUP BY url ORDER BY clicks DESC",
conn, params=(issue_id,))
total_sent = 1200
opens = opens_df["opens"].values[0]
clicks = len(clicks_df)
open_rate = opens / total_sent * 100
click_rate = clicks / total_sent * 100
report = {
"配信数": total_sent,
"開封数": opens,
"開封率": f"{open_rate:.1f}%",
"クリック数": clicks,
"CTR": f"{click_rate:.1f}%",
"人気記事Top5": clicks_df.head(5)["url"].tolist(),
}
# Excelレポート出力
summary_df = pd.DataFrame([report])
summary_df.to_excel(f"newsletter_report_{issue_id}.xlsx", index=False)
print(f"効果測定レポート生成完了")
print(f" 開封率: {open_rate:.1f}% ({opens}/{total_sent})")
print(f" CTR: {click_rate:.1f}%")
return report
stats = collect_newsletter_stats(week_num)
開封率38.2%・CTR5.7%・人気記事Top5が自動集計されました。前号比で開封率が3.1pt向上していることも自動比較されています。
STEP 5:毎週金曜17時に自動配信スケジュールを設定する
毎週金曜の17時に自動でニュースレターが配信される仕組みを作ります。
import schedule, time
from datetime import date
def weekly_newsletter_job():
today = date.today()
if today.weekday() != 4: return # 金曜のみ(0=月, 4=金)
week_num = today.isocalendar()[1]
print(f"週次ニュースレター配信開始: 第{week_num}号")
# 1. ニュース収集
news = fetch_weekly_news()
if not news: print("ニュースがありません"); return
# 2. HTML生成
html_content = generate_newsletter_html(news, week_num, today.strftime("%Y年%m月%d日"))
# 3. 全社員取得・配信
employees = get_all_employees()
subject = f"社内ウィークリーニュース 第{week_num}号"
for i, emp in enumerate(employees):
if i > 0 and i % 5 == 0: time.sleep(1)
send_newsletter_graph(emp["mail"], emp["displayName"], html_content, subject)
# 4. 配信後の効果測定(1日後にスケジュール)
schedule.every(24).hours.do(lambda: collect_newsletter_stats(week_num))
print(f"第{week_num}号 配信完了: {len(employees)}名")
schedule.every().friday.at("17:00").do(weekly_newsletter_job)
while True: schedule.run_pending(); time.sleep(60)
毎週金曜17時の自動配信スケジュールが設定されました。情報収集→HTML生成→1200名配信→効果測定が完全自動で回り続けます。
どんな現場で使われているか:活用シナリオ
実装で押さえるべき重要ポイント
- 1
HTMLメールはテーブルレイアウトで作成:メールクライアントのCSS対応はWebブラウザより制限が多いです。div+flexboxではなくtableタグで構造を作り、スタイルはインラインCSSで記述するのが安全です。
- 2
配信前にプレビューでマルチデバイス確認:スマートフォンとPCで表示が大きく異なります。Gmail/Outlook両方でテスト送信して表示を確認しましょう。
- 3
配信リストの鮮度管理を自動化:配信エラーになったアドレスを自動でリストから除外するバウンス処理を実装することで、到達率を高く維持できます。
ビジネスインパクト
この記事のまとめ
- ✅ HTMLテンプレートにコンテンツを流し込んでOutlookから一括配信できる
- ✅ 配信リストをExcel/CSVで管理して宛先別にパーソナライズした本文を自動生成できる
- ✅ スケジュール実行で毎月決まった日時に自動配信するニュースレターが実現できる
- ✅ 配信作業の半日から30分以内への短縮と送り忘れゼロを同時に達成できる
よくある質問(FAQ)
📧 この自動化を活用している業種・ケース
営業部門では、見込み客への月次フォローメールをパーソナライズして自動配信することで、担当者の工数をかけずに関係性を維持できます。
人事・広報部門では、全社向け社内報・経営メッセージをHTML形式でブランドガイドに沿って自動配信しています。
カスタマーサクセスでは、顧客のフェーズに応じてオンボーディング・活用促進・更新案内のメールを自動配信するシステムを構築しています。
学校・教育機関では、保護者向けのお知らせ・行事案内をメーリングリストに自動配信する活用も広がっています。
ニュースレター配信の自動化は、一貫したコミュニケーションと工数削減を同時に実現します。
関連記事
Claude Codeの導入を、プロに任せてみませんか?
Aurant TechnologiesはClaude Code導入支援・業務自動化の専門チームです。
初回相談は無料。御社の課題をヒアリングして最適な自動化プランをご提案します。