Skip to content

Build a Pluggable Email Service with NodeMailer + TSX Templates + Auto-Fallback #19

@abhishek-nexgen-dev

Description

@abhishek-nexgen-dev

🧩 Description

Create a pluggable, fully reusable Email Service module using NodeMailer and React TSX-based templates inside:

  • src/features/Email/v1/

This module should:

  • Work in any Express/Node/TypeScript backend

  • Support .tsx email templates for styled HTML

  • Allow developers to pass custom JSX components in every method (OTP, Reminder, Custom)

  • Automatically fall back to a default email layout if no component is provided

  • Be highly configurable via .env

  • Be easily publishable to npm as a standalone package

🧱 Why This Is Important

Problem Solution

  • Sending styled HTML emails is tedious Use .tsx JSX components to design them Developers forget templates Provide default fallback templates
    Hard to reuse logic across projects Build this module as a reusable service

📁 Folder Structure


src/
└── features/
    └── Email/
        └── v1/
            ├── Email.service.ts
            ├── Email.utils.ts
            ├── Email.constant.ts
            ├── Email.types.ts
            ├── Email.demo.ts
            ├── Email.validator.ts
            ├── renderEmail.ts
            └── templates/
                ├── OtpEmail.tsx
                ├── ReminderEmail.tsx
                └── DefaultEmail.tsx

✅ Tasks

1. Email.service.ts

  • Class-based implementation

Functions:

  • sendOtpEmail({ to, otp, component })

  • sendReminderEmail({ to, task, dueDate, component })

  • sendCustomEmail({ to, subject, component, fallbackHeading, fallbackMessage })

  • Use renderEmail() to convert JSX into HTML

  • Use .env to load EMAIL_USER, EMAIL_PASS, EMAIL_FROM

2. templates/*.tsx

  • Each email template is a self-contained React component:
export const OtpEmail = ({ otp }: { otp: string }) => (
  <div><h1>Your OTP: {otp}</h1></div>
);

3. Fallback Template

export const DefaultEmail = ({
heading = 'Notification',
message = 'This is an automated message.',
}: {
heading?: string;
message?: string;
}) => (

{heading}

{message}

);

4. renderEmail.ts

import React from 'react';
import ReactDOMServer from 'react-dom/server';
export const renderEmail = (component: React.ReactElement) =>
  ReactDOMServer.renderToStaticMarkup(component);

5. Email.utils.ts

export const isValidEmail = (email: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
  1. Email.demo.ts

await EmailService.sendOtpEmail({
to: 'test@example.com',
otp: '123456',
component: , // custom JSX
});

await EmailService.sendCustomEmail({
to: 'admin@example.com',
subject: 'System Alert',
fallbackHeading: 'Warning',
fallbackMessage: 'Something important happened.',
});


📘 Example Usage

import { EmailService } from '@/features/Email/v1/Email.service';
import { MyOtp } from './custom/OtpEmail';

await EmailService.sendOtpEmail({
to: 'user@example.com',
otp: '889900',
component:
});

If you don’t pass a component, a default layout will be used automatically:

await EmailService.sendCustomEmail({
to: 'admin@example.com',
subject: '🚨 Alert',
fallbackHeading: 'Check Dashboard',
fallbackMessage: 'We detected unusual activity.',
});


.env

EMAIL_USER=your@email.com
EMAIL_PASS=yourpassword
EMAIL_FROM=YourApp <no-reply@yourapp.com>

Feature ✅

  • Fully reusable & typed ✅
  • TSX templates + fallback ✅
  • Works in any project ✅
  • Developer-customizable ✅
  • Email preview logic optional ✅

💡 Future Features (Optional)

  • Email preview in browser

  • Queue support (BullMQ, RabbitMQ)

  • Dark/light theme template variants

  • MJML support

🙋 Looking For

  • Contributors to build more templates (Welcome, Password Reset, Invoice)

  • Ideas to support attachments or logs

  • Suggestions to turn this into a plug-n-play npm package

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions