email-resendSend and receive emails using the Resend API. Use for: (1) sending emails directly via Resend API, (2) receiving email notifications via cron, (3) drafting r...
Install via ClawdBot CLI:
clawdbot install ivelin/email-resendApache License 2.0 — See LICENSE file for full text.
Send and receive emails using the Resend API.
No config file needed. The skill auto-discovers settings from:
memory/email-preferences.md (from_email, from_name, telegram target)export RESEND_API_KEY="re_123456789" # Resend API key (required)
# DEFAULT_FROM_EMAIL and DEFAULT_FROM_NAME are optional - loaded from preferences file if not set
The skill reads sender info from memory/email-preferences.md:
---
from_email: you@company.com
from_name: Your Name
telegram:
target: "CHAT_ID"
threadId: "THREAD_ID"
---
Scripts check env vars first, then fall back to preferences file.
When the skill is first invoked, the sub-agent should:
context.user.email (from USER.md)context.channel (from current session)context.chat_idcontext.thread_id (for topics)memory_get tool:memory_get path="memory/email-preferences.md"memory/email-preferences.md (NO fallback scanning) Then create memory/email-preferences.md with their answers using the format above.
write path="memory/email-preferences.md" content="---
from_email: $EMAIL
from_name: $NAME
telegram:
target: \"$CHAT_ID\"
threadId: \"$THREAD_ID\"
---
# Email Notification Preferences
Saved auto-configured
"
This ensures memory_get finds it in future sessions. Use MD format with YAML frontmatter.
Format (MD with YAML frontmatter):
---
from_email: you@company.com
from_name: Your Name
telegram:
target: \"123456789\"
threadId: \"334\"
---
# Email Notification Preferences
- **Updated:** 2026-01-01
- **Purpose:** Default notification channel for email alerts
Important: Store in memory/email-preferences.md (NOT MEMORY.md) - isolated cron jobs can read this file via memory_get but NOT MEMORY.md.
| Field | Source | Example |
|-------|--------|---------|
| user.email | USER.md | you@company.com |
| user.name | USER.md | Your Name |
| channel | OpenClaw | from context |
| chat_id | OpenClaw | 123456789 |
| thread_id | OpenClaw | 334 |
The skill uses these directly from OpenClaw context — no parsing needed.
There are two ways to configure the cron:
Use this if you always want the same delivery target:
openclaw cron add \
--name "email-resend-inbound" \
--cron "*/15 * * * *" \
--message "Follow instructions in skills/email-resend/cron-prompts/email-inbound.md exactly. If new emails found, include them in your reply." \
--session isolated \
--announce \
--channel telegram \
--to "-1003748898773:topic:334"
This reads your notification preferences from memory/email-preferences.md and configures the cron automatically.
Run:
python3 ~/.openclaw/workspace/skills/email-resend/scripts/configure-cron.py
What it does:
memory/email-preferences.md for your telegram target/threadIdemail-resend-inbound cronFirst-time setup: If preferences don't exist, it will tell you what to configure.
Parameters:
--schedule "cron /15 *" — Run every 15 minutes--session isolated — Required for agentTurn payloads--announce — Enable delivery of results to chat--channel telegram — Delivery channel--to — Telegram target (format: chat_id:topic:thread_id)Note: The cron prompt reads notification preferences from memory/email-preferences.md. On first run, if preferences are missing, it will ask you for:
python3 ~/.openclaw/workspace/skills/email-resend/scripts/inbound.py
Each new email triggers a notification with:
NEVER auto-acknowledge emails. Only the user can acknowledge by:
done / ackEmails must remain in pending state until user explicitly acknowledges.
Use draft-reply.py to compose replies with proper quoting.
Important: Always use inline replies ([[reply_to_current]]) to keep messages linked in the thread. This enables:
CRITICAL: When responding via OpenClaw message tool, use replyTo parameter (not [[reply_to_current]] tag):
message(action="send", channel="<from-context>", replyTo="<msg_id>", ...)
| Script | Purpose |
|--------|---------|
| inbound.py | Check emails, send notifications |
| draft-reply.py | Draft reply workflow with quoting & threading |
| outbound.py | Send emails directly |
| download_attachment.py | Download attachments from inbound emails |
To download attachments from an inbound email:
# List attachments (shows IDs)
python3 scripts/download_attachment.py <email_id> --list
# Download all to directory
python3 scripts/download_attachment.py <email_id> --output-dir ./attachments
# Download specific attachment
python3 scripts/download_attachment.py <email_id> --attachment-id <attachment_id>
Note: The API path is /emails/receiving/{email_id}/attachments (not the standard /emails/ path).
memory/email-resend-inbound-notified.json — pending/acknowledged emailsmemory/email-message-map.json — notification message_id → email_id (legacy)memory/email-custody-chain.json — Full DAG of email → notification → actionsmemory/email-msg-to-chain.json — notification message_id → chain lookupmemory/email-draft-state.json — Active draft state (email_id, status, reply_content)See docs/custody-chain.md for DAG design.
python3 ~/.openclaw/workspace/skills/email-resend/scripts/outbound.py \
--to "recipient@example.com" \
--subject "Hello" \
--body "Message text"
# With attachments
python3 ~/.openclaw/workspace/skills/email-resend/scripts/outbound.py \
--to "recipient@example.com" \
--subject "Here's the file" \
--body "See attachment" \
--attachment ./file.pdf \
--attachment ./image.png
MANDATORY: Always use draft-reply.py for replying to emails.
This is non-negotiable. Failure to follow this rule will result in broken Gmail threading.
In-Reply-To AND References headers# Step 1: Start draft (fetches Message-ID automatically)
python3 ~/.openclaw/workspace/skills/email-resend/scripts/draft-reply.py start <email_id>
# Step 2: Set reply content
python3 ~/.openclaw/workspace/skills/email-resend/scripts/draft-reply.py content "Your reply"
# Step 3: Send
python3 ~/.openclaw/workspace/skills/email-resend/scripts/draft-reply.py send
When user approves a draft, you MUST execute the send command immediately.
The mistake to avoid:
draft-reply.py send → Then confirmCorrect workflow:
1. Show draft for approval
2. User replies "approve", "send", "yes", or "ok"
3. IMMEDIATELY run: draft-reply.py send
4. Only THEN confirm to user
Never:
NEVER use outbound.py for replies:
# WRONG - will break threading
python3 ~/.openclaw/workspace/skills/email-resend/scripts/outbound.py \
--to "x@y.com" --subject "Re: Original" --body "Reply"
NEVER manually construct --reply-to flags:
# WRONG - guessing Message-ID format never works
python3 ~/.openclaw/workspace/skills/email-resend/scripts/outbound.py \
--to "x@y.com" --subject "Re: Original" --body "Reply" \
--reply-to "<some-guess>@resend"
NEVER skip the workflow when subject starts with "Re:":
# WRONG - replying without threading headers breaks thread
python3 ~/.openclaw/workspace/skills/email-resend/scripts/outbound.py \
--to "x@y.com" --subject "Re: Previous Thread" --body "Quick reply"
outbound.py is for new emails only (not replies):
For anything that could be a reply, use draft-reply.py.
RESEND_API_KEY environment variable setrequests libraryWhen composing a reply via draft-reply.py:
> prefix so recipient knows what you're responding toIn-Reply-To and References headers using the original email's Message-IDRe: prefix to maintain thread (but avoid "Re: Re:")
Your reply here
---
On [date] [original sender] wrote:
> quoted original message
> continues here
resume command to continue.| Command | Purpose |
|---------|---------|
| start | Start a draft reply to an email |
| resume | Continue a sent thread to reply again |
| content "text" | Set reply content |
| send | Send the reply |
| cancel | Cancel the draft |
| status | Show current draft status |
After sending, use resume to reply again to the same thread — threading headers are preserved.
Run tests:
python3 skills/email-resend/tests/test_inbound.py
Expected: 43+ tests total (test_inbound.py: 37, test_threading.py: 6, test_attachments.py: varies).
If tests fail:
memory/email-preferences.md.The skill reads ONLY from explicit preferences file:
memory/email-preferences.md — Required for telegram target/threadIdThis restricted approach prevents information leakage from sensitive files.
The configure-cron.py script will create/delete a cron job named email-resend-inbound via OpenClaw CLI.
memory/email-preferences.md to ensure it contains only necessary fieldsGenerated Mar 1, 2026
Automatically send follow-up emails to customers after support tickets are resolved, ensuring consistent communication and gathering feedback. The cron job can check for new support emails every 15 minutes and notify agents via Telegram with priority tagging for urgent issues.
Schedule and send personalized email campaigns to segmented customer lists using Resend API. The skill can draft threaded replies to customer responses and download attachments like order confirmations or lead forms for CRM integration.
Use email notifications to keep distributed teams updated on project milestones and deadlines. The cron feature delivers email summaries to designated Telegram channels with topic threading, allowing team members to acknowledge updates directly in chat.
Automate confirmation emails to event registrants and send reminder notifications as the event approaches. The skill can handle inbound email queries, categorize them by importance (e.g., HIGH for urgent changes), and forward attachments like tickets or schedules.
Set up automated email checks for financial statements or transaction reports from banking systems. The cron job scans for new emails with attachments, notifies accountants via Telegram with previews, and ensures secure handling through isolated sessions.
Offer basic email sending and receiving features for free, with premium tiers for advanced cron scheduling, priority support, and higher email volumes. Revenue comes from subscription fees and API usage overages, targeting small businesses and startups.
License the skill as a customizable solution for marketing or support agencies to integrate into their client services. Revenue is generated through one-time setup fees and ongoing maintenance contracts, with upsells for custom triggers and integrations.
Bundle the skill with other AI tools to create a comprehensive communication suite for large organizations. Revenue streams include enterprise licensing, dedicated support, and training services, focusing on industries like finance and healthcare with strict compliance needs.
💬 Integration Tip
Ensure RESEND_API_KEY is securely stored as an environment variable and test cron jobs in isolated sessions first to avoid disrupting existing workflows.
CLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).
Read and send email via IMAP/SMTP. Check for new/unread messages, fetch content, search mailboxes, mark as read/unread, and send emails with attachments. Works with any IMAP/SMTP server including Gmail, Outlook, 163.com, vip.163.com, 126.com, vip.126.com, 188.com, and vip.188.com.
Gmail API integration with managed OAuth. Read, send, and manage emails, threads, labels, and drafts. Use this skill when users want to interact with Gmail. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).
Automatically logs into email accounts (Gmail, Outlook, QQ Mail, etc.) and generates daily email summaries. Use when the user wants to get a summary of their emails, check important messages, or create daily email digests.
Fetch content from Feishu (Lark) Wiki, Docs, Sheets, and Bitable. Automatically resolves Wiki URLs to real entities and converts content to Markdown.
Manage Feishu (Lark) calendars by listing, searching, checking schedules, syncing events, and marking tasks with automated date extraction.