Skip to Content
ServicesEmail Service

Email Service

Reliable email delivery service using Resend with React Email templates. Send transactional and marketing emails with beautiful, responsive templates.


Installation & Setup

1. Install Dependencies

pnpm add resend react-email @react-email/components

2. Configure Environment Variables

# .env RESEND_API_KEY=re_xxxxxxxxxxxx EMAIL_FROM=hello@orbitus.dev

3. Usage

The Email Service is available as a singleton via getEmailService or can be instantiated manually.

import { getEmailService } from '@orbitusdev/core/services/email'; const emailService = getEmailService();

Manual Instantiation

For advanced use cases (e.g., custom configuration):

import { EmailService } from '@orbitusdev/core/services/email'; // Provider config is typically handled within the service or passed explicitly const emailService = new EmailService('resend', { apiKey: process.env.RESEND_API_KEY });

Email Templates

Welcome Email

// emails/welcome.tsx import { Body, Button, Container, Head, Heading, Html, Preview, Section, Text } from '@react-email/components'; interface WelcomeEmailProps { username: string; loginUrl: string; } export function WelcomeEmail({ username, loginUrl }: WelcomeEmailProps) { return ( <Html> <Head /> <Preview>Welcome to Orbitus - Let's get started!</Preview> <Body style={main}> <Container style={container}> <Heading style={h1}>Welcome to Orbitus! 🎉</Heading> <Text style={text}>Hi {username},</Text> <Text style={text}> We're excited to have you on board. Your account has been successfully created. </Text> <Section style={buttonContainer}> <Button style={button} href={loginUrl}> Get Started </Button> </Section> <Text style={text}> If you have any questions, feel free to reply to this email. </Text> <Text style={footer}> Best regards, <br /> The Orbitus Team </Text> </Container> </Body> </Html> ); } const main = { backgroundColor: '#f6f9fc', fontFamily: '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif' }; const container = { backgroundColor: '#ffffff', margin: '0 auto', padding: '20px 0 48px', marginBottom: '64px' }; const h1 = { color: '#333', fontSize: '24px', fontWeight: 'bold', margin: '40px 0', padding: '0' }; const text = { color: '#333', fontSize: '16px', lineHeight: '26px' }; const buttonContainer = { padding: '27px 0 27px' }; const button = { backgroundColor: '#000', borderRadius: '5px', color: '#fff', fontSize: '16px', fontWeight: 'bold', textDecoration: 'none', textAlign: 'center' as const, display: 'block', width: '200px', padding: '14px 7px' }; const footer = { color: '#8898aa', fontSize: '14px', lineHeight: '16px', marginTop: '32px' };

Email Verification

// emails/verify-email.tsx import { Body, Button, Container, Head, Heading, Html, Preview, Section, Text } from '@react-email/components'; interface VerifyEmailProps { username: string; verificationUrl: string; verificationCode: string; } export function VerifyEmail({ username, verificationUrl, verificationCode }: VerifyEmailProps) { return ( <Html> <Head /> <Preview>Verify your email address</Preview> <Body style={main}> <Container style={container}> <Heading style={h1}>Verify your email</Heading> <Text style={text}>Hi {username},</Text> <Text style={text}> Please verify your email address by clicking the button below: </Text> <Section style={buttonContainer}> <Button style={button} href={verificationUrl}> Verify Email </Button> </Section> <Text style={text}>Or use this verification code:</Text> <Section style={codeContainer}> <Text style={code}>{verificationCode}</Text> </Section> <Text style={text}> This link will expire in 24 hours. If you didn't request this, please ignore this email. </Text> </Container> </Body> </Html> ); } const codeContainer = { background: '#f4f4f4', borderRadius: '4px', margin: '16px auto 14px', verticalAlign: 'middle', width: '280px' }; const code = { color: '#000', display: 'inline-block', fontFamily: 'monospace', fontSize: '32px', fontWeight: 700, letterSpacing: '6px', lineHeight: '40px', paddingBottom: '8px', paddingTop: '8px', margin: '0 auto', width: '100%', textAlign: 'center' as const }; // ... (same styles as WelcomeEmail)

Password Reset

// emails/reset-password.tsx import { Body, Button, Container, Head, Heading, Html, Preview, Section, Text } from '@react-email/components'; interface ResetPasswordProps { username: string; resetUrl: string; } export function ResetPassword({ username, resetUrl }: ResetPasswordProps) { return ( <Html> <Head /> <Preview>Reset your password</Preview> <Body style={main}> <Container style={container}> <Heading style={h1}>Reset your password</Heading> <Text style={text}>Hi {username},</Text> <Text style={text}> We received a request to reset your password. Click the button below to create a new password: </Text> <Section style={buttonContainer}> <Button style={button} href={resetUrl}> Reset Password </Button> </Section> <Text style={text}> This link will expire in 1 hour. If you didn't request a password reset, please ignore this email. </Text> <Text style={text}> For security reasons, we cannot reset your password automatically. </Text> </Container> </Body> </Html> ); } // ... (same styles)

Usage Examples

Send Welcome Email

