使用 Resend.com HTTPS API 发送邮件,原生 Node.js,零依赖。仅在用户明确要求发送邮件、发送消息、邮寄报告或投递时使用。
Send email via the Resend.com HTTPS API.
Native Node.js. Zero dependencies. One POST call for real sends. Small enough to audit directly.
Trigger phrases: "email me", "send an email", "mail this to", "send a notification", "email the report".
Use this when:
Do NOT use this when:
onboarding@resend.dev sender looks transactional)This skill is send-only, but it is still externally mutating. For agent use:
--send only after the user explicitly approves the exact to, cc, bcc, from, reply-to, subject, and body. Treat reply-to as response-routing control and review display-name text in from for spoof-like wording before any real send.RESEND_ALLOWED_TO=addr@example.com,other@example.com is set in the process environment for approved recipients. Treat RESEND_ALLOWED_TO as an operator-controlled, approval-scoped guard; agents must not broaden or set it merely to make a send succeed unless the user explicitly approves that exact allowlist change.The script is in scripts/send.mjs. Requires Node.js 18+ because real sends use native fetch and AbortController.
For operator workflows, prefer --json so dry-runs and real sends produce a stable machine-readable receipt with mode, sent, recipients, subject, body byte count, full body SHA-256, SHA-256 prefix, allowlist status, and resendId on successful real sends.
For agent-generated, user-supplied, multiline, or otherwise arbitrary subject, body, from, reply-to, to, cc, or bcc values, do not interpolate those values into a shell command string. Shell quoting is outside this script's control and can be broken before the script's dry-run, allowlist, or approval gates execute.
Canonical agent path: invoke Node directly with an argv array and pass reviewed message fields as one JSON object on stdin with --input-json-stdin. Keep mode flags such as --dry-run, --send, and --json in argv; the stdin JSON payload accepts only message fields and cannot set send mode.
Example argv shape for agents/orchestrators:
text
argv: ["<skill-dir>/scripts/send.mjs", "--json", "--dry-run", "--input-json-stdin"]
stdin JSON: {"to":["you@example.com"],"subject":"Reviewed subject","body":"Approved body text"}
The shell examples below are for simple literal operator commands only. They are not the safe transfer path for arbitrary generated content.
Basic:
powershell
node "<skill-dir>/scripts/send.mjs" --to "you@example.com" --subject "Hello" --body "Hi there"
Without --send, this prints a dry-run payload and does not send. Dry-run output includes the full reviewed body JSON plus body byte length and SHA-256 prefix; redact dry-run logs before sharing externally.
With from address override:
powershell
node "<skill-dir>/scripts/send.mjs" --from "Example Sender <onboarding@resend.dev>" --to "you@example.com" --subject "Hello" --body "Hi"
HTML body:
powershell
node "<skill-dir>/scripts/send.mjs" --html --to "you@example.com" --subject "Styled" --body "<h1>Hi</h1><p>Hello</p>"
Dry run (no send, just print the payload):
powershell
node "<skill-dir>/scripts/send.mjs" --dry-run --to "you@example.com" --subject "Test" --body "..."
If --dry-run and --send are both present, dry-run wins and no email is sent.
Real send (only after explicit approval):
powershell
node "<skill-dir>/scripts/send.mjs" --send --to "you@example.com" --subject "Weekly report" --body "Approved report text"
FlagRequired?Purpose--toyes unless supplied by --input-json-stdinComma-separated recipient addresses--subjectyes unless supplied by --input-json-stdinMessage subject--bodyyes unless supplied by --input-json-stdinInline message body; use stdin JSON instead for agent-generated or arbitrary text--ccnoComma-separated cc--bccnoComma-separated bcc--fromnoOverride sender, e.g. "Example Sender <onboarding@resend.dev>"``--reply-tonoReply-to address--htmlnoBody is HTML instead of plain text--dry-runnoDon't send; print the JSON payload--sendnoActually send. Without this, the script dry-runs by default--jsonnoPrint a stable JSON receipt for dry-run or real send--input-json-stdinnoRead message fields from one JSON object on stdin; preferred for agent-generated/arbitrary text because it avoids shell interpolation-h, --helpnoShow help
Recipients in --to, --cc, --bcc, and --reply-to must be bare email addresses. Only --from accepts display-name format such as "Reports <reports@example.com>".
--body-file is intentionally not supported in the public package. Review file contents yourself and pass approved text with --body, or for agent workflows pass the exact reviewed message fields through --input-json-stdin without shell interpolation.
Requires process environment values:
RESEND_API_KEY - starts with re_...RESEND_ALLOWED_TO - comma-separated recipient allowlist for real sendsRESEND_ALLOWED_TO; without it the script refuses --sendRESEND_ALLOWED_TO as operator-controlled. Setting or widening it is a separate approval-scoped action, not something an agent should do automatically to satisfy --send.How to get one:
Export it in the runtime process environment:
powershell
$env:RESEND_API_KEY="<your-resend-key>"
$env:RESEND_ALLOWED_TO="you@example.com,reports@example.com"
By default, emails are sent from onboarding@resend.dev - Resend's default sender. This may support quick testing subject to current Resend account restrictions; use a verified domain/sender for production-style mail.
For a custom domain (later, optional):
--from "Reports <reports@your-verified-domain.example>"RESEND_API_KEY from the process environment onlyhttps://api.resend.com/emails with redirects disabled--send is presentRESEND_ALLOWED_TO for real sends; fail-closed if it is missing--json receipt output so automation can compare the reviewed body hash to the send receipt and capture resendId without scraping human text--body-filehttps://api.resend.com/emails request; redirects are disabled with redirect: "error"On success:
text
sent to you@example.com (subject: Hello) - resend-id: c8f43f2a-...
With --json, dry-runs and sends emit parseable JSON. Successful real sends include sent: true, bodySha256, bodySha256Prefix, and resendId.
On failure, clear error on stderr with a non-zero exit code.
RESEND_API_KEY in the process environmentonboarding@resend.dev or verify your own domain)Sanitized representative output for eval/review checks:
text
$ node scripts/send.mjs --to "you@example.com" --subject "Hello" --body "Hi there"
--- DRY RUN: request would be sent ---
note: add --send to perform a real send after explicit approval.
body: 8 bytes, sha256:8328c36d18b7
WARNING: RESEND_ALLOWED_TO is not configured. Real sends will fail closed until an allowlist is set.
POST https://api.resend.com/emails
Authorization: Bearer [redacted]
{
"from": "onboarding@resend.dev",
"to": [
"you@example.com"
],
"subject": "Hello",
"text": "Hi there"
}
$ node scripts/send.mjs --send --to "you@example.com" --subject "Hello" --body "Hi there"
error: RESEND_ALLOWED_TO must be set for real sends. Refusing --send without a recipient allowlist.
# PowerShell:
# Only set or widen RESEND_ALLOWED_TO after explicit approval for that exact allowlist change.
$env:RESEND_ALLOWED_TO="you@example.com"; node scripts/send.mjs --send --to "you@example.com" --subject "Hello" --body "Hi there"
# bash/zsh:
# RESEND_ALLOWED_TO="you@example.com" node scripts/send.mjs --send --to "you@example.com" --subject "Hello" --body "Hi there"
error: RESEND_API_KEY not set in process environment. Create one at https://resend.com, check current pricing/limits, and export RESEND_API_KEY.
Minimum no-send checks:
powershell
node --check skills\resend-send-native-node\scripts\send.mjs
node skills\resend-send-native-node\scripts\send.mjs --help
node skills\resend-send-native-node\scripts\send.mjs --to "test@example.com" --subject "Smoke" --body "Hello" --json
node skills\resend-send-native-node\tests\run-resend-send-tests.mjs
The smoke command above must remain a dry-run: do not include --send. Real sends require separate explicit approval for the exact recipient headers, subject, and body plus an allowlist.
Resend pricing and free-tier limits can change. Check the current Resend dashboard/pricing page before relying on a specific daily/monthly quota or paid-tier price. New accounts commonly support quick testing from onboarding@resend.dev; use a verified domain/sender for production-style mail.
1.0.20: Mirror the operator-controlled RESEND_ALLOWED_TO warning in CLI help and document 5xx retry ambiguity/support guidance. No send behavior change.1.0.19: Make RESEND_ALLOWED_TO ownership explicit: it is an operator-controlled, approval-scoped guard, and agents must not set or widen it merely to make a send succeed. No send behavior change.1.0.18: Clarify the flags table/help that required message fields may be supplied through --input-json-stdin instead of inline flags, so support handoffs do not steer arbitrary generated/user content through shell interpolation. No send behavior change.1.0.17: Add canonical --input-json-stdin agent invocation path for arbitrary reviewed message fields, document that agents must not shell-interpolate generated email content, add hostile metacharacter stdin regression coverage, and enforce fixed-endpoint no-redirect behavior with redirect: "error". No real-send approval semantics changed.1.0.16: Add committed no-send regression coverage for --dry-run --send precedence and cc/ bcc allowlist blocking before any API-key/fetch path. No send behavior change.1.0.15: Document the actual no-send publish/update checks, including the existing tests\run-resend-send-tests.mjs runner, so public update gates do not rely on a nonexistent self-test path. No send behavior change.1.0.14: Public package eval hygiene: generate the Resend API-key-shaped test sentinel at runtime so package scanners do not see a static key-shaped string in source; no send behavior change.1.0.13: Source-polish retest prep: genericized a review fixture subject, documented that --dry-run --send resolves to dry-run, and normalized SKILL.md line endings; no send behavior change.1.0.12: ClawHub publication/version refresh after JSON receipt fix and public-readiness review; no additional runtime behavior change.1.0.11: Add --json structured receipts for dry-run and real send output so operators can capture stable subjects, body hashes, allowlist status, and resendId without scraping human text.1.0.10: Clarify explicit approval must cover all delivery/reply headers ( to, cc, bcc, from, reply-to), subject, and body before real sends.1.0.9: Add explicit Node.js 18+ usage prerequisite and offline gate-regression tests for dry-run, allowlist fail-closed, missing-key fail-closed, HTML/reply-to payloads, unsupported body-file, invalid recipients, and help output.1.0.8: Soften public Resend account/default-sender wording to avoid stale pricing/free-tier/domain-setup assumptions.1.0.7: Fix no-allowlist sample output, document bare-recipient requirement and dry-run body visibility, add 30s send timeout, and warn to verify Resend dashboard before retrying ambiguous network/timeout failures.1.0.6: Add frontmatter version metadata, hedge rate-limit wording, document Windows 403 cleanup assertion behavior, and include sanitized dry-run/fail-closed sample outputs for eval review.1.0.5: Public package wording and metadata cleanup; send behavior remains dry-run-first with --send plus recipient allowlist required for real sends.