Node.js
Mail & Notifications
Send HTML emails and attachments with Nodemailer, use Handlebars for email templates, and send push notifications via Firebase Cloud Messaging.
Nodemailer Install & Transporter Config: Install Nodemailer and set up a reusable SMTP transporter using environment variables.
config/mailer.js
JS
// npm install nodemailer
const nodemailer = require('nodemailer');
const transporter = nodemailer.createTransport({
host: process.env.MAIL_HOST, // e.g. smtp.gmail.com
port: parseInt(process.env.MAIL_PORT) || 587,
secure: process.env.MAIL_PORT === '465', // true for 465, false for 587
auth: {
user: process.env.MAIL_USER,
pass: process.env.MAIL_PASS,
},
});
// Verify connection (optional, for debugging)
transporter.verify((error) => {
if (error) console.error('Mailer error:', error);
else console.log('Mailer is ready');
});
module.exports = transporter;
Send HTML Email: Send a fully formatted HTML email with a plain-text fallback using the configured transporter.
services/mailService.js
JS
const transporter = require('../config/mailer');
const sendWelcomeEmail = async (toEmail, userName) => {
const mailOptions = {
from: `"NeoNote App" <${process.env.MAIL_FROM}>`,
to: toEmail,
subject: 'Welcome to NeoNote!',
text: `Hi ${userName}, welcome aboard!`,
html: `
<h2>Welcome, ${userName}!</h2>
<p>Thanks for joining <strong>NeoNote</strong>.</p>
<a href="https://neonote.app/verify" style="
background:#6366f1;color:#fff;padding:10px 20px;
border-radius:6px;text-decoration:none;">
Verify Email
</a>
`,
};
const info = await transporter.sendMail(mailOptions);
console.log('Message sent:', info.messageId);
return info;
};
module.exports = { sendWelcomeEmail };
Email with Attachments: Attach files from disk, a buffer, or an inline base64 string to an outgoing email.
services/mailService.js
JS
const sendInvoiceEmail = async (toEmail, pdfBuffer) => {
await transporter.sendMail({
from: `"NeoNote" <${process.env.MAIL_FROM}>`,
to: toEmail,
subject: 'Your Invoice',
html: '<p>Please find your invoice attached.</p>',
attachments: [
{
// Attach from file path
filename: 'terms.pdf',
path: './storage/terms.pdf',
},
{
// Attach from Buffer (e.g. dynamically generated PDF)
filename: 'invoice.pdf',
content: pdfBuffer,
contentType: 'application/pdf',
},
{
// Inline image in HTML body
filename: 'logo.png',
path: './public/logo.png',
cid: 'logo@neonote', // referenced as <img src="cid:logo@neonote">
},
],
});
};
Email Templates with Handlebars: Use
nodemailer-express-handlebars to render .hbs template files with dynamic data. Install with npm install nodemailer-express-handlebars hbs.config/mailer.js
JS
const hbs = require('nodemailer-express-handlebars');
const path = require('path');
transporter.use('compile', hbs({
viewEngine: {
extName: '.hbs',
partialsDir: path.resolve('./views/emails/partials'),
defaultLayout: false,
},
viewPath: path.resolve('./views/emails'),
extName: '.hbs',
}));
// Send using template
await transporter.sendMail({
from: `"NeoNote" <${process.env.MAIL_FROM}>`,
to: 'user@example.com',
subject: 'Reset Password',
template: 'reset-password', // views/emails/reset-password.hbs
context: {
name: 'John',
resetLink: 'https://neonote.app/reset?token=abc123',
},
});
Firebase Cloud Messaging (FCM): Send push notifications to mobile or web clients using the Firebase Admin SDK. Install with
npm install firebase-admin.config/firebase.js
JS
const admin = require('firebase-admin');
const serviceAccount = require('./serviceAccountKey.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
module.exports = admin;
services/pushService.js
JS
const admin = require('../config/firebase');
// Send to a single device
const sendPushNotification = async (deviceToken, title, body, data = {}) => {
const message = {
token: deviceToken,
notification: { title, body },
data, // custom key-value pairs
android: { priority: 'high' },
apns: { payload: { aps: { sound: 'default' } } },
};
const response = await admin.messaging().send(message);
console.log('FCM response:', response);
return response;
};
// Send to a topic (multiple subscribers)
const sendToTopic = async (topic, title, body) => {
await admin.messaging().send({
topic,
notification: { title, body },
});
};
module.exports = { sendPushNotification, sendToTopic };