import { getEmailService } from '@orbitusdev/core/services/email'; import { WelcomeEmail } from '@/emails/welcome'; export async function sendWelcomeEmail(user: { email: string; name: string }) { const emailService = getEmailService(); await emailService.sendEmail({ to: user.email, subject: 'Welcome to Orbitus! 🎉', html: '', // React templates usually render to HTML, but here we pass react component if supported or render it first // Note: The current EmailService expects 'html' or 'text'. // If using React Email, render it to HTML string first: // html: render(<WelcomeEmail ... />) // For this example, assuming we render it: react: WelcomeEmail({ username: user.name, loginUrl: 'https://orbitus.dev/login' }) }); }

Send Verification Email

import { getEmailService } from '@orbitusdev/core/services/email'; import { VerifyEmail } from '@/emails/verify-email'; export async function sendVerificationEmail(user: { email: string; name: string; verificationToken: string; }) { const emailService = getEmailService(); const verificationUrl = `https://orbitus.dev/verify?token=${user.verificationToken}`; await emailService.sendEmail({ to: user.email, subject: 'Verify your email address', react: VerifyEmail({ username: user.name, verificationUrl, verificationCode: user.verificationToken.slice(0, 6).toUpperCase() }) }); }

Send Password Reset Email

import { getEmailService } from '@orbitusdev/core/services/email'; import { ResetPassword } from '@/emails/reset-password'; export async function sendPasswordResetEmail(user: { email: string; name: string; resetToken: string; }) { const emailService = getEmailService(); const resetUrl = `https://orbitus.dev/reset-password?token=${user.resetToken}`; await emailService.sendEmail({ to: user.email, subject: 'Reset your password', react: ResetPassword({ username: user.name, resetUrl }) }); }

Server Actions

Complete Auth Flow

'use server'; import { sendWelcomeEmail, sendVerificationEmail } from '@/lib/email'; export async function registerUser(formData: FormData) { const email = formData.get('email') as string; const name = formData.get('name') as string; // Create user const user = await prisma.user.create({ data: { email, name, verificationToken: generateToken() } }); // Send welcome and verification emails await Promise.all([ sendWelcomeEmail(user), sendVerificationEmail(user) ]); return { success: true }; }

Newsletter Templates

Newsletter Email

// emails/newsletter.tsx import { Body, Container, Head, Heading, Html, Img, Link, Preview, Section, Text } from '@react-email/components'; interface NewsletterProps { articles: Array<{ title: string; excerpt: string; url: string; image: string; }>; } export function Newsletter({ articles }: NewsletterProps) { return ( <Html> <Head /> <Preview>Latest updates from Orbitus</Preview> <Body style={main}> <Container style={container}> <Heading style={h1}>📰 Latest from Orbitus</Heading> {articles.map((article) => ( <Section key={article.url} style={articleSection}> <Img src={article.image} alt={article.title} style={image} /> <Heading style={h2}>{article.title}</Heading> <Text style={text}>{article.excerpt}</Text> <Link href={article.url} style={link}> Read more → </Link> </Section> ))} <Text style={footer}> You're receiving this because you subscribed to Orbitus newsletter. <br /> <Link href="https://orbitus.dev/unsubscribe">Unsubscribe</Link> </Text> </Container> </Body> </Html> ); } const articleSection = { marginBottom: '32px', paddingBottom: '32px', borderBottom: '1px solid #e5e5e5' }; const image = { width: '100%', borderRadius: '8px', marginBottom: '16px' }; const h2 = { fontSize: '20px', lineHeight: '28px', fontWeight: 'bold', margin: '16px 0' }; const link = { color: '#000', fontSize: '16px', fontWeight: 'bold' }; // ... (same base styles)

Best Practices

  1. Use environment variables - Never hardcode API keys
  2. Validate email addresses - Check format before sending
  3. Handle errors gracefully - Log failures, retry if needed
  4. Use preview text - Shows in email client preview
  5. Responsive design - Test on mobile and desktop
  6. Plain text fallback - Include text version
  7. Unsubscribe links - Required for marketing emails
  8. Rate limiting - Prevent spam, respect Resend limits
  9. Test templates - Use React Email preview mode
  10. Track deliverability - Monitor bounce and spam rates

Testing

Preview Emails Locally

# Start React Email dev server pnpm email dev

Visit http://localhost:3000 to preview all templates.

Send Test Email

import { getEmailService } from '@orbitusdev/core/services/email'; import { WelcomeEmail } from '@/emails/welcome'; const emailService = getEmailService(); await emailService.sendEmail({ to: 'test@example.com', subject: 'Test Email', react: WelcomeEmail({ username: 'Test User', loginUrl: 'https://orbitus.dev/login' }) });

Error Handling

import { getEmailService } from '@orbitusdev/core/services/email'; import { logger } from '@orbitusdev/core/services/logger'; export async function sendEmailSafe(params: SendEmailParams) { const emailService = getEmailService(); try { const result = await emailService.sendEmail(params); logger.info('Email sent successfully', { to: params.to, subject: params.subject }); return { success: true, data: result }; } catch (error) { logger.error('Failed to send email', error, { to: params.to }); return { success: false, error: error.message }; } }

Last updated on