USP
Unlike generic email tools, this collection provides specialized skills for AI agents, including a secure inbox and best practices guidance, ensuring reliable and compliant email interactions within AI workflows.
Use cases
- 01Sending transactional emails via AI agents
- 02Building secure email inboxes for AI agents
- 03Managing Resend platform resources from the terminal
- 04Developing HTML email templates with React components
- 05Implementing email best practices in AI-driven communication
Detected files (8)
skills/email-best-practices/SKILL.mdskillShow content (3637 bytes)
--- name: email-best-practices description: Use when building email features, emails going to spam, high bounce rates, setting up SPF/DKIM/DMARC authentication, implementing email capture, ensuring compliance (CAN-SPAM, GDPR, CASL), handling webhooks, retry logic, or deciding transactional vs marketing. license: MIT metadata: author: Resend version: "1.0.2" homepage: https://resend.com/agent-skills source: https://github.com/resend/email-best-practices openclaw: links: repository: https://github.com/resend/email-best-practices documentation: https://resend.com/docs/email-best-practices-skill --- # Email Best Practices Guidance for building deliverable, compliant, user-friendly emails. ## Architecture Overview ``` [User] → [Email Form] → [Validation] → [Double Opt-In] ↓ [Consent Recorded] ↓ [Suppression Check] ←──────────────[Ready to Send] ↓ [Idempotent Send + Retry] ──────→ [Email API] ↓ [Webhook Events] ↓ ┌────────┬────────┬─────────────┐ ↓ ↓ ↓ ↓ Delivered Bounced Complained Opened/Clicked ↓ ↓ [Suppression List Updated] ↓ [List Hygiene Jobs] ``` ## Quick Reference | Need to... | See | |------------|-----| | Set up SPF/DKIM/DMARC, fix spam issues | [Deliverability](./references/deliverability.md) | | Build password reset, OTP, confirmations | [Transactional Emails](./references/transactional-emails.md) | | Plan which emails your app needs | [Transactional Email Catalog](./references/transactional-email-catalog.md) | | Build newsletter signup, validate emails | [Email Capture](./references/email-capture.md) | | Send newsletters, promotions | [Marketing Emails](./references/marketing-emails.md) | | Ensure CAN-SPAM/GDPR/CASL compliance | [Compliance](./references/compliance.md) | | Decide transactional vs marketing | [Email Types](./references/email-types.md) | | Handle retries, idempotency, errors | [Sending Reliability](./references/sending-reliability.md) | | Process delivery events, set up webhooks | [Webhooks & Events](./references/webhooks-events.md) | | Manage bounces, complaints, suppression | [List Management](./references/list-management.md) | ## Start Here **New app?** Start with the [Catalog](./references/transactional-email-catalog.md) to plan which emails your app needs (password reset, verification, etc.), then set up [Deliverability](./references/deliverability.md) (DNS authentication) before sending your first email. **Spam issues?** Check [Deliverability](./references/deliverability.md) first—authentication problems are the most common cause. Gmail/Yahoo reject unauthenticated emails. **Marketing emails?** Follow this path: [Email Capture](./references/email-capture.md) (collect consent) → [Compliance](./references/compliance.md) (legal requirements) → [Marketing Emails](./references/marketing-emails.md) (best practices). **Production-ready sending?** Add reliability: [Sending Reliability](./references/sending-reliability.md) (retry + idempotency) → [Webhooks & Events](./references/webhooks-events.md) (track delivery) → [List Management](./references/list-management.md) (handle bounces).skills/react-email/SKILL.mdskillShow content (12637 bytes)
--- name: react-email description: Use when building HTML email templates with React components, adding a visual email editor to an application using the React Email visual editor, rendering emails to HTML, or sending emails with Resend. Covers welcome emails, password resets, notifications, order confirmations, newsletters, transactional emails, and the embeddable email editor component. license: MIT metadata: author: Resend version: "2.1.0" homepage: https://react.email source: https://github.com/resend/react-email openclaw: install: - kind: node package: react-email label: React Email links: repository: https://github.com/resend/react-email documentation: https://resend.com/docs/react-email-skill --- # React Email Build and send HTML emails using React components - a modern, component-based approach to email development that works across all major email clients. ## Installation ```sh npm i react-email ``` Or scaffold a new project: ```sh npx create-email@latest cd react-email-starter npm install npm run dev ``` This works with any package manager (npm, yarn, pnpm, bun) — substitute accordingly. The dev server runs at localhost:3000 with a preview interface for templates in the `emails` folder. ### Adding to an Existing Project Install the packages and add a script to your `package.json`: ```json { "scripts": { "email": "email dev --dir emails --port 3000" } } ``` Make sure the path to the emails folder is relative to the base project directory. Ensure `tsconfig.json` includes proper support for JSX. ## Basic Email Template Create an email component with proper structure using the Tailwind component for styling: ```tsx import { Html, Head, Preview, Body, Container, Heading, Text, Button, Tailwind, pixelBasedPreset } from 'react-email'; interface WelcomeEmailProps { name: string; verificationUrl: string; } export default function WelcomeEmail({ name, verificationUrl }: WelcomeEmailProps) { return ( <Html lang="en"> <Tailwind config={{ presets: [pixelBasedPreset], theme: { extend: { colors: { brand: '#007bff', }, }, }, }} > <Head /> <Body className="bg-gray-100 font-sans"> <Preview>Welcome - Verify your email</Preview> <Container className="max-w-xl mx-auto p-5"> <Heading className="text-2xl text-gray-800"> Welcome! </Heading> <Text className="text-base text-gray-800"> Hi {name}, thanks for signing up! </Text> <Button href={verificationUrl} className="bg-brand text-white px-5 py-3 rounded block text-center no-underline box-border" > Verify Email </Button> </Container> </Body> </Tailwind> </Html> ); } // Preview props for testing WelcomeEmail.PreviewProps = { name: 'John Doe', verificationUrl: 'https://example.com/verify/abc123' } satisfies WelcomeEmailProps; export { WelcomeEmail }; ``` ## Behavioral Guidelines - When iterating over the code, only update what the user asked for. Keep the rest intact. - If the user asks to use media queries, inform them that most email clients don't support them and suggest a different approach. - Never use template variables (like `{{name}}`) directly in TypeScript code. Instead, reference the underlying properties directly. If the user explicitly asks for `{{variableName}}`, place the mustache string only in PreviewProps, never in the component JSX: ```typescript const EmailTemplate = (props) => { return ( <h1>Hello, {props.variableName}!</h1> ); } EmailTemplate.PreviewProps = { variableName: "{{variableName}}", }; export default EmailTemplate; ``` - Never write the `{{variableName}}` pattern directly in the component structure. If the user insists, explain that this would make the template invalid. ## Essential Components See [references/COMPONENTS.md](references/COMPONENTS.md) for complete component documentation. **Core Structure:** - `Html` - Root wrapper with `lang` attribute - `Head` - Meta elements, styles, fonts - `Body` - Main content wrapper - `Container` - Outermost centering wrapper (has built-in `max-width: 37.5em`). Use only once per email. - `Section` - Interior content blocks (no built-in max-width). Use for grouping content inside `Container`. - `Row` & `Column` - Multi-column layouts - `Tailwind` - Enables Tailwind CSS utility classes **Content:** - `Preview` - Inbox preview text, always first inside `<Body>` - `Heading` - h1-h6 headings - `Text` - Paragraphs - `Button` - Styled link buttons (always include `box-border`) - `Link` - Hyperlinks - `Img` - Images (see Static Files section below) - `Hr` - Horizontal dividers **Specialized:** - `CodeBlock` - Syntax-highlighted code - `CodeInline` - Inline code - `Markdown` - Render markdown - `Font` - Custom web fonts ## Before Writing Code When a user requests an email template, ask clarifying questions FIRST if they haven't provided: 1. **Brand colors** - Ask for primary brand color (hex code like #007bff) 2. **Logo** - Ask if they have a logo file and its format (PNG/JPG only - warn if SVG/WEBP) 3. **Style preference** - Professional, casual, or minimal tone 4. **Production URL** - Where will static assets be hosted in production? ## Static Files and Images ### Directory Structure Local images must be placed in the `static` folder inside your emails directory: ``` project/ ├── emails/ │ ├── welcome.tsx │ └── static/ <-- Images go here │ └── logo.png ``` ### Dev vs Production URLs Use this pattern for images that work in both dev preview and production: ```tsx const baseURL = process.env.NODE_ENV === "production" ? "https://cdn.example.com" // User's production CDN : ""; export default function Email() { return ( <Img src={`${baseURL}/static/logo.png`} alt="Logo" width="150" height="50" /> ); } ``` **How it works:** - **Development:** `baseURL` is empty, so URL is `/static/logo.png` - served by React Email's dev server - **Production:** `baseURL` is the CDN domain, so URL is `https://cdn.example.com/static/logo.png` **Important:** Always ask the user for their production hosting URL. Do not hardcode `localhost:3000`. ## Styling See [references/STYLING.md](references/STYLING.md) for comprehensive styling documentation including typography, layout patterns, dark mode, and brand consistency. ### Key Rules - Use `Tailwind` with `pixelBasedPreset` (email clients don't support `rem`). Import `pixelBasedPreset` from `react-email`. - Never use flexbox or grid — use `Row`/`Column` components or tables for layouts. - Avoid CSS/Tailwind media queries (`sm:`, `md:`, `lg:`, `xl:`) — limited email client support. - Never use theme selectors (`dark:`, `light:`) — not supported. - Never use SVG or WEBP images — warn users about rendering issues. - Always specify border type (`border-solid`, `border-dashed`, etc.) — email clients don't inherit it. - For single-side borders, reset others first (`border-none border-l border-solid`). ### Required Classes | Component | Required Class | Why | |-----------|---------------|-----| | `Button` | `box-border` | Prevents padding from overflowing the button width | | `Hr` / any border | `border-solid` (or `border-dashed`, etc.) | Email clients don't inherit border type | | Single-side borders | `border-none` + the side | Resets default borders on other sides | ### Structure Notes - Always define `<Head />` inside `<Tailwind>` when using Tailwind CSS - `<Preview>` should always be the first element inside `<Body>` - Only include props in `PreviewProps` that the component actually uses - Use fixed width/height for known-size elements (logos, icons); responsive sizing (`w-full`, `h-auto`) for content images ## Rendering ### Convert to HTML ```tsx import { render } from 'react-email'; import { WelcomeEmail } from './emails/welcome'; const html = await render( <WelcomeEmail name="John" verificationUrl="https://example.com/verify" /> ); ``` ### Convert to Plain Text ```tsx const text = await render(<WelcomeEmail name="John" verificationUrl="https://example.com/verify" />, { plainText: true }); ``` ## Sending React Email supports sending with any email service provider. See [references/SENDING.md](references/SENDING.md) for complete sending documentation including Resend, Nodemailer, and SendGrid examples. Quick example using the Resend SDK: ```tsx import { Resend } from 'resend'; import { WelcomeEmail } from './emails/welcome'; const resend = new Resend(process.env.RESEND_API_KEY); const { data, error } = await resend.emails.send({ from: 'Acme <onboarding@resend.dev>', to: ['user@example.com'], subject: 'Welcome to Acme', react: <WelcomeEmail name="John" verificationUrl="https://example.com/verify" /> }); ``` The Resend Node SDK automatically handles both HTML and plain-text rendering. ## CLI Commands The `react-email` package provides a CLI accessible via the `email` command: | Command | Description | |---------|-------------| | `email dev --dir <path> --port <port>` | Start the preview development server (default: `./emails`, port 3000) | | `email build --dir <path>` | Build the preview app for production deployment | | `email start` | Run the built preview app | | `email export --outDir <path> --pretty --plainText --dir <path>` | Export templates to static HTML files | | `email resend setup` | Connect the CLI to your Resend account via API key | | `email resend reset` | Remove the stored Resend API key | ## Internationalization See [references/I18N.md](references/I18N.md) for complete i18n documentation. React Email supports three libraries: next-intl, react-i18next, and react-intl. ## Email Editor React Email includes a visual editor (`@react-email/editor`) that can be embedded in your app. It's built on TipTap/ProseMirror and produces email-ready HTML. See [references/EDITOR.md](references/EDITOR.md) for complete documentation including: - `EmailEditor` — batteries-included component with bubble menus, slash commands, and theming - `StarterKit` — 35+ email-aware extensions (headings, lists, tables, columns, buttons, etc.) - `Inspector` — contextual sidebar for editing styles - `EmailTheming` — built-in themes (`basic`, `minimal`) with customizable CSS properties - `composeReactEmail` — export editor content to email-ready HTML and plain text - Custom extensions via `EmailNode` and `EmailMark` Quick example: ```tsx import { EmailEditor, type EmailEditorRef } from '@react-email/editor'; import '@react-email/editor/themes/default.css'; import { useRef } from 'react'; export function MyEditor() { const ref = useRef<EmailEditorRef>(null); return ( <EmailEditor ref={ref} content="<p>Start typing...</p>" theme="basic" /> ); } ``` ## Common Patterns See [references/PATTERNS.md](references/PATTERNS.md) for complete examples including: - Password reset emails - Order confirmations with product lists - Notification emails with code blocks - Multi-column layouts - Team invitation emails ## Email Best Practices 1. **Test across email clients** - Gmail, Outlook, Apple Mail, Yahoo Mail 2. **Keep it responsive** - Max-width around 600px, test on mobile 3. **Use absolute image URLs** - Host on reliable CDN, always include `alt` text 4. **Provide plain text version** - Required for accessibility 5. **Keep file size under 102KB** - Gmail clips larger emails 6. **Add proper TypeScript types** - Define interfaces for all email props 7. **Include preview props** - Add `.PreviewProps` for development testing 8. **Use verified domains** - For production `from` addresses ## Additional Resources - [React Email Documentation](https://react.email/docs/llms.txt) - [React Email GitHub](https://github.com/resend/react-email) - [Resend Documentation](https://resend.com/docs/llms.txt) - [Email Client CSS Support](https://www.caniemail.com) - Component Reference: [references/COMPONENTS.md](references/COMPONENTS.md) - Styling Guide: [references/STYLING.md](references/STYLING.md) - Email Editor: [references/EDITOR.md](references/EDITOR.md) - Sending Guide: [references/SENDING.md](references/SENDING.md) - Internationalization Guide: [references/I18N.md](references/I18N.md) - Common Patterns: [references/PATTERNS.md](references/PATTERNS.md)skills/resend-cli/SKILL.mdskillShow content (8831 bytes)
--- name: resend-cli description: > Operate the Resend platform from the terminal — send emails (including React Email .tsx templates via --react-email), manage domains, contacts, broadcasts, templates, webhooks, API keys, logs, automations, and events via the `resend` CLI. Use when the user wants to run Resend commands in the shell, scripts, or CI/CD pipelines, or send/preview React Email templates. Always load this skill before running `resend` commands — it contains the non-interactive flag contract and gotchas that prevent silent failures. license: MIT metadata: author: resend version: "2.0.1" homepage: https://resend.com/docs/cli-agents source: https://github.com/resend/resend-cli openclaw: primaryEnv: RESEND_API_KEY requires: env: - RESEND_API_KEY bins: - resend envVars: - name: RESEND_API_KEY required: true description: Resend API key for authenticating CLI commands - name: RESEND_PROFILE required: false description: Named auth profile for multi-account setups install: - kind: node package: resend-cli bins: [resend] label: Resend CLI links: repository: https://github.com/resend/resend-cli documentation: https://resend.com/docs/cli inputs: - name: RESEND_API_KEY description: Resend API key for authenticating CLI commands. Get yours at https://resend.com/api-keys required: true - name: RESEND_PROFILE description: Named auth profile for multi-account setups. Selects which stored API key to use (see `resend auth`). required: false references: - references/emails.md - references/domains.md - references/api-keys.md - references/automations.md - references/broadcasts.md - references/contacts.md - references/contact-properties.md - references/segments.md - references/templates.md - references/topics.md - references/logs.md - references/webhooks.md - references/auth.md - references/workflows.md - references/error-codes.md --- # Resend CLI ## Installation Before running any `resend` commands, check whether the CLI is installed: ```bash resend --version ``` If the command is not found, install it using one of the methods below: **cURL (macOS / Linux):** ```bash curl -fsSL https://resend.com/install.sh | bash ``` **Homebrew (macOS / Linux):** ```bash brew install resend/cli/resend ``` **Node.js:** ```bash npm install -g resend-cli ``` **PowerShell (Windows):** ```powershell irm https://resend.com/install.ps1 | iex ``` After installing, verify: ```bash resend --version ``` ## Agent Protocol The CLI auto-detects non-TTY environments and outputs JSON — no `--json` flag needed. **Rules for agents:** - Supply ALL required flags. The CLI will NOT prompt when stdin is not a TTY. - Pass `--quiet` (or `-q`) to suppress spinners and status messages. - Exit `0` = success, `1` = error. - Error JSON goes to stderr, success JSON goes to stdout: ```json {"error":{"message":"...","code":"..."}} ``` - Use `--api-key` or `RESEND_API_KEY` env var. Never rely on interactive login. - All `delete`/`rm` commands require `--yes` in non-interactive mode. ## Authentication Auth resolves: `--api-key` flag > `RESEND_API_KEY` env > config file (`resend login --key`). Use `--profile` or `RESEND_PROFILE` for multi-profile. ## Global Flags | Flag | Description | |------|-------------| | `--api-key <key>` | Override API key for this invocation | | `-p, --profile <name>` | Select stored profile | | `--json` | Force JSON output (auto in non-TTY) | | `-q, --quiet` | Suppress spinners/status (implies `--json`) | ## Available Commands | Command Group | What it does | |--------------|-------------| | `emails` | send, get, list, batch, cancel, update | | `emails receiving` | list, get, attachments, forward, listen | | `domains` | create, verify, update, delete, list | | `logs` | list, get, open | | `api-keys` | create, list, delete | | `automations` | create, get, list, update, delete, stop, open, runs | | `events` | create, get, list, update, delete, send, open | | `broadcasts` | create, send, update, delete, list | | `contacts` | create, update, delete, segments, topics | | `contact-properties` | create, update, delete, list | | `segments` | create, get, list, delete, contacts | | `templates` | create, publish, duplicate, delete, list | | `topics` | create, update, delete, list | | `webhooks` | create, update, listen, delete, list | | `auth` | login, logout, switch, rename, remove | | `whoami` / `doctor` / `update` / `open` / `commands` | Utility commands | Read the matching reference file for detailed flags and output shapes. **Dry-run:** Only `emails send` and `broadcasts create` support `--dry-run` (payload validation before send/create). They print `{ "dryRun": true, "request": { ... } }` on stdout without calling the API. There is no `--dry-run` on `emails batch`, `broadcasts send`, or other commands yet. ## Common Mistakes | # | Mistake | Fix | |---|---------|-----| | 1 | **Forgetting `--yes` on delete commands** | All `delete`/`rm` subcommands require `--yes` in non-interactive mode — otherwise the CLI exits with an error | | 2 | **Not saving webhook `signing_secret`** | `webhooks create` shows the secret once only — it cannot be retrieved later. Capture it from command output immediately | | 3 | **Omitting `--quiet` in CI** | Without `-q`, spinners and status text still go to stderr (not stdout). Use `-q` for JSON on stdout with no spinner noise on stderr | | 4 | **Using `--scheduled-at` with batch** | Batch sending does not support `scheduled_at` — use single `emails send` instead | | 5 | **Expecting `domains list` to include DNS records** | List returns summaries only — use `domains get <id>` for the full `records[]` array | | 6 | **Sending a dashboard-created broadcast via CLI** | Only API-created broadcasts can be sent with `broadcasts send` — dashboard broadcasts must be sent from the dashboard | | 7 | **Passing `--events` to `webhooks update` expecting additive behavior** | `--events` replaces the entire subscription list — always pass the complete set | | 8 | **Expecting `logs list` to include request/response bodies** | List returns summary fields only — use `logs get <id>` for full `request_body` and `response_body` | ## Common Patterns **Send an email:** ```bash resend emails send --from "you@domain.com" --to user@example.com --subject "Hello" --text "Body" ``` **Send a React Email template (.tsx):** ```bash resend emails send --from "you@domain.com" --to user@example.com --subject "Welcome" --react-email ./emails/welcome.tsx ``` **Domain setup flow:** ```bash resend domains create --name example.com --region us-east-1 # Configure DNS records from output, then: resend domains verify <domain-id> resend domains get <domain-id> # check status ``` **Create and send a broadcast:** ```bash resend broadcasts create --from "news@domain.com" --subject "Update" --segment-id <id> --html "<h1>Hi</h1>" --send ``` **CI/CD (no login needed):** ```bash RESEND_API_KEY=re_xxx resend emails send --from ... --to ... --subject ... --text ... ``` **Check environment health:** ```bash resend doctor -q ``` ## When to Load References - **Sending or reading emails** → [references/emails.md](references/emails.md) - **Setting up or verifying a domain** → [references/domains.md](references/domains.md) - **Managing API keys** → [references/api-keys.md](references/api-keys.md) - **Creating or sending broadcasts** → [references/broadcasts.md](references/broadcasts.md) - **Managing contacts, segments, or topics** → [references/contacts.md](references/contacts.md), [references/segments.md](references/segments.md), [references/topics.md](references/topics.md) - **Defining contact properties** → [references/contact-properties.md](references/contact-properties.md) - **Working with templates** → [references/templates.md](references/templates.md) - **Viewing API request logs** → [references/logs.md](references/logs.md) - **Creating automations or sending events** → [references/automations.md](references/automations.md) - **Setting up webhooks or listening for events** → [references/webhooks.md](references/webhooks.md) - **Auth, profiles, or health checks** → [references/auth.md](references/auth.md) - **Multi-step recipes** (setup, CI/CD, broadcast workflow) → [references/workflows.md](references/workflows.md) - **Command failed with an error** → [references/error-codes.md](references/error-codes.md) - **Resend SDK integration** (Node.js, Python, Go, etc.) → Install the [`resend`](https://github.com/resend/resend-skills) skill - **AI agent email inbox** → Install the [`agent-email-inbox`](https://github.com/resend/resend-skills) skillskills/resend/SKILL.mdskillShow content (14303 bytes)
--- name: resend description: Use when working with the Resend email API — sending transactional emails (single or batch), receiving inbound emails via webhooks, managing email templates, tracking delivery events, managing domains, contacts, broadcasts, webhooks, API keys, automations, events, viewing API request logs, or setting up the Resend SDK. Always use this skill when the user mentions Resend, even for simple tasks like "send an email with Resend" — the skill contains critical gotchas (idempotency keys, webhook verification, template variable syntax) that prevent common production issues. license: MIT metadata: author: resend version: "3.3.3" homepage: https://resend.com/agent-skills source: https://github.com/resend/resend-skills openclaw: primaryEnv: RESEND_API_KEY requires: env: - RESEND_API_KEY envVars: - name: RESEND_API_KEY required: true description: Resend API key for sending and receiving emails - name: RESEND_WEBHOOK_SECRET required: false description: Webhook signing secret for verifying event payloads links: repository: https://github.com/resend/resend-skills documentation: https://resend.com/docs/resend-skill inputs: - name: RESEND_API_KEY description: Resend API key for sending and receiving emails. Get yours at https://resend.com/api-keys required: true - name: RESEND_WEBHOOK_SECRET description: Webhook signing secret for verifying event payloads. Found in the Resend dashboard under Webhooks after creating an endpoint. required: false references: - sending - receiving.md - templates.md - webhooks.md - domains.md - contacts.md - broadcasts.md - api-keys.md - logs.md - contact-properties.md - segments.md - topics.md - automations.md - events.md - installation.md - fetch-all-templates.mjs --- # Resend ## Quick Send — Node.js ```typescript import { Resend } from 'resend'; const resend = new Resend(process.env.RESEND_API_KEY); const { data, error } = await resend.emails.send( { from: 'Acme <onboarding@resend.dev>', to: ['delivered@resend.dev'], subject: 'Hello World', html: '<p>Email body here</p>', }, { idempotencyKey: `welcome-email/${userId}` } ); if (error) { console.error('Failed:', error.message); return; } console.log('Sent:', data.id); ``` **Key gotcha:** The Resend Node.js SDK does NOT throw exceptions — it returns `{ data, error }`. Always check `error` explicitly instead of using try/catch for API errors. ## Quick Send — Python ```python import resend import os resend.api_key = os.environ["RESEND_API_KEY"] email = resend.Emails.send({ "from": "Acme <onboarding@resend.dev>", "to": ["delivered@resend.dev"], "subject": "Hello World", "html": "<p>Email body here</p>", }, idempotency_key=f"welcome-email/{user_id}") ``` ### Single vs Batch Decision | Choose | When | |--------|------| | **Single** (`POST /emails`) | 1 email, needs attachments, needs scheduling | | **Batch** (`POST /emails/batch`) | 2-100 distinct emails, no attachments, no scheduling | Batch is atomic — if one email fails validation, the entire batch fails. Always validate before sending. Batch does NOT support attachments or `scheduled_at`. ### Idempotency Keys (Critical for Retries) Prevent duplicate emails when retrying failed requests: | Key Facts | | |-----------|---| | **Format (single)** | `<event-type>/<entity-id>` (e.g., `welcome-email/user-123`) | | **Format (batch)** | `batch-<event-type>/<batch-id>` (e.g., `batch-orders/batch-456`) | | **Expiration** | 24 hours | | **Max length** | 256 characters | | **Same key + same payload** | Returns original response without resending | | **Same key + different payload** | Returns 409 error | ## Quick Receive (Node.js) ```typescript import { Resend } from 'resend'; const resend = new Resend(process.env.RESEND_API_KEY); export async function POST(req: Request) { const payload = await req.text(); // Must use raw text, not req.json() const event = resend.webhooks.verify({ payload, headers: { 'svix-id': req.headers.get('svix-id'), 'svix-timestamp': req.headers.get('svix-timestamp'), 'svix-signature': req.headers.get('svix-signature'), }, secret: process.env.RESEND_WEBHOOK_SECRET, }); if (event.type === 'email.received') { // Webhook has metadata only — call API for body const { data: email } = await resend.emails.receiving.get( event.data.email_id ); console.log(email.text); } return new Response('OK', { status: 200 }); } ``` **Key gotcha:** Webhook payloads do NOT contain the email body. You must call `resend.emails.receiving.get()` separately. ## What Do You Need? | Task | Reference | |------|-----------| | **Send a single email** | [sending/overview.md](references/sending/overview.md) — parameters, deliverability, testing | | **Send batch emails** | [sending/overview.md](references/sending/overview.md) → [sending/batch-email-examples.md](references/sending/batch-email-examples.md) | | **Full SDK examples** (Node.js, Python, Go, cURL) | [sending/single-email-examples.md](references/sending/single-email-examples.md) | | **Idempotency, retries, error handling** | [sending/best-practices.md](references/sending/best-practices.md) | | **Get, list, reschedule, cancel emails** | [sending/email-management.md](references/sending/email-management.md) | | **Receive inbound emails** | [receiving.md](references/receiving.md) — domain setup, webhooks, attachments | | **Manage templates** (CRUD, variables) | [templates.md](references/templates.md) — lifecycle, aliases, pagination | | **Set up webhooks** (events, verification) | [webhooks.md](references/webhooks.md) — verification, CRUD, retry schedule, IP allowlist | | **Manage domains** (create, verify, DNS) | [domains.md](references/domains.md) — regions, TLS, tracking, capabilities | | **Manage contacts** (CRUD, properties) | [contacts.md](references/contacts.md) — segments, topics, custom properties | | **Send broadcasts** (marketing campaigns) | [broadcasts.md](references/broadcasts.md) — lifecycle, scheduling, template variables | | **Manage API keys** | [api-keys.md](references/api-keys.md) — permission scoping, domain restrictions | | **View API request logs** | [logs.md](references/logs.md) — list and retrieve API call history, debugging | | **Define contact properties** | [contact-properties.md](references/contact-properties.md) — custom fields for contacts | | **Manage segments** (contact groups) | [segments.md](references/segments.md) — broadcast targeting, contact grouping | | **Manage topics** (subscriptions) | [topics.md](references/topics.md) — opt-in/out preferences, broadcast filtering | | **Create automations** (event-driven workflows) | [automations.md](references/automations.md) — steps, connections, runs, conditions | | **Define and send events** (automation triggers) | [events.md](references/events.md) — schemas, payloads, contact association | | **Install SDK** (8+ languages) | [installation.md](references/installation.md) | | **Set up an AI agent inbox** | Install the `agent-email-inbox` skill — covers security levels for untrusted input | ## SDK Version Requirements Always install the latest SDK version. These are the minimum versions for full functionality (sending, receiving, webhook verification): | Language | Package | Min Version | Install | |----------|---------|-------------|---------| | Node.js | `resend` | >= 6.9.2 | `npm install resend` | | Python | `resend` | >= 2.21.0 | `pip install resend` | | Go | `resend-go/v3` | >= 3.1.0 | `go get github.com/resend/resend-go/v3` | | Ruby | `resend` | >= 1.0.0 | `gem install resend` | | PHP | `resend/resend-php` | >= 1.1.0 | `composer require resend/resend-php` | | Rust | `resend-rs` | >= 0.20.0 | `cargo add resend-rs` | | Java | `resend-java` | >= 4.11.0 | See [installation.md](references/installation.md) | | .NET | `Resend` | >= 0.2.1 | `dotnet add package Resend` | > **If the project already has a Resend SDK installed**, check the version and upgrade if it's below the minimum. Older SDKs may be missing `webhooks.verify()` or `emails.receiving.get()`. See [installation.md](references/installation.md) for full installation commands, language detection, and cURL fallback. ## Common Setup ### API Key Store in environment variable — never hardcode: ```bash export RESEND_API_KEY=re_xxxxxxxxx ``` Get your key at [resend.com/api-keys](https://resend.com/api-keys). ### Detect Project Language Check for these files: `package.json` (Node.js), `requirements.txt`/`pyproject.toml` (Python), `go.mod` (Go), `Gemfile` (Ruby), `composer.json` (PHP), `Cargo.toml` (Rust), `pom.xml`/`build.gradle` (Java), `*.csproj` (.NET). ## Common Mistakes | # | Mistake | Fix | |---|---------|-----| | 1 | **Retrying without idempotency key** | Always include idempotency key — prevents duplicate sends on retry. Format: `<event-type>/<entity-id>` | | 2 | **Not verifying webhook signatures** | Always verify with `resend.webhooks.verify()` — unverified events can't be trusted | | 3 | **Template variable name mismatch** | Variable names are case-sensitive — must match the template definition exactly. Use triple mustache `{{{VAR}}}` syntax | | 4 | **Expecting email body in webhook payload** | Webhooks contain metadata only — call `resend.emails.receiving.get()` for body content | | 5 | **Using try/catch for Node.js SDK errors** | SDK returns `{ data, error }` — check `error` explicitly, don't wrap in try/catch | | 6 | **Using batch for emails with attachments** | Batch doesn't support attachments — use single sends instead | | 7 | **Testing with fake emails (test@gmail.com)** | Use `delivered@resend.dev` — fake addresses bounce and hurt reputation | | 8 | **Sending with draft template** | Templates must be published before sending — call `.publish()` first | | 9 | **`html` + `template` in same send call** | Mutually exclusive — remove `html`/`text`/`react` when using template | | 10 | **MX record not lowest priority for inbound** | Ensure Resend's MX has the lowest number (highest priority) or emails won't route | | 11 | **403 when sending from `resend.dev`** | The default `onboarding@resend.dev` is a sandbox — it can only deliver to your Resend account email. Verify your own domain first | | 12 | **403 domain mismatch** | The `from` address domain must exactly match a verified domain. Verified `send.acme.com` but sending from `user@acme.com` will fail | | 13 | **Calling Resend API from the browser (CORS)** | The API does not support CORS — this is intentional to protect your API key. Always call from server-side (API routes, serverless functions) | | 14 | **401 `restricted_api_key`** | A sending-only API key was used on a non-sending endpoint (domains, contacts, etc.). Create a full-access key instead | ## Cross-Cutting Concerns ### Send + Receive Together Auto-replies, email forwarding, or any receive-then-send workflow requires both capabilities: 1. Set up inbound domain first (see [receiving.md](references/receiving.md)) 2. Set up sending (see [sending/overview.md](references/sending/overview.md)) 3. Note: batch sending does NOT support attachments or scheduling — use single sends when forwarding with attachments ### AI Agent Inbox If your system processes untrusted email content and takes actions (refunds, database changes, forwarding), install the `agent-email-inbox` skill. This applies whether or not AI is involved — any system interpreting freeform email content from external senders needs security measures. ### Marketing Emails The sending capabilities in this skill are for **transactional email** (receipts, confirmations, notifications). For marketing campaigns to large subscriber lists with unsubscribe links and engagement tracking, use Resend Broadcasts — see [broadcasts.md](references/broadcasts.md) for the API. ### Domain Warm-up New domains must gradually increase sending volume. Day 1 limit: ~150 emails (new domain) or ~1,000 (existing domain). See the warm-up schedule in [sending/overview.md](references/sending/overview.md). ### Testing **Never test with fake addresses at real email providers** (test@gmail.com, fake@outlook.com) — they bounce and destroy sender reputation. | Address | Result | |---------|--------| | `delivered@resend.dev` | Simulates successful delivery | | `bounced@resend.dev` | Simulates hard bounce | | `complained@resend.dev` | Simulates spam complaint | ### Suppression List Resend automatically suppresses hard-bounced and spam-complained addresses. Sending to suppressed addresses fires the `email.suppressed` webhook event instead of attempting delivery. Manage in Dashboard → Suppressions. ### Webhook Event Types | Event | Trigger | |-------|---------| | `email.sent` | API request successful | | `email.delivered` | Reached recipient's mail server | | `email.bounced` | Permanently rejected (hard bounce) | | `email.complained` | Recipient marked as spam | | `email.opened` / `email.clicked` | Recipient engagement | | `email.delivery_delayed` | Soft bounce, Resend retries | | `email.received` | Inbound email arrived | | `domain.*` / `contact.*` | Domain/contact changes | See [webhooks.md](references/webhooks.md) for full details, signature verification, and retry schedule. ## Error Handling Quick Reference | Code | Action | |------|--------| | 400, 422 | Fix request parameters, don't retry | | 401 | Check API key — `restricted_api_key` means sending-only key used on non-sending endpoint | | 403 | Verify domain ownership — common causes: `resend.dev` sandbox, `from` domain mismatch, unverified domain | | 409 | Idempotency conflict — use new key or fix payload | | 429 | Rate limited — retry with exponential backoff (default rate limit: 2 req/s) | | 500 | Server error — retry with exponential backoff | ## Resources - [Resend Documentation](https://resend.com/docs) - [API Reference](https://resend.com/docs/api-reference) - [Dashboard](https://resend.com/emails)skills/agent-email-inbox/SKILL.mdskillShow content (16300 bytes)
--- name: agent-email-inbox description: Use when building any system where email content triggers actions — AI agent inboxes, automated support handlers, email-to-task pipelines, or any workflow processing untrusted inbound email. Always use this skill when the user wants to receive emails and act on them programmatically, even if they don't mention "agent" — the skill contains critical security patterns (sender allowlists, content filtering, sandboxed processing) that prevent untrusted email from controlling your system. license: MIT metadata: author: resend version: "3.0.2" homepage: https://resend.com/agent-skills source: https://github.com/resend/resend-skills openclaw: primaryEnv: RESEND_API_KEY requires: env: - RESEND_API_KEY envVars: - name: RESEND_API_KEY required: true description: Resend API key for sending and receiving emails - name: RESEND_WEBHOOK_SECRET required: false description: Webhook signing secret for verifying inbound email event payloads - name: SECURITY_LEVEL required: false description: Security level for inbound email processing (strict, moderate, permissive) - name: ALLOWED_SENDERS required: false description: Comma-separated list of allowed sender email addresses - name: ALLOWED_DOMAINS required: false description: Comma-separated list of allowed sender domains - name: OWNER_EMAIL required: false description: Owner email address for forwarding or notifications links: repository: https://github.com/resend/resend-skills documentation: https://resend.com/docs/agent-email-inbox-skill inputs: - name: RESEND_API_KEY description: Resend API key for sending and receiving emails. Get yours at https://resend.com/api-keys required: true - name: RESEND_WEBHOOK_SECRET description: Webhook signing secret for verifying inbound email event payloads. Returned as `signing_secret` in the response when you create a webhook via the API. required: true references: - security-levels.md - webhook-setup.md - advanced-patterns.md --- # AI Agent Email Inbox ## Overview This skill covers setting up a secure email inbox that allows your application or AI agent to receive and respond to emails, with content safety measures in place. **Core principle:** An AI agent's inbox receives untrusted input. Security configuration is important to handle this safely. ### Why Webhook-Based Receiving? Resend uses webhooks for inbound email, meaning your agent is notified **instantly** when an email arrives. This is valuable for agents because: - **Real-time responsiveness** — React to emails within seconds, not minutes - **No polling overhead** — No cron jobs checking "any new mail?" repeatedly - **Event-driven architecture** — Your agent only wakes up when there's actually something to process - **Lower API costs** — No wasted calls checking empty inboxes ## Architecture ``` Sender → Email → Resend (MX) → Webhook → Your Server → AI Agent ↓ Security Validation ↓ Process or Reject ``` ## SDK Version Requirements This skill requires Resend SDK features for webhook verification (`webhooks.verify()`) and email receiving (`emails.receiving.get()`). Always install the latest SDK version. If the project already has a Resend SDK installed, check the version and upgrade if needed. | Language | Package | Min Version | |----------|---------|-------------| | Node.js | `resend` | >= 6.9.2 | | Python | `resend` | >= 2.21.0 | | Go | `resend-go/v3` | >= 3.1.0 | | Ruby | `resend` | >= 1.0.0 | | PHP | `resend/resend-php` | >= 1.1.0 | | Rust | `resend-rs` | >= 0.20.0 | | Java | `resend-java` | >= 4.11.0 | | .NET | `Resend` | >= 0.2.1 | Install the `resend` npm package: `npm install resend` (or the equivalent for your language). For full sending docs, install the `resend` skill. ## Quick Start 1. **Ask the user for their email address** — You need a real email address to send test emails to. Ask the user and wait for their response before proceeding. 2. **Choose your security level** — Decide how to validate incoming emails *before* any are processed 3. **Set up receiving domain** — Configure MX records for the user's custom domain (see Domain Setup section) 4. **Create webhook endpoint** — Handle `email.received` events with security built in from the start. **The webhook endpoint MUST be a POST route.** 5. **Set up tunneling** (local dev) — Use Tailscale Funnel (recommended) or ngrok. See [references/webhook-setup.md](references/webhook-setup.md) 6. **Create webhook via API** — Use the Resend Webhook API to register your endpoint programmatically. See [references/webhook-setup.md](references/webhook-setup.md) 7. **Connect to agent** — Pass validated emails to your AI agent for processing ## Before You Start: Account & API Key Setup ### First Question: New or Existing Resend Account? Ask your human: - **New account just for the agent?** → Simpler setup, full account access is fine - **Existing account with other projects?** → Use domain-scoped API keys for sandboxing ### Creating API Keys Securely > Don't paste API keys in chat! They'll be in conversation history forever. **Safer options:** 1. **Environment file method:** Human creates `.env` file directly: `echo "RESEND_API_KEY=re_xxx" >> .env` 2. **Password manager / secrets manager:** Human stores key in 1Password, Vault, etc. 3. **If key must be shared in chat:** Human should rotate the key immediately after setup ### Domain-Scoped API Keys (Recommended for Existing Accounts) If your human has an existing Resend account with other projects, create a **domain-scoped API key**: 1. **Verify the agent's domain first** (Dashboard → Domains → Add Domain) 2. **Create a scoped API key:** Dashboard → API Keys → Create API Key → "Sending access" → select only the agent's domain 3. **Result:** Even if the key leaks, it can only send from one domain ## Domain Setup ### Option 1: Resend-Managed Domain (Recommended for Getting Started) Use your auto-generated address: `<anything>@<your-id>.resend.app` No DNS configuration needed. Find your address in Dashboard → Emails → Receiving → "Receiving address". ### Option 2: Custom Domain The user must enable receiving in the Resend dashboard: Domains page → toggle on "Enable Receiving". Then add an MX record: | Setting | Value | |---------|-------| | **Type** | MX | | **Host** | Your domain or subdomain (e.g., `agent.example.com`) | | **Value** | Provided in Resend dashboard | | **Priority** | 10 (must be lowest number to take precedence) | **Use a subdomain** (e.g., `agent.example.com`) to avoid disrupting existing email services. **Tip:** Verify DNS propagation at [dns.email](https://dns.email). > DNS Propagation: MX record changes can take up to 48 hours to propagate globally, though often complete within a few hours. ## Security Levels **Choose your security level before setting up the webhook endpoint.** An AI agent that processes emails without security is dangerous — anyone can email instructions that your agent will execute. The webhook code you write next should include your chosen security level from the start. Ask the user what level of security they want, and ensure that they understand what each level means. | Level | Name | When to Use | Trade-off | |-------|------|-------------|-----------| | **1** | Strict Allowlist | Most use cases — known, fixed set of senders | Maximum security, limited functionality | | **2** | Domain Allowlist | Organization-wide access from trusted domains | More flexible, anyone at domain can interact | | **3** | Content Filtering | Accept from anyone, filter unsafe patterns | Can receive from anyone, pattern matching not foolproof | | **4** | Sandboxed Processing | Process all emails with restricted agent capabilities | Maximum flexibility, complex to implement | | **5** | Human-in-the-Loop | Require human approval for untrusted actions | Maximum security, adds latency | For detailed implementation code for each level, see [references/security-levels.md](references/security-levels.md). ### Level 1: Strict Allowlist (Recommended) Only process emails from explicitly approved addresses. Reject everything else. ```typescript const ALLOWED_SENDERS = [ 'you@youremail.com', 'notifications@github.com', ]; async function processEmailForAgent( eventData: EmailReceivedEvent, emailContent: EmailContent ) { const sender = eventData.from.toLowerCase(); if (!ALLOWED_SENDERS.some(allowed => sender === allowed.toLowerCase())) { console.log(`Rejected email from unauthorized sender: ${sender}`); await notifyOwnerOfRejectedEmail(eventData); return; } await agent.processEmail({ from: eventData.from, subject: eventData.subject, body: emailContent.text || emailContent.html, }); } ``` ### Security Best Practices #### Always Do | Practice | Why | |----------|-----| | Verify webhook signatures | Prevents spoofed webhook events | | Log all rejected emails | Audit trail for security review | | Use allowlists where possible | Explicit trust is safer than filtering | | Rate limit email processing | Prevents excessive processing load | | Separate trusted/untrusted handling | Different risk levels need different treatment | #### Never Do | Anti-Pattern | Risk | |--------------|------| | Process emails without validation | Anyone can control your agent | | Trust email headers for authentication | Headers are trivially spoofed | | Execute code from email content | Untrusted input should never run as code | | Store email content in prompts verbatim | Untrusted input mixed into prompts can alter agent behavior | | Give untrusted emails full agent access | Scope capabilities to the minimum needed | ## Webhook Endpoint After choosing your security level and setting up your domain, create a webhook endpoint. **The webhook endpoint MUST be a POST route.** Resend sends all webhook events as POST requests. > **Critical: Use raw body for verification.** Webhook signature verification requires the raw request body. > - **Next.js App Router:** Use `req.text()` (not `req.json()`) > - **Express:** Use `express.raw({ type: 'application/json' })` on the webhook route ### Next.js App Router ```typescript // app/webhook/route.ts import { Resend } from 'resend'; import { NextRequest, NextResponse } from 'next/server'; const resend = new Resend(process.env.RESEND_API_KEY); export async function POST(req: NextRequest) { try { const payload = await req.text(); const event = resend.webhooks.verify({ payload, headers: { 'svix-id': req.headers.get('svix-id'), 'svix-timestamp': req.headers.get('svix-timestamp'), 'svix-signature': req.headers.get('svix-signature'), }, secret: process.env.RESEND_WEBHOOK_SECRET, }); if (event.type === 'email.received') { // Webhook payload only includes metadata, not email body const { data: email } = await resend.emails.receiving.get( event.data.email_id ); // Apply the security level chosen above await processEmailForAgent(event.data, email); } return new NextResponse('OK', { status: 200 }); } catch (error) { console.error('Webhook error:', error); return new NextResponse('Error', { status: 400 }); } } ``` ### Express ```javascript import express from 'express'; import { Resend } from 'resend'; const app = express(); const resend = new Resend(process.env.RESEND_API_KEY); app.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => { try { const payload = req.body.toString(); const event = resend.webhooks.verify({ payload, headers: { 'svix-id': req.headers['svix-id'], 'svix-timestamp': req.headers['svix-timestamp'], 'svix-signature': req.headers['svix-signature'], }, secret: process.env.RESEND_WEBHOOK_SECRET, }); if (event.type === 'email.received') { const sender = event.data.from.toLowerCase(); if (!isAllowedSender(sender)) { console.log(`Rejected email from unauthorized sender: ${sender}`); res.status(200).send('OK'); // Return 200 even for rejected emails return; } const { data: email } = await resend.emails.receiving.get(event.data.email_id); await processEmailForAgent(event.data, email); } res.status(200).send('OK'); } catch (error) { console.error('Webhook error:', error); res.status(400).send('Error'); } }); app.get('/', (req, res) => res.send('Agent Email Inbox - Ready')); app.listen(3000, () => console.log('Webhook server running on :3000')); ``` For webhook registration via API, tunneling setup, svix fallback, and retry behavior, see [references/webhook-setup.md](references/webhook-setup.md). ## Sending Emails from Your Agent ```typescript import { Resend } from 'resend'; const resend = new Resend(process.env.RESEND_API_KEY); async function sendAgentReply(to: string, subject: string, body: string, inReplyTo?: string) { if (!isAllowedToReply(to)) { throw new Error('Cannot send to this address'); } const { data, error } = await resend.emails.send({ from: 'Agent <agent@example.com>', to: [to], subject: subject.startsWith('Re:') ? subject : `Re: ${subject}`, text: body, headers: inReplyTo ? { 'In-Reply-To': inReplyTo } : undefined, }); if (error) throw new Error(`Failed to send: ${error.message}`); return data.id; } ``` For full sending docs, install the `resend` skill. ## Environment Variables ```bash # Required RESEND_API_KEY=re_xxxxxxxxx RESEND_WEBHOOK_SECRET=whsec_xxxxxxxxx # Security Configuration SECURITY_LEVEL=strict # strict | domain | filtered | sandboxed ALLOWED_SENDERS=you@email.com,trusted@example.com ALLOWED_DOMAINS=example.com OWNER_EMAIL=you@email.com # For security notifications ``` ## Common Mistakes | Mistake | Fix | |---------|-----| | No sender verification | Always validate who sent the email before processing | | Trusting email headers | Use webhook verification, not email headers for auth | | Same treatment for all emails | Differentiate trusted vs untrusted senders | | Verbose error messages | Keep error responses generic to avoid leaking internal logic | | No rate limiting | Implement per-sender rate limits. See [references/advanced-patterns.md](references/advanced-patterns.md) | | Processing HTML directly | Strip HTML or use text-only to reduce complexity and risk | | No logging of rejections | Log all security events for audit | | Using ephemeral tunnel URLs | Use persistent URLs (Tailscale Funnel, paid ngrok) or deploy to production | | Using `express.json()` on webhook route | Use `express.raw({ type: 'application/json' })` — JSON parsing breaks signature verification | | Returning non-200 for rejected emails | Always return 200 to acknowledge receipt — otherwise Resend retries | | Old Resend SDK version | `emails.receiving.get()` and `webhooks.verify()` require recent SDK versions — see SDK Version Requirements | ## Testing Use Resend's test addresses for development: - `delivered@resend.dev` — Simulates successful delivery - `bounced@resend.dev` — Simulates hard bounce For security testing, send test emails from non-allowlisted addresses to verify rejection works correctly. **Quick verification checklist:** 1. Server is running: `curl http://localhost:3000` should return a response 2. Tunnel is working: `curl https://<your-tunnel-url>` should return the same response 3. Webhook is active: Check status in Resend dashboard → Webhooks 4. Send a test email from an allowlisted address and check server logs ## Related Skills - For full sending and receiving docs, install the `resend` skill.mcp.jsonmcp_serverShow content (177 bytes)
{ "mcpServers": { "resend": { "command": "npx", "args": ["-y", "resend-mcp"], "env": { "RESEND_API_KEY": "${RESEND_API_KEY}" } } } }.cursor-plugin/marketplace.jsonmarketplaceShow content (181 bytes)
{ "name": "resend-skills", "owner": { "name": "Resend", "email": "support@resend.com" }, "plugins": [ { "name": "resend", "source": "./" } ] }.claude-plugin/marketplace.jsonmarketplaceShow content (296 bytes)
{ "name": "resend-skills", "metadata": { "description": "Resend email skills for Claude Code" }, "owner": { "name": "Resend", "email": "support@resend.com" }, "plugins": [ { "name": "resend", "source": "./", "category": "developer-tools" } ] }
README
Resend Skills
A collection of skills for AI coding agents following the Agent Skills format. Available as a plugin for Claude Code, Cursor, and OpenAI Codex. Includes an MCP server for tool access.
Install
npx skills add resend/resend-skills
Then select the ones you wish to install.
Available Skills
| Skill | Description | Source |
|---|---|---|
resend | Resend email API | Authored here |
agent-email-inbox | Secure email inbox for AI agents | Authored here |
resend-cli | Operate Resend from the terminal | Synced from resend/resend-cli |
react-email | Build HTML emails with React components | Synced from resend/react-email |
email-best-practices | Guidance for building deliverable, compliant, user-friendly emails | Synced from resend/email-best-practices |
MCP Server
The plugin includes the Resend MCP server, giving agents tool access to the full Resend API.
Plugins
This repo serves as a plugin for multiple platforms:
- Claude Code —
.claude-plugin/ - Cursor —
.cursor-plugin/ - OpenAI Codex —
.codex-plugin/
Editing skills
Skills marked "Authored here" can be edited directly in this repo.
Skills marked "Synced from" are automatically synced from their source repos. Do not edit them here — changes will be overwritten on the next sync. Edit in the source repo instead.
Prerequisites
- A Resend account with a verified domain
- API key stored in
RESEND_API_KEYenvironment variable
Get your API key at resend.com/api-keys
License
MIT