0

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

pelotador.1
  • 195
  • 1
  • 12
  • The error message shows that it is an absolute path that lacks project context. The code seems to use `path.resolve` incorrectly leading to this. – Dave Meehan Jun 27 '22 at 10:31
  • @DaveMeehan HI, okay, how am I using ```path.resolve``` incorrectly? – pelotador.1 Jun 27 '22 at 21:00
  • In mailer.js you ask it to resolve starting with an absolute path (leading /), so it will produce an absolute path. Note that it doesn’t validate the existence of the given path, only resolving out any path traversal when concatenating. – Dave Meehan Jun 28 '22 at 06:56

0 Answers0