I'm trying to use handlebars
to create templates for emails that I am sending through nodemailer
. I'm currently, get an error saying Error: ENOENT: no such file or directory, open '/backend/views/layouts/main.hbs'
. I have tried doing what both ENOENT: no such file or directory and Error: ENOENT: no such file or directory in express-handlebars suggest, but neither has helped me solve this issue. I would really appreciate any help or advice. Thank you!
server.js
import express from 'express';
import cors from 'cors';
import mongoose from 'mongoose';
import dotenv from 'dotenv';
import path from 'path';
import hbs from 'express-handlebars';
import orderRouter from './routers/orderRouter.js';
import mailerRouter from './mailer.js';
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
mongoose.connect(process.env.MONGODB_URL || 'mongodb://localhost/AM', {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
});
app.use('/api/orders', orderRouter);
const __dirname = path.resolve();
app.use('/api/mailer', mailerRouter);
app.engine('hbs', hbs({
extname: 'hbs',
defaultLayout: false,
layoutDir:__dirname+'/backend/views/layouts/',
partialsDir: __dirname + '/backend/views/layouts',
}));
app.set('views', path.join( __dirname, '/backend/views/layouts'));
app.set('view engine', 'hbs');
app.get('/', (req, res) => {
res.send('Server is ready');
});
app.use((err, req, res, next) => {
res.status(500).send({ message: err.message });
});
const port = process.env.PORT || 5000;
app.listen(port, () => {
console.log(`Serve at http://localhost:${port}`);
});
mailer.js
import express from 'express';
import expressAsyncHandler from 'express-async-handler';
import nodemailer from 'nodemailer';
import expressHbs from 'nodemailer-express-handlebars';
import handlebars from 'handlebars';
import Order from './models/orderModel.js';
import path from 'path';
import fs from 'fs';
const mailerRouter = express.Router();
/*
mailerRouter.engine('handlebar', exphbs());
mailerRouter.set('view engine', 'handlebars');
*/
mailerRouter.post (
'/order',
expressAsyncHandler(async (req, res) => {
const email = req.body.email
const orderId = req.body.orderId
const em = req.body.em
const sender = req.body.sender
const orderNum = req.body.orderNum
const emailBody = await Order.findById(orderId).lean()
if (emailBody) {
res.render('main', {data: emailBody})
}
const sub = `Order: ${orderId}`
let transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
service: 'gmail',
auth: {
type: 'OAuth2',
user: sender,
pass: '',
clientId: '',
clientSecret: '',
refreshToken: '',
}
})
const handlebarOptions = {
viewEngine: {
extName: ".hbs",
partialsDir: path.resolve('/backend/views/layouts'),
defaultLayout: 'main',
},
viewPath: path.resolve('/backend/views/layouts'),
extName: ".hbs",
}
transporter.use('compile', hbs(handlebarOptions));
const mailOptions = {
from: sender
to: em,
subject: sub,
text: '', // plain text body
//html: htmlToSend,/*output,*/ // html body
template: 'main',
}
console.log(mailOptions.template)
transporter.sendMail(mailOptions, function (err, info) {
if(err)
console.log(err)
else
console.log(info);
});
}))
export default mailerRouter;
main.hbs
(my handlebars document) directory order:
backend - views - layouts - main.hbs