email-delivery
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEmail Delivery Skill
邮件投递技能
Comprehensive patterns and templates for implementing robust email delivery with Resend, covering single emails, batch operations, scheduled delivery, and attachment handling.
本技能提供使用Resend实现可靠邮件投递的全面模式与模板,涵盖单封邮件发送、批量操作、定时投递以及附件处理。
Use When
适用场景
- Building transactional email systems (confirmations, notifications, alerts)
- Implementing batch email campaigns (up to 100 recipients per request)
- Setting up scheduled/delayed email delivery
- Handling file attachments, buffers, or URL-based attachments
- Adding reply-to, CC, and BCC functionality
- Creating email templates with variables and dynamic content
- Implementing retry logic and delivery error handling
- 构建事务性邮件系统(确认邮件、通知、告警)
- 实现批量邮件营销活动(单次请求最多支持100个收件人)
- 配置邮件定时/延迟投递
- 处理文件附件、缓冲区数据或基于URL的附件
- 添加回复地址、抄送(CC)和密送(BCC)功能
- 创建包含变量与动态内容的邮件模板
- 实现重试逻辑与投递错误处理
Core Patterns
核心模式
1. Single Email Sending
1. 单封邮件发送
Transactional emails for immediate delivery with minimal latency:
typescript
import { Resend } from 'resend';
const resend = new Resend('your_resend_key_here');
async function sendTransactionalEmail() {
const { data, error } = await resend.emails.send({
from: 'notifications@example.com',
to: 'user@example.com',
subject: 'Welcome to Example',
html: '<h1>Welcome!</h1><p>Thank you for signing up.</p>',
});
if (error) {
console.error('Failed to send email:', error);
return null;
}
return data;
}事务性邮件,实现低延迟即时投递:
typescript
import { Resend } from 'resend';
const resend = new Resend('your_resend_key_here');
async function sendTransactionalEmail() {
const { data, error } = await resend.emails.send({
from: 'notifications@example.com',
to: 'user@example.com',
subject: 'Welcome to Example',
html: '<h1>Welcome!</h1><p>Thank you for signing up.</p>',
});
if (error) {
console.error('Failed to send email:', error);
return null;
}
return data;
}2. Batch Email Sending
2. 批量邮件发送
Bulk operations for sending up to 100 emails in a single request:
typescript
async function sendBatchEmails(recipients: Array<{email: string; name: string}>) {
const emails = recipients.map(recipient => ({
from: 'newsletter@example.com',
to: recipient.email,
subject: `Hello ${recipient.name}!`,
html: `<p>Welcome ${recipient.name}</p>`,
}));
const { data, error } = await resend.batch.send(emails);
if (error) {
console.error('Batch send failed:', error);
return null;
}
return data;
}批量操作,单次请求最多发送100封邮件:
typescript
async function sendBatchEmails(recipients: Array<{email: string; name: string}>) {
const emails = recipients.map(recipient => ({
from: 'newsletter@example.com',
to: recipient.email,
subject: `Hello ${recipient.name}!`,
html: `<p>Welcome ${recipient.name}</p>`,
}));
const { data, error } = await resend.batch.send(emails);
if (error) {
console.error('Batch send failed:', error);
return null;
}
return data;
}3. Scheduled Email Delivery
3. 定时邮件投递
Time-based delivery for emails sent at specific times:
typescript
async function scheduleEmail(scheduledAt: Date) {
const { data, error } = await resend.emails.send({
from: 'marketing@example.com',
to: 'user@example.com',
subject: 'Scheduled Message',
html: '<p>This was scheduled!</p>',
scheduled_at: scheduledAt.toISOString(),
});
if (error) {
console.error('Failed to schedule email:', error);
return null;
}
return data;
}基于时间的投递,在指定时间发送邮件:
typescript
async function scheduleEmail(scheduledAt: Date) {
const { data, error } = await resend.emails.send({
from: 'marketing@example.com',
to: 'user@example.com',
subject: 'Scheduled Message',
html: '<p>This was scheduled!</p>',
scheduled_at: scheduledAt.toISOString(),
});
if (error) {
console.error('Failed to schedule email:', error);
return null;
}
return data;
}4. Attachment Handling
4. 附件处理
File attachments from files, buffers, or URLs:
文件附件,支持从文件、缓冲区或URL获取:
File-based Attachment
文件型附件
typescript
import fs from 'fs';
import path from 'path';
async function sendWithFileAttachment(filePath: string) {
const fileContent = fs.readFileSync(filePath);
const fileName = path.basename(filePath);
const { data, error } = await resend.emails.send({
from: 'documents@example.com',
to: 'recipient@example.com',
subject: 'Your Document',
html: '<p>Please find attached your document.</p>',
attachments: [
{
filename: fileName,
content: fileContent,
},
],
});
return { data, error };
}typescript
import fs from 'fs';
import path from 'path';
async function sendWithFileAttachment(filePath: string) {
const fileContent = fs.readFileSync(filePath);
const fileName = path.basename(filePath);
const { data, error } = await resend.emails.send({
from: 'documents@example.com',
to: 'recipient@example.com',
subject: 'Your Document',
html: '<p>Please find attached your document.</p>',
attachments: [
{
filename: fileName,
content: fileContent,
},
],
});
return { data, error };
}Buffer-based Attachment
缓冲区型附件
typescript
async function sendWithBufferAttachment(buffer: Buffer, filename: string) {
const { data, error } = await resend.emails.send({
from: 'reports@example.com',
to: 'user@example.com',
subject: 'Monthly Report',
html: '<p>Your monthly report is attached.</p>',
attachments: [
{
filename: filename,
content: buffer,
},
],
});
return { data, error };
}typescript
async function sendWithBufferAttachment(buffer: Buffer, filename: string) {
const { data, error } = await resend.emails.send({
from: 'reports@example.com',
to: 'user@example.com',
subject: 'Monthly Report',
html: '<p>Your monthly report is attached.</p>',
attachments: [
{
filename: filename,
content: buffer,
},
],
});
return { data, error };
}URL-based Attachment
URL型附件
typescript
async function sendWithUrlAttachment(fileUrl: string) {
const response = await fetch(fileUrl);
const buffer = await response.arrayBuffer();
const { data, error } = await resend.emails.send({
from: 'notifications@example.com',
to: 'user@example.com',
subject: 'Download Your File',
html: '<p>Your file is ready.</p>',
attachments: [
{
filename: 'document.pdf',
content: Buffer.from(buffer),
},
],
});
return { data, error };
}typescript
async function sendWithUrlAttachment(fileUrl: string) {
const response = await fetch(fileUrl);
const buffer = await response.arrayBuffer();
const { data, error } = await resend.emails.send({
from: 'notifications@example.com',
to: 'user@example.com',
subject: 'Download Your File',
html: '<p>Your file is ready.</p>',
attachments: [
{
filename: 'document.pdf',
content: Buffer.from(buffer),
},
],
});
return { data, error };
}5. Reply-To and CC/BCC
5. 回复地址与抄送/密送
Message routing with multiple recipients and reply addresses:
typescript
async function sendWithRouting(mainRecipient: string) {
const { data, error } = await resend.emails.send({
from: 'support@example.com',
to: mainRecipient,
reply_to: 'support-team@example.com',
cc: ['manager@example.com'],
bcc: ['archive@example.com'],
subject: 'Support Ticket #12345',
html: '<p>We received your support request.</p>',
});
return { data, error };
}消息路由,支持多收件人与指定回复地址:
typescript
async function sendWithRouting(mainRecipient: string) {
const { data, error } = await resend.emails.send({
from: 'support@example.com',
to: mainRecipient,
reply_to: 'support-team@example.com',
cc: ['manager@example.com'],
bcc: ['archive@example.com'],
subject: 'Support Ticket #12345',
html: '<p>We received your support request.</p>',
});
return { data, error };
}Python Patterns
Python实现模式
Single Email (Python)
单封邮件(Python)
python
import os
from resend import Resend
client = Resend(api_key=os.environ.get("RESEND_API_KEY"))
def send_email():
email = {
"from": "notifications@example.com",
"to": "user@example.com",
"subject": "Welcome",
"html": "<h1>Welcome!</h1>",
}
response = client.emails.send(email)
return responsepython
import os
from resend import Resend
client = Resend(api_key=os.environ.get("RESEND_API_KEY"))
def send_email():
email = {
"from": "notifications@example.com",
"to": "user@example.com",
"subject": "Welcome",
"html": "<h1>Welcome!</h1>",
}
response = client.emails.send(email)
return responseBatch Email (Python)
批量邮件(Python)
python
def send_batch_emails(recipients):
emails = [
{
"from": "newsletter@example.com",
"to": recipient["email"],
"subject": f"Hello {recipient['name']}",
"html": f"<p>Welcome {recipient['name']}</p>",
}
for recipient in recipients
]
response = client.batch.send(emails)
return responsepython
def send_batch_emails(recipients):
emails = [
{
"from": "newsletter@example.com",
"to": recipient["email"],
"subject": f"Hello {recipient['name']}",
"html": f"<p>Welcome {recipient['name']}</p>",
}
for recipient in recipients
]
response = client.batch.send(emails)
return responseFile Attachment (Python)
文件附件(Python)
python
def send_with_attachment(file_path):
with open(file_path, 'rb') as f:
file_content = f.read()
email = {
"from": "documents@example.com",
"to": "recipient@example.com",
"subject": "Your Document",
"html": "<p>Document attached.</p>",
"attachments": [
{
"filename": "document.pdf",
"content": file_content,
}
],
}
response = client.emails.send(email)
return responsepython
def send_with_attachment(file_path):
with open(file_path, 'rb') as f:
file_content = f.read()
email = {
"from": "documents@example.com",
"to": "recipient@example.com",
"subject": "Your Document",
"html": "<p>Document attached.</p>",
"attachments": [
{
"filename": "document.pdf",
"content": file_content,
}
],
}
response = client.emails.send(email)
return responseTemplate Variables
模板变量
Environment Variables Required
所需环境变量
bash
RESEND_API_KEY=your_resend_key_here
RESEND_FROM_EMAIL=your-verified-email@example.combash
RESEND_API_KEY=your_resend_key_here
RESEND_FROM_EMAIL=your-verified-email@example.comEmail Template Variables
邮件模板变量
typescript
interface EmailPayload {
from: string; // Verified sender email
to: string | string[]; // Recipient(s)
cc?: string[]; // Carbon copy recipients
bcc?: string[]; // Blind carbon copy
reply_to?: string; // Reply-to address
subject: string; // Email subject
html?: string; // HTML content
text?: string; // Plain text fallback
attachments?: Array<{
filename: string;
content: Buffer | string;
}>;
scheduled_at?: string; // ISO 8601 datetime for scheduling
tags?: Array<{
name: string;
value: string;
}>;
}typescript
interface EmailPayload {
from: string; // Verified sender email
to: string | string[]; // Recipient(s)
cc?: string[]; // Carbon copy recipients
bcc?: string[]; // Blind carbon copy
reply_to?: string; // Reply-to address
subject: string; // Email subject
html?: string; // HTML content
text?: string; // Plain text fallback
attachments?: Array<{
filename: string;
content: Buffer | string;
}>;
scheduled_at?: string; // ISO 8601 datetime for scheduling
tags?: Array<{
name: string;
value: string;
}>;
}Best Practices
最佳实践
Error Handling
错误处理
Always implement retry logic for transient failures:
typescript
async function sendWithRetry(emailPayload, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const { data, error } = await resend.emails.send(emailPayload);
if (!error) return { data, success: true };
if (error.message?.includes('rate_limit') && attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
return { error, success: false };
}
}始终为临时故障实现重试逻辑:
typescript
async function sendWithRetry(emailPayload, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const { data, error } = await resend.emails.send(emailPayload);
if (!error) return { data, success: true };
if (error.message?.includes('rate_limit') && attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
return { error, success: false };
}
}Rate Limiting
速率限制
Resend has rate limits. For batch operations over 100 emails:
typescript
async function sendLargeBatch(emails: EmailPayload[]) {
const batchSize = 100;
const results = [];
for (let i = 0; i < emails.length; i += batchSize) {
const batch = emails.slice(i, i + batchSize);
const { data, error } = await resend.batch.send(batch);
if (error) {
console.error(`Batch ${Math.floor(i / batchSize) + 1} failed:`, error);
results.push({ success: false, error });
} else {
results.push({ success: true, data });
}
// Rate limit handling - wait between batches
if (i + batchSize < emails.length) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
return results;
}Resend存在速率限制。对于超过100封邮件的批量操作:
typescript
async function sendLargeBatch(emails: EmailPayload[]) {
const batchSize = 100;
const results = [];
for (let i = 0; i < emails.length; i += batchSize) {
const batch = emails.slice(i, i + batchSize);
const { data, error } = await resend.batch.send(batch);
if (error) {
console.error(`Batch ${Math.floor(i / batchSize) + 1} failed:`, error);
results.push({ success: false, error });
} else {
results.push({ success: true, data });
}
// Rate limit handling - wait between batches
if (i + batchSize < emails.length) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
return results;
}Template Best Practices
模板最佳实践
- Use responsive HTML templates
- Always provide text fallback
- Test across email clients
- Include unsubscribe links for marketing emails
- Avoid large attachments (keep under 25MB)
- 使用响应式HTML模板
- 始终提供纯文本备选内容
- 在多邮件客户端中进行测试
- 营销邮件中包含退订链接
- 避免过大附件(保持在25MB以下)
Examples Directory Structure
示例目录结构
- - Basic transactional email patterns
single-email/ - - Bulk sending with 50-100 recipients
batch-emails/ - - File, buffer, and URL attachment handling
attachments/ - - Time-based delivery scheduling
scheduled/
See individual example README files for complete code and usage patterns.
- - 基础事务性邮件模式
single-email/ - - 支持50-100个收件人的批量发送
batch-emails/ - - 文件、缓冲区与URL附件处理
attachments/ - - 基于时间的投递调度
scheduled/
查看各示例目录下的README文件获取完整代码与使用模式。
Related Skills
相关技能
- email-templates - HTML template management and rendering
- email-validation - Recipient address validation
- email-webhooks - Delivery event tracking and bounce handling
- email-templates - HTML模板管理与渲染
- email-validation - 收件人地址验证
- email-webhooks - 投递事件追踪与退信处理
Resources
资源
Security Notes
安全注意事项
- API keys should be stored in environment variables (never hardcoded)
- Use from secure secret management
RESEND_API_KEY - Verify sender emails before using in production
- Implement authentication for email submission endpoints
- Log email events for compliance and debugging
- API密钥应存储在环境变量中(切勿硬编码)
- 从安全的密钥管理系统获取
RESEND_API_KEY - 生产环境使用前验证发件人邮箱
- 为邮件提交端点实现认证机制
- 记录邮件事件以满足合规性与调试需求