跳到正文
cccskills
免费在 GitHub 公开

resend-inbound

Use when receiving emails with Resend - setting up inbound domains, processing email.received webhooks, retrieving email content/attachments, or forwarding received emails. Triggers on "inbound email", "receive email", "email webhook", "Resend inbound", "process incoming email", "email forwarding", "email.received", "MX records for email".

中文简介正在准备中。当前显示原文说明。

查看安装方法

包含的文件(1)

  • SKILL.md8.8 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Receive Emails with Resend

Overview

Resend processes incoming emails for your domain and sends webhook events to your endpoint. Webhooks contain metadata only — you must call separate APIs to retrieve email body and attachments.

This skill is context-independent — it does not use brand/ files and works identically in any project.

On Activation

  1. Determine if the user needs a Resend-managed domain or custom domain.
  2. Walk through domain setup and webhook configuration.
  3. Implement webhook handler with signature verification.
  4. Add content retrieval logic (body + attachments as needed).
  5. Add routing logic if multiple recipients are expected.

Output: A webhook handler file with signature verification, content retrieval, and routing logic.

Quick Start

  1. Configure receiving domain — Use Resend's .resend.app domain or add MX record for custom domain
  2. Set up webhook — Subscribe to email.received event
  3. Retrieve content — Call Receiving API for body, Attachments API for files

Domain Setup

Option 1: Resend-Managed Domain (Fastest)

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

Add MX record to receive at <anything>@yourdomain.com.

SettingValue
TypeMX
HostYour domain or subdomain
ValueProvided in Resend dashboard
Priority10 (lowest number wins a conflict, but typically only multiples of 10 are used)

Critical: Your MX record must have the lowest priority value, or emails won't route to Resend.

Subdomain Recommendation

If you already have MX records (e.g., Google Workspace, Microsoft 365):

ApproachResult
Use subdomain (recommended)support.acme.com → Resend, acme.com → existing provider
Use root domainAll email routes to Resend (breaks existing email)
# Example: receive at support.acme.com without affecting acme.com
support.acme.com.  MX  10  <resend-mx-value>

If you set up Resend to receive email on a root domain, all traffic will be routed to Resend, not to any other mailbox. It's crucial, then, to use a subdomain with inbound emails.

Webhook Setup

Subscribe to email.received

Dashboard → Webhooks → Add Webhook → Select email.received

For local development, use tunneling (ngrok, VS Code Port Forwarding):

ngrok http 3000
# Use https://abc123.ngrok.io/api/webhook as endpoint

Webhook Payload Structure

Important: Payload contains metadata only, not email body or attachment content.

{
  "type": "email.received",
  "created_at": "2024-02-22T23:41:12.126Z",
  "data": {
    "email_id": "a1b2c3d4-...",
    "from": "sender@example.com",
    "to": ["support@acme.com"],
    "cc": [],
    "bcc": [],
    "subject": "Question about my order",
    "attachments": [
      {
        "id": "att_abc123",
        "filename": "receipt.pdf",
        "content_type": "application/pdf"
      }
    ]
  }
}

Verify Webhook Signatures

Always verify signatures to prevent spoofed events:

import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);

export async function POST(req: Request) {
  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') {
    // Process the email
  }

  return new Response('OK', { status: 200 });
}

Retrieving Email Content

Webhooks exclude email body and headers. Call the Receiving API to get them:

if (event.type === 'email.received') {
  const { data: email } = await resend.emails.receiving.get(
    event.data.email_id
  );

  console.log(email.html);    // HTML body
  console.log(email.text);    // Plain text body
  console.log(email.headers); // Email headers
}

Why this design? Serverless environments have request body size limits. Separating content retrieval supports large emails and attachments.

Handling Attachments

Get Attachment Metadata and Download URLs

const { data: attachments } = await resend.emails.receiving.attachments.list({
  emailId: event.data.email_id,
});

for (const attachment of attachments) {
  console.log(attachment.filename);
  console.log(attachment.download_url);  // Valid for 1 hour
  console.log(attachment.expires_at);
}

Download Attachment Content

const response = await fetch(attachment.download_url);
const buffer = await response.arrayBuffer();

// Save to storage, process, etc.
await saveToStorage(attachment.filename, buffer);

Important: download_url expires after 1 hour. Call the API again for a fresh URL if needed.

Forwarding Emails

Complete workflow to receive and forward an email with attachments:

import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);

export async function POST(req: Request) {
  const payload = await req.text();
  const event = resend.webhooks.verify({ /* ... */ });

  if (event.type === 'email.received') {
    // 1. Get email content
    const { data: email } = await resend.emails.receiving.get(
      event.data.email_id
    );

    // 2. Get attachments (if any)
    const { data: attachmentList } = await resend.emails.receiving.attachments.list({
      emailId: event.data.email_id,
    });

    // 3. Download and encode attachments
    const attachments = await Promise.all(
      attachmentList.map(async (att) => {
        const res = await fetch(att.download_url);
        const buffer = Buffer.from(await res.arrayBuffer());
        return {
          filename: att.filename,
          content: buffer.toString('base64'),
        };
      })
    );

    // 4. Forward the email
    await resend.emails.send({
      from: 'Support System <system@acme.com>',
      to: ['team@acme.com'],
      subject: `Fwd: ${email.subject}`,
      html: email.html,
      text: email.text,
      attachments,
    });
  }

  return new Response('OK', { status: 200 });
}

