Email Templates with Handlebars
JifiJs uses Handlebars as its templating engine for creating beautiful, dynamic HTML emails. This guide shows you how to create, customize, and send professional email templates.
Template Structure
Directory Layout
templates/
├── layouts/
│ └── default.hbs # Base layout
├── emails/
│ ├── welcome.hbs # Welcome email
│ ├── password-reset.hbs # Password reset
│ └── verify-email.hbs # Email verification
└── ...
Creating Templates
Basic Template
Create templates/emails/welcome.hbs:
Using Layouts
JifiJs uses a layout system. Create a reusable layout in templates/layouts/default.hbs:
The {{{body}}} placeholder will be replaced with your template content.
Sending Emails with MailService
JifiJs provides a built-in MailService for sending emails.
Basic Email Sending
import mailService from './utils/bases/mail.service';
// Send email immediately
await mailService.send(
'user@example.com', // receivers
'Welcome to JifiJs', // subject
'emails/welcome', // template path
{ // template data
name: 'John Doe',
verificationLink: 'https://example.com/verify?token=abc123',
}
);
Sending with Queue
For better performance, use queue-based sending:
import mailService from './utils/bases/mail.service';
// Send email via queue (recommended for production)
await mailService.sendWithQueue(
'user@example.com',
'Welcome to JifiJs',
'emails/welcome',
{
name: 'John Doe',
verificationLink: 'https://example.com/verify?token=abc123',
}
);
Custom Sender
await mailService.send(
'user@example.com',
'Important Notification',
'emails/notification',
{ message: 'Your account has been updated' },
{
name: 'Support Team',
email: 'support@example.com',
}
);
Email with Attachments
await mailService.send(
'user@example.com',
'Your Invoice',
'emails/invoice',
{ invoiceNumber: 'INV-001' },
null, // use default sender
[ // attachments
{
filename: 'invoice.pdf',
path: '/path/to/invoice.pdf',
},
]
);
Plain Text Email
Send email without template (plain text):
await mailService.send(
'user@example.com',
'Test Email',
'This is a plain text email', // content (not a template path)
null // null = no template rendering
);
Template Data
Available Variables
JifiJs automatically provides these variables to all templates:
{
app_name: string; // From APP_NAME env variable
app_settings: { // Application configuration
name: string;
mode: string;
port: number;
url: string;
// ... other app settings
};
// ... your custom data
}
Example Usage
Handlebars Helpers
JifiJs registers custom Handlebars helpers for common tasks.
Date Formatting
Conditional Rendering
Loops
Email Configuration
Environment Variables
Configure email settings in .env:
Development Mode (APP_MODE=DEVELOPMENT)
Uses _DEV suffix variables:
MAIL_HOST_DEV=localhost
MAIL_PORT_DEV=1025
MAIL_SERVICE_DEV=gmail
MAIL_SENSER_NAME_DEV="Development Team"
MAIL_SENSER_EMAIL_DEV="dev@example.com"
MAIL_SECURE_DEV=false
MAIL_USER_DEV=false
MAIL_PASSWORD_DEV=false
Production Mode (APP_MODE=PRODUCTION)
Uses production variables:
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_SERVICE=gmail
MAIL_SENSER_NAME="Company Name"
MAIL_SENSER_EMAIL="noreply@example.com"
MAIL_SECURE=true
MAIL_USER=your-email@gmail.com
MAIL_PASSWORD=your-app-password
Template Path
TEMPLATE_PATH=templates
Responsive Email Design
Mobile-Friendly Template
Email-Safe CSS
Best Practices
Recommended:
- Use inline styles for maximum compatibility
- Use tables for layout instead of divs
- Use web-safe fonts (Arial, Helvetica, Times New Roman)
- Specify full hex colors (#000000 instead of #000)
- Use padding instead of margin
Avoid:
- Flexbox/grid layouts (poor email client support)
- Background images (often blocked)
- JavaScript (completely blocked)
- External CSS (often stripped)
- Video/audio elements (not supported)
Inline Styles Example
Testing Emails
Local Testing with MailHog
For development, use MailHog to catch all outgoing emails:
# Install MailHog
brew install mailhog # macOS
# or download from https://github.com/mailhog/MailHog
# Run MailHog
mailhog
# Configure .env for development
MAIL_HOST_DEV=localhost
MAIL_PORT_DEV=1025
Access MailHog UI at http://localhost:8025
Testing Tools
- Mailtrap - https://mailtrap.io (catch-all SMTP for development)
- Litmus - https://litmus.com (test across email clients)
- Email on Acid - https://www.emailonacid.com (comprehensive testing)
Queue Management
Check Queue Status
const stats = await mailService.getQueueStats();
console.log(stats);
// {
// waiting: 10,
// active: 2,
// completed: 145,
// failed: 3,
// delayed: 5
// }
Get Failed Jobs
const failedJobs = await mailService.getFailedJobs();
console.log(failedJobs);
Retry Failed Jobs
// Retry specific job
await mailService.retryFailedJob('job-id');
// Retry all failed jobs
await mailService.retryAllFailedJobs();
Clean Old Jobs
// Clean completed jobs older than 24 hours
await mailService.cleanCompletedJobs(24 * 60 * 60 * 1000);
// Clean failed jobs older than 7 days
await mailService.cleanFailedJobs(7 * 24 * 60 * 60 * 1000);
Common Email Templates
Welcome Email
Password Reset
Email Verification
Troubleshooting
Email Not Sending
Check the mail queue status:
const stats = await mailService.getQueueStats();
if (stats.failed > 0) {
const failedJobs = await mailService.getFailedJobs();
console.log('Failed jobs:', failedJobs);
}
Gmail Authentication
For Gmail, you need an App Password:
- Enable 2FA on your Google account
- Generate App Password at https://myaccount.google.com/apppasswords
- Use the App Password (not your regular password) in
MAIL_PASSWORD
SMTP Connection Errors
The MailService automatically detects connection errors and won't retry permanently failed connections. Check your SMTP settings:
# Test SMTP connection
telnet smtp.gmail.com 587
Related Documentation
Pro Tip: Always use queue-based sending (sendWithQueue) in production for better performance and reliability. The queue system automatically handles retries and prevents email sending from blocking your API responses.