Features
Docs
CLI
Benchmarks
Examples

© 2024 MoroJs

Email System

Production-ready email support with multiple adapters (Nodemailer, SendGrid, AWS SES, Resend). Template rendering, queue integration, and zero forced dependencies.

Email That Just Works

Send emails with any provider.
Nodemailer, SendGrid, AWS SES, or Resend. Same API. Templates included.

It's This Simple

Send emails with one call

typescript

1import { createApp } from '@morojs/moro';
2
3const app = createApp();
4
5// Configure email
6app.mailInit({
7  adapter: 'nodemailer',
8  from: { name: 'My App', email: 'noreply@myapp.com' },
9  connection: {
10    host: 'smtp.gmail.com',
11    port: 587,
12    auth: {
13      user: process.env.EMAIL_USER,
14      pass: process.env.EMAIL_PASSWORD
15    }
16  }
17});
18
19// Send email
20await app.sendMail({
21  to: 'user@example.com',
22  subject: 'Welcome',
23  template: 'welcome',
24  data: { name: 'John' }
25});

Why Email Integration Matters

Without proper email systems, you're manually integrating different providers, managing templates, and handling async sending. With MoroJS, you get all of that automatically.

Traditional email setup requires different libraries and APIs for each provider. We give you one consistent API.

Without Email System

  • Different APIs for each provider
  • Manual template management
  • No built-in queue integration
  • Complex provider switching

With MoroJS

  • Same API across all providers
  • Built-in template rendering
  • Automatic queue integration
  • Easy provider switching

It's This Easy

Use the same API regardless of which provider you choose.

Same API, different providers

typescript

1// Nodemailer (SMTP)
2app.mailInit({ adapter: 'nodemailer', ... });
3
4// SendGrid
5app.mailInit({ adapter: 'sendgrid', ... });
6
7// AWS SES
8app.mailInit({ adapter: 'ses', ... });
9
10// Resend
11app.mailInit({ adapter: 'resend', ... });
12
13// All use the same API
14await app.sendMail({
15  to: 'user@example.com',
16  subject: 'Welcome',
17  template: 'welcome',
18  data: { name: 'John' }
19});

Why It Makes Sense

Flexible

Choose Nodemailer, SendGrid, SES, or Resend. Same API.

Templates

Built-in template rendering with Moro, Handlebars, or EJS.

Queue Ready

Automatic queue integration for async sending.

How It Works

MoroJS provides a unified email API that works with multiple providers. You configure your chosen adapter, send emails with templates, and optionally integrate with queues for async sending. The system handles provider-specific details automatically.

Quick Start

Installation

typescript

1# Install the adapter you need (all optional)
2npm install nodemailer          # For SMTP
3npm install @sendgrid/mail      # For SendGrid
4npm install @aws-sdk/client-ses # For AWS SES
5npm install resend              # For Resend

Basic Configuration

typescript

1import { createApp } from '@morojs/moro';
2
3const app = createApp();
4
5// Configure email - synchronous, no await needed!
6app.mailInit({
7  adapter: 'nodemailer',
8  from: {
9    name: 'My App',
10    email: 'noreply@myapp.com'
11  },
12  connection: {
13    host: 'smtp.gmail.com',
14    port: 587,
15    secure: false,
16    auth: {
17      user: process.env.EMAIL_USER,
18      pass: process.env.EMAIL_PASSWORD
19    }
20  },
21  templates: {
22    path: './emails',
23    engine: 'moro', // or 'handlebars', 'ejs'
24    cache: true
25  },
26  queue: {
27    enabled: true,
28    name: 'emails'
29  }
30});

Sending Emails

typescript

1// Simple email
2await app.sendMail({
3  to: 'user@example.com',
4  subject: 'Welcome',
5  text: 'Welcome to our app!',
6  html: '<h1>Welcome to our app!</h1>'
7});
8
9// With template
10await app.sendMail({
11  to: 'user@example.com',
12  subject: 'Password Reset',
13  template: 'password-reset',
14  data: {
15    name: 'John',
16    resetUrl: 'https://myapp.com/reset/token123'
17  }
18});
19
20// With attachments
21await app.sendMail({
22  to: 'user@example.com',
23  subject: 'Invoice',
24  template: 'invoice',
25  data: { invoice },
26  attachments: [
27    {
28      filename: 'invoice.pdf',
29      content: pdfBuffer
30    }
31  ]
32});
33
34// Batch emails
35await app.sendBulkMail([
36  { to: 'user1@example.com', subject: 'Hello', text: 'Hi!' },
37  { to: 'user2@example.com', subject: 'Hello', text: 'Hi!' }
38]);

Template System

Template Example

typescript