Routing by Recipient

All emails to your domain arrive at the same webhook. Route based on the to field:

if (event.type === 'email.received') {
  const recipient = event.data.to[0];

  if (recipient.includes('support@')) {
    await handleSupportEmail(event.data);
  } else if (recipient.includes('billing@')) {
    await handleBillingEmail(event.data);
  } else {
    await handleUnknownEmail(event.data);
  }
}

Error Handling

FailureAction
Webhook signature verification failsReturn 400, log the attempt. Never process unverified webhooks.
resend.emails.receiving.get() returns errorLog the email_id, return 200 to acknowledge webhook, queue for retry via your own retry logic.
Attachment download_url expiredCall resend.emails.receiving.attachments.list() again for a fresh URL.
Attachment download times outRetry with exponential backoff (max 3 attempts). Log failure if all retries exhaust.
Malformed email (missing from/subject)Log and skip gracefully. Return 200 to prevent Resend retries on bad data.

Anti-Patterns

MistakeFix
Expecting body in webhook payloadWebhook has metadata only — call resend.emails.receiving.get() for body
MX record not lowest priorityEnsure Resend's MX has lowest number (highest priority)
Adding MX to root domain with existing emailUse subdomain to avoid breaking existing email service
Using expired download_urlURLs expire after 1 hour — call attachments API again for fresh URL
Not verifying webhook signaturesAlways verify — attackers can send fake events
Forgetting to return 200 OKResend retries on non-200 responses

Storage Note

Resend stores received emails even if:

  • Webhook isn't configured yet
  • Webhook endpoint is down

View all received emails in Dashboard → Emails → Receiving tab.

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

Add a new expert to the Remotion experts page

中文简介正在准备中。当前显示原文说明。

MoizIbnYousaf/marketing-cli322026年9月12日 更新

add-sfx

免费

Add a new sound effect to @remotion/sfx

中文简介正在准备中。当前显示原文说明。

MoizIbnYousaf/marketing-cli322026年9月12日 更新

Use when setting up a secure email inbox for any AI agent — configuring inbound email via Resend, webhooks, tunneling for local development, and implementing security measures to prevent prompt injection attacks. Also use when someone mentions 'agent email', 'bot inbox', 'receive emails for agent', 'agent webhook', 'email security for AI', 'prompt injection via email', 'inbound email for bot', or wants their AI agent to receive and respond to emails securely.

中文简介正在准备中。当前显示原文说明。

MoizIbnYousaf/marketing-cli322026年9月12日 更新

ai-seo

免费

Builds, measures, and improves an Answer Engine Optimization program across ChatGPT, Perplexity, Claude, Gemini, Google AI Overviews, and Copilot. Use for AEO, GEO, LLMO, AI search visibility, AI citations, brand mentions, answer-engine monitoring, llms.txt, AI crawler audits, or questions like 'what does AI say about us?' and 'why are competitors cited instead of us?'. Produces a durable evidence report and prioritized gameplan, not a one-shot content checklist.

中文简介正在准备中。当前显示原文说明。

MoizIbnYousaf/marketing-cli322026年9月12日 更新

Generate Apple App Store screenshot pages as a Next.js app with html-to-image export at required resolutions. Screenshots are advertisements, not documentation — every screenshot sells one idea. Use when building App Store screenshots, generating exportable marketing screenshots for iOS apps, or creating programmatic screenshot generators. Triggers on 'app store screenshots', 'App Store', 'screenshot generator', 'iOS screenshots', 'marketing screenshots', 'phone mockup', 'ASO screenshots', 'app store assets', 'app listing', 'app store page', or 'app preview images'. Also use when someone is about to submit an app and needs store assets, or when they say 'make my app store page look good'. Includes iPhone and iPad mockup components with pre-measured dimensions.

中文简介正在准备中。当前显示原文说明。

MoizIbnYousaf/marketing-cli322026年9月12日 更新

Build detailed buyer personas and audience profiles from research. Use this skill whenever the user mentions audience, buyer persona, ideal customer, target market, ICP, watering holes, 'who am I selling to', customer research, or audience profile. Also use when content feels unfocused or generic (that's an audience problem), when conversion is low because messaging doesn't resonate, when starting any new project (audience should be first), or when any downstream skill needs audience.md but it doesn't exist yet. Even if the user doesn't explicitly ask for audience research, trigger this if they're writing copy or building a landing page without a clear audience defined. Three approaches: Quick Profile, Persona Build, Community Mining.

中文简介正在准备中。当前显示原文说明。

MoizIbnYousaf/marketing-cli322026年9月12日 更新

查看 MoizIbnYousaf 的全部技能

报告此技能的问题