Reputation: 63
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>
Upvotes: 4
Views: 4017
Reputation: 151
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: [email protected], // 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: '[email protected]', // 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>
Upvotes: 2
Reputation: 63
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!
Upvotes: 1