1// emails/welcome.html
2<!DOCTYPE html>
3<html>
4<head>
5  <style>
6    body { font-family: Arial, sans-serif; }
7    .button { background: #007bff; color: white; padding: 10px 20px; }
8  </style>
9</head>
10<body>
11  <h1>Welcome {{name}}!</h1>
12  <p>Thanks for joining {{appName}}. We're excited to have you.</p>
13
14  {{#if verifyUrl}}
15    <a href="{{verifyUrl}}" class="button">Verify Your Email</a>
16  {{/if}}
17
18  <p>Best regards,<br>The {{appName}} Team</p>
19</body>
20</html>

Using Templates

typescript

1// Use template
2await app.sendMail({
3  to: user.email,
4  template: 'welcome',
5  data: {
6    name: user.name,
7    appName: 'My App',
8    isPremium: user.plan === 'premium',
9    verifyUrl: generateVerifyUrl(user)
10  }
11});

Email Adapters

Nodemailer (SMTP)

typescript

1app.mailInit({
2  adapter: 'nodemailer',
3  connection: {
4    host: 'smtp.gmail.com',
5    port: 587,
6    secure: false,
7    auth: {
8      user: process.env.EMAIL_USER,
9      pass: process.env.EMAIL_PASSWORD
10    }
11  }
12});
13
14// Works with any SMTP server
15// Gmail, Outlook, custom servers
16// OAuth2 authentication support

SendGrid

typescript

1app.mailInit({
2  adapter: 'sendgrid',
3  apiKey: process.env.SENDGRID_API_KEY,
4  from: {
5    name: 'My App',
6    email: 'noreply@myapp.com'
7  }
8});
9
10// Features:
11// - Template management in SendGrid
12// - Click/open tracking
13// - Suppression list management
14// - Webhook integration

AWS SES

typescript

1app.mailInit({
2  adapter: 'ses',
3  region: 'us-east-1',
4  credentials: {
5    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
6    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
7  }
8});
9
10// Features:
11// - Configuration sets
12// - Bounce/complaint handling
13// - Email verification
14// - High volume sending

Resend

typescript

1app.mailInit({
2  adapter: 'resend',
3  apiKey: process.env.RESEND_API_KEY,
4  from: {
5    name: 'My App',
6    email: 'noreply@myapp.com'
7  }
8});
9
10// Features:
11// - Modern REST API
12// - Simple authentication
13// - Domain verification
14// - Batch sending

Console Adapter (Testing)

typescript

1app.mailInit({
2  adapter: 'console',
3  // Logs emails to console for development/testing
4  // No external dependencies required
5});
6
7// Perfect for:
8// - Development
9// - Testing
10// - CI/CD pipelines

Use Cases

User Registration

typescript

1app.post('/register')
2  .body(RegisterSchema)
3  .handler(async (req, res) => {
4    const user = await createUser(req.body);
5
6    // Send welcome email (queued)
7    await app.sendMail({
8      to: user.email,
9      template: 'welcome',
10      data: {
11        name: user.name,
12        verifyUrl: generateVerifyUrl(user)
13      }
14    });
15
16    return { success: true };
17  });

Password Reset

typescript

1app.post('/forgot-password')
2  .body(z.object({ email: z.string().email() }))
3  .handler(async (req, res) => {
4    const user = await findUser(req.body.email);
5    const token = generateResetToken(user);
6
7    await app.sendMail({
8      to: user.email,
9      template: 'password-reset',
10      data: {
11        name: user.name,
12        resetUrl: `https://myapp.com/reset/${token}`,
13        expiresIn: '1 hour'
14      }
15    });
16
17    return { success: true };
18  });

Transactional Emails

typescript

1// Order confirmation
2await app.sendMail({
3  to: order.customerEmail,
4  template: 'order-confirmation',
5  data: {
6    orderNumber: order.id,
7    items: order.items,
8    total: order.total,
9    trackingUrl: order.trackingUrl
10  },
11  attachments: [
12    {
13      filename: 'invoice.pdf',
14      content: await generateInvoice(order)
15    }
16  ]
17});

Queue Integration

Async Email Sending

typescript

1// Configure email with queue
2app.mailInit({
3  adapter: 'sendgrid',
4  apiKey: process.env.SENDGRID_API_KEY,
5  queue: {
6    enabled: true,
7    name: 'emails'
8  }
9});
10
11// Configure queue
12app.queueInit('emails', {
13  adapter: 'bull',
14  connection: {
15    host: 'localhost',
16    port: 6379
17  },
18  concurrency: 10
19});
20
21// Emails are automatically queued
22await app.sendMail({
23  to: 'user@example.com',
24  template: 'welcome',
25  data: { name: 'John' }
26});
27
28// Returns immediately, email sent asynchronously

Features

Core Capabilities

  • Multiple provider support
  • Template rendering (Moro, Handlebars, EJS)
  • Attachment support
  • HTML and text emails
  • CC, BCC support
  • Queue integration for async sending

Supported Adapters

Nodemailer (Default)
SMTP, Gmail, custom mail servers
SendGrid
Templates, analytics, deliverability
AWS SES
High volume, cost-effective
Resend
Modern API, developer-friendly
Console (Built-in)
Development and testing

Next Steps