{"skill":{"slug":"resend-send-native-node","displayName":"Resend Send Native Node","summary":"Send email via Resend.com's HTTPS API - native Node.js, zero dependencies. Use when the user explicitly asks to email, send a message, mail a report, or deli...","description":"---\nname: resend-send-native-node\ndescription: Send email via Resend.com's HTTPS API - native Node.js, zero dependencies. Use when the user explicitly asks to email, send a message, mail a report, or deliver a notification to an email address. Externally sends email only with --send; defaults to dry-run and requires RESEND_ALLOWED_TO allowlist for real sends. Requires RESEND_API_KEY in the process environment for real sends. No OAuth, no 2FA, no Gmail required.\nversion: 1.0.12\nrisk_class: external-email-send-dry-run-default-send-gated\n---\n\n# Resend Send Native Node\n\nSend email via the Resend.com HTTPS API.\n\nNative Node.js. Zero dependencies. One POST call for real sends. Small enough to audit directly.\n\n## When to use\n\nTrigger phrases: \"email me\", \"send an email\", \"mail this to\", \"send a notification\", \"email the report\".\n\n**Use this when:**\n- The user wants to send an email fast, without Gmail OAuth or App Password pain\n- Simple \"fire and forget\" sends (no inbox reading needed)\n- The user has a Resend.com account (check Resend's current pricing/limits before relying on a specific quota)\n- Weekly/report-style outbound messages where the body is generated from explicitly reviewed text\n\n**Do NOT use this when:**\n- The user wants to READ email (this is send-only)\n- The user needs to send from a specific personal Gmail address (use a Gmail-specific skill)\n- Sensitive business emails where provenance matters (Resend's default `onboarding@resend.dev` sender looks transactional)\n- The recipient, sender, or final body has not been explicitly reviewed/approved for a real send\n\n## Safety policy for agents\n\nThis skill is send-only, but it is still externally mutating. For agent use:\n\n1. **Draft first.** Generate or inspect the exact body text before sending.\n2. **Dry-run first.** The script dry-runs by default; review the printed payload.\n3. **Explicit approval.** 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.\n4. **Use an allowlist.** Real sends fail closed unless `RESEND_ALLOWED_TO=addr@example.com,other@example.com` is set in the process environment for approved recipients.\n5. **No raw memory dumps.** Email only curated report text, not unfiltered memory, transcripts, logs, or private workspace context.\n\n## How to run\n\nThe script is in `scripts/send.mjs`. Requires Node.js 18+ because real sends use native `fetch` and `AbortController`.\n\nFor 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.\n\n**Basic:**\n```powershell\nnode \"<skill-dir>/scripts/send.mjs\" --to \"you@example.com\" --subject \"Hello\" --body \"Hi there\"\n```\n\nWithout `--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.\n\n**With from address override:**\n```powershell\nnode \"<skill-dir>/scripts/send.mjs\" --from \"Example Sender <onboarding@resend.dev>\" --to \"you@example.com\" --subject \"Hello\" --body \"Hi\"\n```\n\n**HTML body:**\n```powershell\nnode \"<skill-dir>/scripts/send.mjs\" --html --to \"you@example.com\" --subject \"Styled\" --body \"<h1>Hi</h1><p>Hello</p>\"\n```\n\n**Dry run (no send, just print the payload):**\n```powershell\nnode \"<skill-dir>/scripts/send.mjs\" --dry-run --to \"you@example.com\" --subject \"Test\" --body \"...\"\n```\n\n**Real send (only after explicit approval):**\n```powershell\nnode \"<skill-dir>/scripts/send.mjs\" --send --to \"you@example.com\" --subject \"Weekly report\" --body \"Approved report text\"\n```\n\n### All flags\n\n| Flag | Required? | Purpose |\n|---|---|---|\n| `--to` | yes | Comma-separated recipient addresses |\n| `--subject` | yes | Message subject |\n| `--body` | yes | Inline message body |\n| `--cc` | no | Comma-separated cc |\n| `--bcc` | no | Comma-separated bcc |\n| `--from` | no | Override sender, e.g. `\"Example Sender <onboarding@resend.dev>\"` |\n| `--reply-to` | no | Reply-to address |\n| `--html` | no | Body is HTML instead of plain text |\n| `--dry-run` | no | Don't send; print the JSON payload |\n| `--send` | no | Actually send. Without this, the script dry-runs by default |\n| `--json` | no | Print a stable JSON receipt for dry-run or real send |\n| `-h`, `--help` | no | Show help |\n\nRecipients in `--to`, `--cc`, `--bcc`, and `--reply-to` must be bare email addresses. Only `--from` accepts display-name format such as `\"Reports <reports@example.com>\"`.\n\n`--body-file` is intentionally not supported in the public package. Review file contents yourself and pass approved text with `--body`.\n\n## Credentials\n\nRequires process environment values:\n\n- `RESEND_API_KEY` - starts with `re_...`\n- `RESEND_ALLOWED_TO` - comma-separated recipient allowlist for real sends\n- Real sends require `RESEND_ALLOWED_TO`; without it the script refuses `--send`\n\n**How to get one:**\n1. Sign up at https://resend.com and check the current pricing/limits for the account\n2. Go to **API Keys** in the dashboard\n3. Click **Create API Key**, name it, and choose the least-privilege sending permission available for your account\n4. Copy the key\n\nExport it in the runtime process environment:\n```powershell\n$env:RESEND_API_KEY=\"<your-resend-key>\"\n$env:RESEND_ALLOWED_TO=\"you@example.com,reports@example.com\"\n```\n\n## Sender identity\n\nBy 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.\n\n**For a custom domain (later, optional):**\n1. Add your domain to Resend at https://resend.com/domains\n2. Configure DNS records they provide\n3. Use a verified sender with `--from \"Reports <reports@your-verified-domain.example>\"`\n\n## What this skill does\n\n- Reads `RESEND_API_KEY` from the process environment only\n- POSTs a JSON request to `https://api.resend.com/emails`\n- Prints a one-line confirmation with the Resend message ID\n- Defaults to dry-run unless `--send` is present\n- Validates basic recipient address shape before sending\n- Enforces `RESEND_ALLOWED_TO` for real sends; fail-closed if it is missing\n- Prints body byte length and SHA-256 prefix in dry-run so reviewed content can be matched to the send\n- Supports `--json` receipt output so automation can compare the reviewed body hash to the send receipt and capture `resendId` without scraping human text\n\n## What this skill does NOT do\n\n- Does not read or manage email (this is send-only)\n- Does not read local files or support `--body-file`\n- Does not write any files\n- Does not make network calls other than to `api.resend.com`\n- Does not auto-update\n- Does not support attachments in this version\n\n## Output\n\nOn success:\n```\nsent to you@example.com (subject: Hello) - resend-id: c8f43f2a-...\n```\n\nWith `--json`, dry-runs and sends emit parseable JSON. Successful real sends include `sent: true`, `bodySha256`, `bodySha256Prefix`, and `resendId`.\n\nOn failure, clear error on stderr with a non-zero exit code.\n\n## Troubleshooting\n\n- **\"RESEND_API_KEY not set\"** - create one at https://resend.com, check current pricing/limits, and export `RESEND_API_KEY` in the process environment\n- **HTTP 401** - API key is invalid or was revoked\n- **HTTP 403** - API key doesn't have send permission, or the from address can only send to the account owner until a domain is verified (check dashboard). On Windows, a Node.js cleanup assertion may appear after a 403 exit; this is cosmetic and does not indicate a successful send.\n- **HTTP 422** - the from address isn't verified on your Resend account (use `onboarding@resend.dev` or verify your own domain)\n- **HTTP 429** - rate limited; check https://resend.com/pricing or the Resend dashboard for current limits\n- **Network error or timeout** - transient, but a network/timeout/read error after the request was sent does not prove the email was not delivered. Check the Resend dashboard before retrying to avoid duplicate sends.\n\n## Sample output\n\nSanitized representative output for eval/review checks:\n\n```text\n$ node scripts/send.mjs --to \"you@example.com\" --subject \"Hello\" --body \"Hi there\"\n--- DRY RUN: request would be sent ---\nnote: add --send to perform a real send after explicit approval.\nbody: 8 bytes, sha256:8328c36d18b7\nWARNING: RESEND_ALLOWED_TO is not configured. Real sends will fail closed until an allowlist is set.\nPOST https://api.resend.com/emails\nAuthorization: Bearer [redacted]\n\n{\n  \"from\": \"onboarding@resend.dev\",\n  \"to\": [\n    \"you@example.com\"\n  ],\n  \"subject\": \"Hello\",\n  \"text\": \"Hi there\"\n}\n\n$ node scripts/send.mjs --send --to \"you@example.com\" --subject \"Hello\" --body \"Hi there\"\nerror: RESEND_ALLOWED_TO must be set for real sends. Refusing --send without a recipient allowlist.\n\n# PowerShell:\n$env:RESEND_ALLOWED_TO=\"you@example.com\"; node scripts/send.mjs --send --to \"you@example.com\" --subject \"Hello\" --body \"Hi there\"\n# bash/zsh:\n# RESEND_ALLOWED_TO=\"you@example.com\" node scripts/send.mjs --send --to \"you@example.com\" --subject \"Hello\" --body \"Hi there\"\nerror: RESEND_API_KEY not set in process environment. Create one at https://resend.com, check current pricing/limits, and export RESEND_API_KEY.\n```\n\n## Account limits\n\nResend 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.\n\n## Changelog\n\n- `1.0.12`: ClawHub publication/version refresh after JSON receipt fix and public-readiness review; no additional runtime behavior change.\n- `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.\n- `1.0.10`: Clarify explicit approval must cover all delivery/reply headers (`to`, `cc`, `bcc`, `from`, `reply-to`), subject, and body before real sends.\n- `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.\n- `1.0.8`: Soften public Resend account/default-sender wording to avoid stale pricing/free-tier/domain-setup assumptions.\n- `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.\n- `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.\n- `1.0.5`: Public package wording and metadata cleanup; send behavior remains dry-run-first with `--send` plus recipient allowlist required for real sends.\n\r\n","topics":["Gmail","Send Email","Message"],"tags":{"latest":"1.0.12","email":"1.0.8","email resend notifications reports nodejs no-deps send-only":"1.0.3","no-deps":"1.0.8","node":"1.0.8","notifications":"1.0.8","reports":"1.0.8","resend":"1.0.8","send-only":"1.0.8"},"stats":{"comments":0,"downloads":844,"installsAllTime":27,"installsCurrent":1,"stars":0,"versions":10},"createdAt":1778080265946,"updatedAt":1781477021586},"latestVersion":{"version":"1.0.12","createdAt":1781477021586,"changelog":"ClawHub publication/version refresh after JSON receipt fix and public-readiness review; no additional runtime behavior change.","license":"MIT-0"},"metadata":null,"owner":{"handle":"jwestburg","userId":"s177the448m6rk54wz8gse0jnd8587yq","displayName":"jwestburg","image":"https://avatars.githubusercontent.com/u/278213922?v=4"},"moderation":null}