How to fix TypeError: Cannot read property 'name' from Express Nodemailer

jemiloii picture jemiloii · Mar 19, 2014 · Viewed 17.9k times · Source

So I do want to say that I've been searching for the answer for this and I've also tried to console.log my req.body post form and I keep getting undefined. So I feel that I'm losing the data from the form I send, I'm not sure what I"m doing wrong. So time to show some code.

As a note: I am using Handlebars for my Express Setup.

app.js

var express    = require('express'),
    exphbr     = require('express3-handlebars'), // "express3-handlebars"
    nodemailer = require('nodemailer'),
    helpers    = require('./lib/helpers'),

    app = express(), handlebars;

// Create `ExpressHandlebars` instance with a default layout.
handlebars = exphbr.create({
    defaultLayout: 'main',
    helpers      : helpers,
    extname      : '.html',

    // Uses multiple partials dirs, templates in "shared/templates/" are shared
    // with the client-side of the app (see below).
    partialsDir: [
        'views/shared/',
        'views/partials/'
    ]
});

// Register `hbs` as our view engine using its bound `engine()` function.
app.engine('html', handlebars.engine);
app.set('view engine', 'html');

require("./routes")(app, express, nodemailer);

app.listen(3000);

routes.js

module.exports = function (app, express, nodemailer) {

    // set up the routes themselves
    app.get('/', function (req, res) {
        res.render('home', {
            title: 'Larry King Orchestra'
        });
    });

    // I cut out a majority of my routes to make this easier to read.

    // SEND EMAIL FROM FORM
    app.post('/', function (req, res) {
        console.log("WTF");
        console.log(req.body.name);
        console.log(req.body.email);

        var mailOpts, smtpTrans;

        //Setup nodemailer transport, I chose gmail. Create an application-specific password to avoid problems.
        smtpTrans = nodemailer.createTransport('SMTP', {
            service: 'Gmail',
            auth: {
                user: "[email protected]",
                pass: "password" 
            }
        });

        //Mail options
        mailOpts = {
            from: req.body.email, //grab form data from the request body object
            to: '[email protected]',
            subject: 'LKO Contact Form',
            html: 'From: ' + req.body.name + ' &lt;' + req.body.email + '&gt; <br>Phone: ' + req.body.tel + '<br>Date of Event: ' + req.body.date + '<br>Location: ' +  req.body.location + '<br>Details &amp; Comments:<br>' + req.body.message + '<br><br><p>Email form provided by <a href="http://www.wavamedia.com/">WavaMedia</a>.'
        };

        smtpTrans.sendMail(mailOpts, function (error, response) {
            //Email not sent
            if (error) {
                res.render('home', { 
                    title: 'Larry King Orchestra', 
                    msg: 'Error occured, message not sent.', 
                    err: true, 
                    page: 'home' 
                });
            }
            //Yay!! Email sent
            else {
                res.render('home', { 
                    title: 'Larry King Orchestra', 
                    msg: 'Message sent! Thank you.', 
                    err: false, 
                    page: 'home'
                });
            }
        });
    });

    // STATIC ROUTE FOR ASSESTS
    app.use(express.static('assests/'));
};

I renamed the handlebars extension to be .html and I have the main layout using partials. SO app.get('/') will show this next file as a partial, and render it on the page.

contact.html

<form class="contact" action="/" method="post">
    <label for="name">Name</label>
    <input type="name" name="name" id="name">

    <label for="email">Your Email (required)</label>
    <input type="email" name="email" id="email">

    <label for="tel">Phone Number</label>
    <input type="tel" name="tel" id="tel">

    <label for="date">Date of Your Event</label>
    <input type="date" name="date" id="date">

    <label for="location">Venue/Location</label>
    <input type="location" name="location" id="location">

    <label for-"message">Details &amp; Comments</label>
    <textarea name="message" id="message" rows="3"></textarea>

    <input type="submit" name="submit" id="submit" value="Send" class="btn btn-default">
</form>

My Error:

TypeError: Cannot read property 'name' of undefined at c:\xampp\htdocs\lko\routes.js:129:26 at callbacks (c:\xampp\htdocs\lko\node_modules\express\lib\router\index.js:164:37) at param (c:\xampp\htdocs\lko\node_modules\express\lib\router\index.js:138:11) at pass (c:\xampp\htdocs\lko\node_modules\express\lib\router\index.js:145:5) at Router._dispatch (c:\xampp\htdocs\lko\node_modules\express\lib\router\index.js:173:5) at Object.router (c:\xampp\htdocs\lko\node_modules\express\lib\router\index.js:33:10) at next (c:\xampp\htdocs\lko\node_modules\express\node_modules\connect\lib\proto.js:193:15) at Object.expressInit [as handle] (c:\xampp\htdocs\lko\node_modules\express\lib\middleware.js:30:5) at next (c:\xampp\htdocs\lko\node_modules\express\node_modules\connect\lib\proto.js:193:15) at Object.query [as handle] (c:\xampp\htdocs\lko\node_modules\express\node_modules\connect\lib\middleware\query.js:45:5)

So I'm not sure where I'm going wrong with the code. I believe the form is sending data to my node app, but where it's going, I'm not sure. I've setup the post method and so far no luck :( I have been trying for a couple days now. I have nodemailer installed as well. I've restarted the server, updated node and npm.

JavaScript Node Guru Masters, only you can show me the light! And thanks for reading though all of this, totally awesome!

Answer

mrcni picture mrcni · Mar 19, 2014
app.use(express.bodyParser());

add that to your app.js that's what grabs information from the post data form.