Use Cases

How to Efficiently Implement Email Sending with Claude Code

Learn how to efficiently implement email sending using Claude Code. Includes practical code examples and step-by-step guidance.

Why Use Claude Code for Email Features

Email features involve many concerns: template authoring, send logic, error handling, and retry logic. Claude Code can implement all of these in one pass and suggest a testable structure.

Basic Email Sending With Resend

> Create an email sending service using Resend.
> Manage templates with React Email.
> Also implement retries and error handling.
// src/services/email-service.ts
import { Resend } from 'resend';

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

interface SendEmailOptions {
  to: string | string[];
  subject: string;
  html: string;
  text?: string;
  replyTo?: string;
}

export class EmailService {
  private maxRetries = 3;

  async send(options: SendEmailOptions): Promise<{ id: string }> {
    let lastError: Error | null = null;

    for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
      try {
        const { data, error } = await resend.emails.send({
          from: 'MyApp <noreply@example.com>',
          to: options.to,
          subject: options.subject,
          html: options.html,
          text: options.text,
          replyTo: options.replyTo,
        });

        if (error) throw new Error(error.message);
        return { id: data!.id };
      } catch (err) {
        lastError = err as Error;
        if (attempt < this.maxRetries) {
          await this.delay(1000 * attempt); // Exponential backoff
        }
      }
    }

    throw new Error(`Failed after ${this.maxRetries} attempts: ${lastError?.message}`);
  }

  private delay(ms: number) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

Authoring Templates With React Email

// emails/welcome.tsx
import {
  Body,
  Container,
  Head,
  Heading,
  Html,
  Link,
  Preview,
  Section,
  Text,
} from '@react-email/components';

interface WelcomeEmailProps {
  userName: string;
  loginUrl: string;
}

export function WelcomeEmail({ userName, loginUrl }: WelcomeEmailProps) {
  return (
    <Html>
      <Head />
      <Preview>Welcome, {userName}!</Preview>
      <Body style={{ backgroundColor: '#f6f9fc', fontFamily: 'sans-serif' }}>
        <Container style={{ margin: '0 auto', padding: '40px 20px', maxWidth: '560px' }}>
          <Heading style={{ fontSize: '24px', color: '#333' }}>
            Welcome, {userName}!
          </Heading>
          <Text style={{ fontSize: '16px', color: '#555', lineHeight: '1.6' }}>
            Your account has been created successfully. Use the link below to log in and start using the service.
          </Text>
          <Section style={{ textAlign: 'center', margin: '32px 0' }}>
            <Link
              href={loginUrl}
              style={{
                backgroundColor: '#2563eb',
                color: '#fff',
                padding: '12px 24px',
                borderRadius: '6px',
                textDecoration: 'none',
                fontSize: '16px',
              }}
            >
              Log in
            </Link>
          </Section>
          <Text style={{ fontSize: '14px', color: '#888' }}>
            If you have any questions, feel free to reach out.
          </Text>
        </Container>
      </Body>
    </Html>
  );
}

Integrating Email Sending

// src/services/notification-service.ts
import { render } from '@react-email/render';
import { EmailService } from './email-service';
import { WelcomeEmail } from '../emails/welcome';

const emailService = new EmailService();

export class NotificationService {
  async sendWelcomeEmail(user: { email: string; name: string }) {
    const html = await render(
      WelcomeEmail({
        userName: user.name,
        loginUrl: `${process.env.APP_URL}/login`,
      })
    );

    return emailService.send({
      to: user.email,
      subject: `Welcome, ${user.name}!`,
      html,
    });
  }

  async sendPasswordReset(email: string, token: string) {
    const resetUrl = `${process.env.APP_URL}/reset-password?token=${token}`;
    const html = await render(
      PasswordResetEmail({ resetUrl })
    );

    return emailService.send({
      to: email,
      subject: 'Password reset instructions',
      html,
    });
  }
}

Implementing an Email Queue

For bulk email, use a queue.

// src/queues/email-queue.ts
import { Queue, Worker } from 'bullmq';
import { EmailService } from '../services/email-service';

const emailQueue = new Queue('emails', {
  connection: { host: 'localhost', port: 6379 },
});

// Add an email to the queue
export async function enqueueEmail(options: {
  to: string;
  subject: string;
  html: string;
}) {
  await emailQueue.add('send-email', options, {
    attempts: 3,
    backoff: { type: 'exponential', delay: 2000 },
    removeOnComplete: 100,
    removeOnFail: 50,
  });
}

// Process with a worker
const emailService = new EmailService();

new Worker('emails', async (job) => {
  await emailService.send(job.data);
  console.log(`Email sent: ${job.data.to}`);
}, {
  connection: { host: 'localhost', port: 6379 },
  concurrency: 5,
});

Writing Tests

import { vi, describe, it, expect } from 'vitest';
import { NotificationService } from './notification-service';

vi.mock('resend', () => ({
  Resend: vi.fn().mockImplementation(() => ({
    emails: {
      send: vi.fn().mockResolvedValue({ data: { id: 'test-id' }, error: null }),
    },
  })),
}));

describe('NotificationService', () => {
  it('should send welcome email', async () => {
    const service = new NotificationService();
    const result = await service.sendWelcomeEmail({
      email: 'test@example.com',
      name: 'Test User',
    });
    expect(result.id).toBe('test-id');
  });
});

Summary

With Claude Code, you can implement email features end-to-end, from template management to queue processing. React Email template authoring is especially well-suited to Claude Code. Writing your email feature design policies in CLAUDE.md helps keep the implementation consistent. For tips on test-driven development, see the automating refactoring article.

For Claude Code details, see the official Anthropic documentation. For React Email, see the official React Email site.

#Claude Code #email #SendGrid #Resend #Node.js

Level up your Claude Code workflow

50 battle-tested prompt templates you can copy-paste into Claude Code right now.

Free

Free PDF: Claude Code Cheatsheet in 5 Minutes

Key commands, shortcuts, and prompt examples on a single printable page.

Download PDF
M

About the Author

Masa

Engineer obsessed with Claude Code. Runs claudecode-lab.com, a 10-language tech media with 2,000+ pages.