send-email-to-mailing-list について
サーバーサイドの JavaScript/TypeScript プロジェクトや Claude Code のワークフローから、メーリングリストへ通知を送るポータブルな Claude スキルです。テンプレートと本文の直接指定に対応し、CLI の dry-run で送信せずにリクエストを検証できます。
主な機能
- 01サーバーサイドコードからリストへ送信
- 02テンプレートまたはテキストと HTML を使用
- 03CLI で単発通知を送信
- 04dry-run でリクエストを検証
活用シーン
- 01登録や請求イベントをリストへ通知
- 02バックグラウンド処理のエラーや運用アラートを報告
- 03Claude Code からワークフロー完了を通知
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ schemavaults/ send-email --skill send-email-to-mailing-listインストール後、Claude Code で/send-email-to-mailing-listを入力して読み込まれたか確認します。
詳細
メーリングリストにメールを送信する
このスキルでは、Claude がメーリングリストにメールを送信する方法を説明します。方法は、(a)@schemavaults/send-email をインポートするサーバーサイドの TypeScript/JavaScript プロジェクトから送信する方法と、(b)Claude Code セッションから直接送信する方法のいずれかです。たとえば、タスクの最後に「このワークフローが完了しました」という通知を送信できます。どちらの場合も、sendEmailToMailingList() ヘルパーは SchemaVaults メールサーバーの POST /api/send ルートをラップし、環境変数から API キーを自動的に解決します。このスキルは自己完結型で、移植可能です。任意のプロジェクトの .claude/skills/ フォルダーに配置すれば、すぐに使えます。
このスキルを使う場面
このスキルには、明確に異なる 2 つの用途があります。どちらにも使用できます。
(a)アプリケーションコードから、メーリングリストの宛先に通知を送信する場合。 たとえば、次のようなケースです。
- 新規ユーザー登録/初回購入イベント
- バックグラウンドジョブや cron タスクで処理されなかったエラー
- 請求/サブスクリプションのライフサイクルイベント(トライアル終了、支払い失敗)
- 運用アラート(デプロイ成功、レート制限の超過、ヘルスチェック失敗)
- メーリングリストの宛先に送る、任意の「参考までに、たった今こんなことがありました」というメッセージ
(b)Claude Code 自体が、ワークフローの最後にメーリングリストへ通知を送信する場合。 たとえば、次のようなケースです。
- Claude が機能の実装を完了し、ブランチをプッシュした。
- Claude が PR のレビューを完了し、コメントを投稿した。
- 時間のかかるビルド、マイグレーション、CI タスクが完了した(成功または失敗)。
- Claude が進行を管理していた、スケジュール済みのメンテナンススクリプトが完了した。
用途(b)については、以下の「使用方法 -- Claude Code のワークフロー後通知」セクションを参照してください。
次の用途には使用しないでください。
- 個々のエンドユーザーへの送信(代わりにメールアドレス文字列を指定して
sendEmail()を使用してください) - クライアントサイド/ブラウザーのコード(API キーは秘密情報です)
- 1 回の送信で 50 人を超える宛先への大量配信(メールサーバーでは、1 回の送信呼び出しあたりの宛先数が 50 人に制限されています)
前提条件
-
対象プロジェクトにヘルパーパッケージをインストールします。
bun add @schemavaults/send-email # or: npm install @schemavaults/send-email -
コードの実行環境(ローカル開発環境、CI、本番環境)に 2 つの環境変数を設定します。
SCHEMAVAULTS_MAIL_API_KEY-- メールサーバーのapi_keysテーブルから発行された Bearer トークンです。必ずsvlts_mail_pk_で始まります。他の秘密情報と同様に扱い、コミットしたり、ブラウザーに配布したりしないでください。SCHEMAVAULTS_MAILING_LIST_ID-- メールサーバーのMAILING_LISTSテーブルにある、対象メーリングリストの UUID です。
値を直接渡さない場合は、両方とも必須です。いずれかが設定されていないと、ヘルパーは
Error("Failed to load ... from environment variable ...")をスローします。 -
3 つ目の環境変数は任意です。
SCHEMAVAULTS_APP_ENVIRONMENT="production"|"development"|"staging"。未設定の場合、ヘルパーはproductionにフォールバックし、本番環境のメールサーバーを対象にします。非本番環境に接続する場合に限り、明示的に設定してください。 -
サーバーサイドのコードからのみ呼び出してください。 API ルート、サーバーアクション、cron ハンドラー、バックグラウンドワーカーから呼び出します。React クライアントコンポーネントやブラウザーバンドルからは呼び出さないでください。
使用方法 -- テンプレート形式(推奨)
メールサーバーのカタログに React Email テンプレートがすでにある場合は、template_id を指定してください。これにより、メールサーバー側で HTML とプレーンテキストがレンダリングされます。利用可能なテンプレート ID を確認するには、@schemavaults/send-email の listEmailTemplates() を使用するか、list-email-templates スキルを参照してください。
import { sendEmailToMailingList } from "@schemavaults/send-email";
export async function notifyMailingListOfSignup(userName: string): Promise<void> {
await sendEmailToMailingList({
body: {
subject: `New signup: ${userName}`,
message: {
template_id: "<template-id-from-GET-/api/templates>",
template_props: {
/* prop shape per the template's description field */
},
},
},
});
}
登録済みのテンプレートに通知に合うものがない場合は、合わないテンプレートを無理に使おうとせず、代わりに以下の生の text/html 形式を使用してください。
使用方法 -- 生の HTML/テキスト形式(アドホック)
専用の React Email テンプレートを作成するほどではない単発の通知には、text と html を直接指定します。両方のフィールドが必須です。
import { sendEmailToMailingList } from "@schemavaults/send-email";
export async function notifyMailingListOfError(err: Error, context: string): Promise<void> {
const subject = `[alert] ${context}: ${err.message}`;
const text =
`An error occurred in ${context}.\n\n` +
`Message: ${err.message}\n\n` +
`Stack:\n${err.stack ?? "(no stack)"}\n`;
const html =
`<p>An error occurred in <code>${context}</code>.</p>` +
`<p><strong>Message:</strong> ${err.message}</p>` +
`<pre>${err.stack ?? "(no stack)"}</pre>`;
await sendEmailToMailingList({
body: { subject, message: { text, html } },
});
}
html にユーザー入力値を埋め込む場合、その値に </>/& が含まれる可能性があれば、エスケープしてください。メールサーバーは値を自動でサニタイズしません。
使用方法 -- メーリングリスト ID を明示的に渡す
デフォルトでは、sendEmailToMailingList はメーリングリストの UUID を SCHEMAVAULTS_MAILING_LIST_ID 環境変数から読み取ります。呼び出しごとに上書きできます。
await sendEmailToMailingList({
mailingListId: "00000000-0000-0000-0000-000000000000",
body: {
subject: "Hello from a specific list",
message: { text: "Hello", html: "<p>Hello</p>" },
},
});
使用方法 -- CLI(単発/臨時の送信に推奨)
@schemavaults/send-email には、同じヘルパーをラップする schemavaults-send-email バイナリが含まれています。手動通知、簡単なスモークテスト、bash の cron エントリ、Claude Code がワークフローの最後に送信する単発メールなど、単発の送信には CLI が最も簡単です。/tmp/ スクリプトも bun run も必要ありません。
# Raw text/html (both required)
bunx schemavaults-send-email send-to-mailing-list \
--subject "[ops] nightly backup finished" \
--text "Backup completed at $(date -u +%FT%TZ). 0 errors." \
--html "<p>Backup completed at $(date -u +%FT%TZ). <strong>0 errors.</strong></p>"
# Template-based
bunx schemavaults-send-email send-to-mailing-list \
--subject "Welcome aboard, Alice" \
--template-id welcome-email \
--template-props '{"name":"Alice"}'
# Override the mailing list per-call
bunx schemavaults-send-email send-to-mailing-list \
--mailing-list-id 00000000-0000-0000-0000-000000000000 \
--subject "..." --text "..." --html "..."
# Route through a specific mail-server transport (global flag, before the subcommand)
bunx schemavaults-send-email --transport smtp-primary send-to-mailing-list \
--subject "..." --text "..." --html "..."
# Long bodies: read from files instead of inline strings
bunx schemavaults-send-email send-to-mailing-list \
--subject "weekly digest" \
--text-file /tmp/digest.txt \
--html-file /tmp/digest.html
# Or supply the entire request body as a JSON file (validated server-side)
bunx schemavaults-send-email send-to-mailing-list --body-file /tmp/payload.json
(bun を利用できない場合は、bunx を npx に置き換えてください。)CLI はヘルパーと同様に、環境変数から SCHEMAVAULTS_MAIL_API_KEY と SCHEMAVAULTS_MAILING_LIST_ID を読み取ります。失敗時は 1 行のエラーを出力して 0 以外の終了コードで終了し、mail-server から 200 が返ると 0 で終了します。
すべてのフラグのリファレンスを確認するには、bunx schemavaults-send-email send-to-mailing-list --help を実行してください。
送信前の検証(--dry-run)
メーリングリストへの送信はすべての購読者に配信されるため、リクエストの検証に実際の送信を絶対に使わないでください。--dry-run を使うと、何も配信せずに Zod の body と template_props の形式、および API キー/メーリングリストのスコープをサーバー経由で一通り検証できます。
bunx schemavaults-send-email send-to-mailing-list --dry-run \
--subject "Welcome aboard, Alice" \
--template-id welcome-email \
--template-props '{"name":"Alice"}'
dry-run が成功すると [dry-run] mailing-list request validated; no email sent. と表示され、0 で終了します。不正なリクエストの場合は、サーバーの検証エラーとともに 0 以外で終了します。
使用方法 -- Claude Code のワークフロー完了後の通知
Claude は、@schemavaults/send-email に依存する任意のリポジトリ(このリポジトリも該当します)で、ワークフローの最後にメーリングリストへ単発の通知を送るため、このスキルを使用できます。
推奨:CLI を直接実行する
ワークフロー完了後の通知(数文と短い箇条書き)には、CLI が最適です。シェルコマンド 1 つで済み、一時ファイルも不要です。
bunx schemavaults-send-email send-to-mailing-list \
--subject "[claude-code] workflow finished: <short description>" \
--text "$(printf 'Claude just finished a workflow.\n\nSummary:\n- <bullet 1>\n- <bullet 2>\n- <bullet 3>\n')" \
--html "$(printf '<p>Claude just finished a workflow.</p><p><strong>Summary:</strong></p><ul><li><bullet 1></li><li><bullet 2></li><li><bullet 3></li></ul>')"
<short description> と箇条書きのプレースホルダーを、具体的な概要に置き換えてください。件名は約 70 文字以内にし、本文は読みやすくまとめてください(通常は 3~5 項目で十分です)。終了コードが 0 以外の場合はヘルパーがエラーをスローしています。黙って再試行せず、概要の中でユーザーにエラーを伝えてください。
代替手段:/tmp/ スクリプトを書く
本文が長い場合やテンプレート化されていて、シェル内での文字列の引用符処理が難しい場合(複数段落の HTML、動的データの組み立て、条件付きコンテンツなど)に限り、スクリプト形式を使ってください。
// /tmp/send-notification-after-workflow.ts
import { sendEmailToMailingList } from "@schemavaults/send-email";
async function main(): Promise<void> {
await sendEmailToMailingList({
body: {
subject: "[claude-code] workflow finished: <short description>",
message: {
text:
"Claude just finished a workflow.\n\n" +
"Summary:\n" +
"- <bullet 1>\n" +
"- <bullet 2>\n" +
"- <bullet 3>\n",
html:
"<p>Claude just finished a workflow.</p>" +
"<p><strong>Summary:</strong></p>" +
"<ul>" +
"<li><bullet 1></li>" +
"<li><bullet 2></li>" +
"<li><bullet 3></li>" +
"</ul>",
},
},
});
console.log("[notify] sent");
}
main().catch((err) => {
console.error("[notify] failed:", err);
process.exit(1);
});
Bun がリポジトリの node_modules/ を通じて @schemavaults/send-email を解決できるよう、リポジトリのルートから実行してください。
bun run /tmp/send-notification-after-workflow.ts
送信するタイミング
コミットとプッシュがすべて完了した後、ワークフローの最後に通知を必ず 1 件だけ送信してください。これにより、メールに最終状態が反映されます。
注意事項
SCHEMAVAULTS_MAIL_API_KEYとSCHEMAVAULTS_MAILING_LIST_IDの環境変数が Claude のプロセスに設定されている必要があります。設定されていない場合、ヘルパー(および CLI)は明確なエラーをスローします。むやみに再試行せず、ユーザーにその旨を伝えてください。- 通知はワークフローごとに 1 件だけにし、ステップごとには送信しないでください。 ワークフローに意味のある成果がなかった場合(例:「ユーザーが質問し、Claude が回答した」など)は、通知を一切送信しないでください。受信トレイを通知で埋めてはいけません。
- 作業が完了する前に通知を送信しないでください。 先にプッシュし、その後に通知してください。
- ユーザーがワークフロー完了後の通知を明示的に許可していない場合は、送信前に確認してください。メールの送信は他の人にも見える副作用です。ユーザーが依頼していないタスクで、黙って送信してはいけません。
- リクエストを検証するために、空メールや「テスト」メールをメーリングリストに絶対に送信しないでください。
--dry-run(CLI)またはdryRun: true(ヘルパーの body)を使ってください。mail-server は、template_propsの形式を含むリクエスト全体を、宛先に配信せずに検証します。誤って実際のテストメールを送信すると、すべての購読者に届きます。
リクエスト body の形式
sendEmailToMailingList が受け付けるのは Omit<SendEmailRequestBody, "to" | "cc" | "bcc"> です。宛先はメーリングリストなので、to、cc、bcc は意図的に使用できません。使用できるフィールドは次のとおりです。
type MailingListNotificationBody = {
subject: string;
message:
| { template_id: string; template_props?: unknown }
| { text: string; html: string };
from?: string; // defaults to the mail-server's configured sender
replyTo?: string; // optional reply-to override
dryRun?: boolean; // server validates without dispatching
transport?: string; // which mail-server transport to deliver with
};
// Full call signature:
type ISendEmailToMailingListOpts = {
body: MailingListNotificationBody;
mailingListId?: string; // override SCHEMAVAULTS_MAILING_LIST_ID
bearerToken?: string; // override SCHEMAVAULTS_MAIL_API_KEY; rarely needed
mailServerUrl?: string; // override the server origin; rarely needed
environment?: "production" | "development" | "staging";
dryRun?: boolean; // convenience; sets body.dryRun
transport?: string; // convenience; sets body.transport
};
エラー処理
このヘルパーは、200 以外のレスポンスを受け取ると例外をスローします。通知の失敗によって呼び出し元の主要な処理を中断させない場合は、必ず呼び出しを try/catch で囲んでください。
try {
await sendEmailToMailingList({
body: {
subject: `New signup: ${userName}`,
message: { text, html },
},
});
} catch (notifyErr) {
console.error("[notify] failed to send mailing list notification", notifyErr);
}
よくある失敗モード:
| エラー | 原因 |
|---|---|
Failed to load API key from environment variable 'SCHEMAVAULTS_MAIL_API_KEY' | 実行環境で環境変数が設定されていない(または空文字列になっている)場合です。 |
Failed to load mailing list ID from environment variable 'SCHEMAVAULTS_MAILING_LIST_ID' | 実行環境で環境変数が設定されていない(または空文字列になっている)場合です。 |
Bad request body to send email with! | body がスキーマに一致していません。通常は、subject がない、text と html のペアがない、または不明なフィールドが含まれています。 |
Invalid or revoked API key. (HTTP 401) | SCHEMAVAULTS_MAIL_API_KEY が誤っている、期限切れ、または取り消されています。 |
This API key is not permitted... (HTTP 403) | API キーが、対象とは異なるメーリングリストを許可リストに登録しています。 |
Failed to parse request body! (HTTP 400) | サーバー側で Zod による解析に失敗しました。通常は、テンプレートの template_props の形式が一致していません。 |
| 不明なトランスポートのエラー (HTTP 400) | transport に、メールサーバーで設定されていないトランスポートが指定されています。クライアントは名前の形式が正しいかどうかだけを確認し、存在するかどうかはサーバーが判断します。 |
環境の指定
デフォルトでは、このヘルパーは production 環境のメールサーバー URL を解決します。staging または development を明示的に指定するには、次のようにします。
await sendEmailToMailingList({
environment: "development",
body: {
subject: "dev smoke test",
message: { template_id: "my-test-email", template_props: { name: "test" } },
},
});
または、プロセスレベルで SCHEMAVAULTS_APP_ENVIRONMENT を設定してください。opts.environment が渡されていない場合、このヘルパーは @schemavaults/app-definitions の getAppEnvironment() を使ってその値を読み取ります。
このスキルを別のプロジェクトに追加する
- このファイルを対象プロジェクトの
.claude/skills/フォルダーにコピーします。 - 対象プロジェクトにヘルパーパッケージをインストールします。
bun add @schemavaults/send-email - プロジェクトで通常使用しているシークレット管理方法(ローカル開発用の
.env.local、本番環境用のホスティングプロバイダーのシークレットストアなど)を使って、2 つの環境変数を設定します。SCHEMAVAULTS_MAIL_API_KEY=svlts_mail_pk_... SCHEMAVAULTS_MAILING_LIST_ID=00000000-0000-0000-0000-000000000000 - スキルファイルをコミットします。そのリポジトリで次回 Claude Code セッションを開始すると、スキルが自動的に検出されます。
リファレンス
インストールしたパッケージ内のソースファイル(node_modules/@schemavaults/send-email/dist/)です。正確な仕様を確認する必要がある場合は、これらを参照してください。
send-email-to-mailing-list.{d.ts,js}—sendEmailToMailingList()ヘルパーと、そのISendEmailToMailingListOptsインターフェースです。send-email.{d.ts,js}—getSchemaVaultsMailApiKey()とサーバー URL の解決を含む、基盤となるsendEmail()の実装です。send-email-request-body-schema.{d.ts,js}— クライアントヘルパーとメールサーバーのルートがリクエスト本文の検証に使用する Zod スキーマ(createSendEmailRequestBodySchema)です。index.d.ts— パッケージのエントリーポイントです。エクスポートされるすべてのシンボルが記載されています。