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
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions