Email delivery patterns including single, batch, scheduled emails and attachment handling. Use when building transactional email systems, batch communication workflows, scheduled delivery, or implementing file/URL attachments with reply-to and CC/BCC functionality.
Limited to specific tools
Additional assets for this skill
This skill is limited to using the following tools:
examples/attachments/README.mdexamples/batch-emails/README.mdexamples/scheduled/README.mdexamples/single-email/README.mdscripts/generate-html-template.shscripts/validate-attachment.shscripts/validate-email.shtemplates/attachment-email-template.tstemplates/batch-email-template.tstemplates/scheduled-email-template.tstemplates/single-email-template.tsComprehensive patterns and templates for implementing robust email delivery with Resend, covering single emails, batch operations, scheduled delivery, and attachment handling.
Transactional emails for immediate delivery with minimal latency:
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;
}
Bulk operations for sending up to 100 emails in a single request:
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;
}
Time-based delivery for emails sent at specific times:
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;
}
File attachments from files, buffers, or URLs:
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 };
}
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 };
}
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 };
}
Message routing with multiple recipients and reply addresses:
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 };
}
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 response
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 response
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 response
RESEND_API_KEY=your_resend_key_here
RESEND_FROM_EMAIL=your-verified-email@example.com
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;
}>;
}
Always implement retry logic for transient failures:
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 };
}
}
Resend has rate limits. For batch operations over 100 emails:
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;
}
single-email/ - Basic transactional email patternsbatch-emails/ - Bulk sending with 50-100 recipientsattachments/ - File, buffer, and URL attachment handlingscheduled/ - Time-based delivery schedulingSee individual example README files for complete code and usage patterns.
RESEND_API_KEY from secure secret management