简体   繁体   中英

Creating a contact form in Angular with Nodemailer

I am trying to create a contact form for my site. I am using a MEAN stack, so the nodemailer module seemed to make sense to use.

I have created an endpoint '/api/contact' to which accepts a POST request and uses the data on that request to send a mail.

I then have a form in my angular app, which on submit calls a function which makes an http.

Hopefully this sounds correct. As an aside I've been using the Yeoman angular-fullstack generator, so my code is following that structure.

When the app loads though in my console I see a 500 error code, and then when I look in the logs I see an error in reading the from and body properties in my contact.controller.

Here's my code:

app.js

...

var express = require('express');

---

// Setup server
var app = express();
var server = require('http').createServer(app);
require('./config/express')(app);
require('./routes')(app);

// Start server
server.listen(config.port, config.ip, function () {
  console.log('Express server listening on %d, in %s mode', config.port, app.get('env'));
});

// Expose app
exports = module.exports = app;

routes.js

module.exports = function(app) {

  // Insert routes below
  app.use('/api/contact', require('./api/contact'));
...

./api/contact/index.js

var express = require('express');
var controller = require('./contact.controller');

var router = express.Router();

router.post('/', controller.send);

module.exports = router;

./api/contact/contact.controller.js

var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
  service: 'gmail',
  auth: {
    user: //removed
    pass: //removed
  }
});

exports.send = function(req,res){
  var mailOptions = {
    to: //removed - my email address,
    subject: 'New request on lumbajack from ',
    from: req.data.from,
    html: req.data.body
  };
  transporter.sendMail(mailOptions, function(err, info){
    if (err) {
      console.log(err);
    }else{
      console.log('Message sent: ' + info.response);
    }
  });
}

Then on the client side, my angular controller

angular.module('lumbajackApp')
  .controller('MainCtrl', ['$http', function ($http) {
    var ctrl = this;

    ctrl.emailData = {
        from: '',
        name: '',
        body: ''
    };

    ctrl.postMail = function (data) {
        $http.post('/api/contact', data);
    };

  }]);

And finally my HTML

<form ng-submit="main.postMail(main.emailData)" novalidate>
    <input type="text" ng-model="main.emailData.from">
    <input type="text" ng-model="main.emailData.name">
    <input type="text" ng-model="main.emailData.body">
    <input type="submit" value="Submit">
  </form>

You were missing the callback in your server controller. I rewrote some of the code below

(server/api/contact/contact.controller.js)

var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
  service: 'gmail',
  auth: {
    user: me@gmail.com,    // your email here
    pass: xxxxxxx          // your password here
  }
});

exports.send = function(req,res){
  var htmlContent = '<p>Name: ' + req.body.name + '</p>' +
                    '<p>Email: ' + req.body.email + '</p>' +
                    '<p>Message: ' + req.body.message + '</p>';
  var mailOptions = {
    to: 'me@gmail.com',                  // your email here
    subject: 'New message',
    from: req.body.name + ' <' + req.body.email + '>',
    sender: req.body.email,
    html: htmlContent
  };
  transporter.sendMail(mailOptions, function(err, info){
    if (err) {
      console.log(err);
    }else{
      console.log('Message sent: ' + info.response);
      return res.json(201, info);
    }
  });
}

Then in your Angular controller: (client/app/main/main.controller.js)

'use strict';

angular.module('myApp')
  .controller('MainCtrl', function ($scope, $http) {

    $scope.postData = {};

    $scope.postMail = function (contact) {
      // Check form validation
      if ($scope.contactForm.$invalid === true) {
        return
      }
      // wrap all your input values in $scope.postData
      $scope.postData = angular.copy(contact);

      $http.post('/api/contact', $scope.postData)
        .success(function(data) {
          // Show success message
        })
        .error(function(data) {
          // Show error message
        });
    };
  });

You form will look like this: (in client/app/main/main.html)

<form name="contactForm" novalidate>
  <input type="text" name="name" ng-model="contact.name" placeholder="Your name" required>
  <input type="email" name="email" ng-model="contact.email" placeholder="Your email" required>
  <textarea name="message" ng-model="contact.message" placeholder="Your message" required>{{message}}</textarea>
  <button type="submit" ng-click="postMail(contact)">Send</button>
</form>

Thanks guys. Tried doing the console log and could see the data was not being passed through, additionally, the endpoint was being hit on the page load rather than on submit.

Solved by changing the angular code around to stop the function being invoked immediately, and then had to add a response on the post call and a res.end() declaration!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM