Email Service

The Email Service component provides a production-ready solution for sending emails in Servercn using nodemailer. It supports multiple email providers including Gmail, SMTP servers, SendGrid, and more.

Features

  • Multiple email providers - Gmail, SMTP, SendGrid, AWS SES, and more
  • HTML and plain text emails - Support for both HTML and text content
  • Attachments - Send files as email attachments
  • Multiple recipients - Support for CC, BCC, and multiple recipients
  • Type-safe - Full TypeScript support
  • Error handling - Comprehensive error handling and validation
  • Email verification - Verify email configuration before sending

Installation Guide

Install this component using the following command:

npx servercn-cli add email-service

Prerequisites

  1. Enable 2-Step Verification on your Google Account
  2. Generate an App Password:
    • Go to Google Account → Security → 2-Step Verification → App passwords
    • Create a new app password for "Mail"
    • Copy the generated password

Add the following to your .env file:

SMTP Server

SMTP_HOST='smtp.gmail.com'
SMTP_PORT='465'
SMTP_USER=''
SMTP_PASS=''
EMAIL_FROM=""

Resend

RESEND_API_KEY="your-resend-api-key"

Basic Implementation

1. Add nodemailer configuration

MVC Path: src/configs/nodemailer.ts

Feature Path: src/shared/configs/nodemailer.ts

import nodemailer from "nodemailer";
import env from "./env";
 
let transporter: nodemailer.Transporter | null = null;
 
export function getTransporter() {
  if (transporter) return transporter;
  const host = env.SMTP_HOST;
  const port = Number(env.SMTP_PORT || 465);
  const user = env.SMTP_USER;
  const pass = env.SMTP_PASS;
  const from = env.EMAIL_FROM;
  if (!host || !user || !pass || !from) {
    throw new Error("SMTP/EMAIL env not configured");
  }
 
  transporter = nodemailer.createTransport({
    host,
    port,
    secure: port === 465,
    auth: { user, pass }
  });
  return transporter;
}

2. Send Email Function

MVC Path: src/utils/send-mail.ts

Feature Path: src/shared/utils/send-mail.ts

import env from "../configs/env";
import { getTransporter } from "../configs/nodemailer";
import { ApiError } from "./api-error";
 
type sendMail = {
  from?: string;
  subject: string;
  data: Record<string, any>;
  email: string;
  html: string;
};
 
export async function sendEmail({
  from,
  email,
  subject,
  html
}: sendMail) {
  const transporter = getTransporter();
 
  return transporter
    .sendMail({
      from: from || `<${env.EMAIL_FROM}>`,
      to: email,
      subject,
      html
    })
    .catch(() => {
      throw ApiError.badRequest("Failed to send email");
    });
}

1. Resend configuration

MVC Path: src/configs/resend.ts

Feature Path: src/shared/configs/resend.ts

import { Resend } from "resend";
import env from "./env";
 
export const resend = new Resend(env.RESEND_API_KEY);

2. Send Email Function

MVC Path: src/utils/send-mail.ts

Feature Path: src/shared/utils/send-mail.ts

import env from "../configs/env";
import { resend } from "../configs/resend";
import { ApiError } from "./api-error";
 
type sendMail = {
  from?: string;
  subject: string;
  data: Record<string, any>;
  email: string;
  html: string;
};
 
export async function sendEmail({
  from,
  email,
  subject,
  html
}: sendMail) {
 
  return await resend.emails.send({
      from: from || `<${env.EMAIL_FROM}>`,
      to: email,
      subject,
      replyTo: email,
      html
    });
}

Usage Examples

import { sendEmail } from "../utils/send-mail";
 
const html = `
  <h1>Welcome to Servercn</h1>
  <p>Thank you for joining us!</p>
`;
 
await sendEmail({
  email: "john.doe@example.com",
  subject: "Welcome to Servercn",
  html
});
import { sendEmail } from "../utils/send-mail";
const html = `
  <h1>Reset Your Password</h1>
  <p>Click <a href="https://example.com/reset">here</a> to reset your password.</p>
`;
 
await sendEmail({
  email: "john.doe@example.com",
  subject: "Reset Your Password",
  html,
  from: "Servercn <servercn@example.com>"
});

Best Practices

  1. Use environment variables - Never hardcode email credentials
  2. Validate email addresses - Validate recipient emails before sending
  3. Handle errors gracefully - Implement proper error handling and logging
  4. Use HTML templates - Use template engines for consistent email design
  5. Rate limiting - Implement rate limiting for email endpoints
  6. Email queuing - Use job queues (Bull, BullMQ) for bulk emails
  7. Test emails - Use services like Mailtrap for testing in development

Security Considerations

  1. App Passwords - Use app-specific passwords for Gmail
  2. Environment Variables - Store credentials securely
  3. Rate Limiting - Prevent email spam and abuse
  4. Input Validation - Validate email addresses and content
  5. HTTPS - Use secure connections (EMAIL_SECURE=true for port 465)

File & Folder Structure

ServerCN

Select a file to view its contents

Installation

npx servercn-cli add email-service