JS email server won't function while deployed - javascript

I'm pretty new to the space so not sure how obvious this question is. I've created a contact page for a simple website that is hosting live with a domain name. On localhost the contact page operates perfectly and the message is received successfully. However, when I attempt to submit the contact form during the web hosting i get the alert "something went wrong!" from the app.js file. I've created a html contact form, app.js and server.js file. I've also used the nodemailer extension.
Here is the app.js file:
let pname = document.getElementById('name');
let email = document.getElementById('email');
let phone = document.getElementById('phone');
let subject = document.getElementById('subject');
let message = document.getElementById('message');
contactForm.addEventListener('submit', (e)=>{
e.preventDefault();
let formData = {
pname: pname.value,
email: email.value,
phone: phone.value,
subject: subject.value,
message: message.value
}
let xhr = new XMLHttpRequest();
xhr.open('POST', '/');
xhr.setRequestHeader('content-type', 'application/json');
xhr.onload = function(){
console.log(xhr.responseText);
if(xhr.responseText == 'success'){
alert('Your email has been sent! ###### will be in touch shortly.');
pname.value = '';
email.value = '';
phone.value = '';
subject.value = '';
message.value = '';
}else{
alert('Something went wrong!')
}
}
xhr.send(JSON.stringify(formData));
})
Here is the server.js file:
const express = require('express');
const app = express();
const nodemailer = require("nodemailer");
const PORT = process.env.PORT || 5001;
//middleware
app.use('/',express.static(__dirname));
app.use(express.static('public'))
app.use(express.json())
function ignoreFavicon(req, res, next) {
if (req.originalUrl.includes('favicon.ico')) {
res.status(204).end()
}
next();
}
app.use(ignoreFavicon);
app.get('/', (req, res)=>{
res.sendFile(__dirname + '/public/contact.html');
})
app.post('/', (req, res)=>{
console.log(req.body);
const transporter = nodemailer.createTransport({
pool: true,
host: "smtp.gmail.com",
port: 465,
secure: true,
auth: {
user: "######",
pass: "######"
}
})
const mailOptions = {
from: '######',
to: '######',
subject:`You have a message from ${req.body.pname} (${req.body.email}) Subject: (${req.body.subject}) Ph: (${req.body.phone})`,
text: req.body.message
}
transporter.sendMail(mailOptions, (error, info)=>{
if(error){
console.log(error);
res.send('error');
}else{
console.log('Email sent: ' + info.response);
res.send('success')
}
})
})
app.listen(PORT, ()=>{
console.log(`Server running on port ${PORT}`)
})
Thank you!

Related

Upload Nodejs - Express Server on Cpanel

I've created a server using NodeJs on localhost:3000 for my angular application. When user will submit contact form, server will run the script and send an email.
Everything working fine on localhost but when I upload on Cpanel, its giving an error Internal Server Error: 500.
I've created Node application from Cpanel. Root file is server.js. var http is auto generated by Cpanel. Rest of the things, I've added.
Server.js
const express = require('express');
const sendMail = require('./mail.js');
const bodyParser = require('body-parser');
const cors = require('cors');
var http = require('http');
const app = express();
app.use(bodyParser.json());
app.use(cors());
var server = http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
var message = 'It works!\n',
version = 'NodeJS ' + process.versions.node + '\n',
response = [message, version].join('\n');
res.end(response);
});
server.listen();
app.post('/submit', function(req, res) {
const { name, email, phone, subject, message} = req.body;
console.log(req.body);
res.status(200).json({message: req.body});
sendMail(name, email, phone, subject, message, function(err, data) {
if(err) {
res.status(500).json({ message: 'Internal Error'});
} else {
res.json({message: 'Email Sent!!!!!'});
}
});
})
mail.js
const nodemailer = require('nodemailer');
const mailGun = require('nodemailer-mailgun-transport');
const auth = {
auth: {
api_key: 'privatekey-381f2624-ccbf9964',
domain: 'domain-17bb134be0f54584b0e8751d3a3ec19b.mailgun.org'
}
};
const transporter = nodemailer.createTransport(mailGun(auth));
const sendMail = (name, email, phone, subject, message, cb) => {
const mailOptions = {
from: email,
to: 'webmaster#gmail.com',
subject: subject,
text: 'Name: ' + name + '\n Email:' + email + '\n Phone: ' + phone + '\n Message: ' + message
};
transporter.sendMail(mailOptions, function(err, data) {
if(err) {
cb(err, null);
} else {
cb(null, data);
}
});
}
module.exports = sendMail;
Angular EmailService where I placed this api link.
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class EmailService {
_url = 'https://gump.akc-uae.com/api/submit';
constructor(private _http: HttpClient) { }
contact(clientData:any) {
return this._http.post<any>(this._url, clientData);
}
}
Its my first attempt to upload Node app on Cpanel.
ok. you were calling the sendMail function after sending the response.
Your code should be:
app.post('/submit', async function(req, res) {
const { name, email, phone, subject, message} = req.body;
try{
await sendMail(name, email, phone, subject, message,
function(err, data) {
if(err) {
res.status(500).json({ message: 'Internal Error'});
} else {
res.json({message: 'Email Sent!!!!!'});
}
});
res.status(200).json({message: req.body});
}catch(error){
res.json({message: error.message});
}
})
Note: make your sendMail function promise

Nodemailer not sending email, displays "Message sent:Undefined"

It was working and then it wasn't. I sent a few mails and after a while it stopped working. I get
"Message sent:Undefined"
(node:9048) UnhandledPromiseRejectionWarning: Error: spawn sendmail ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:269:19)
I have no idea why.
Frontend- Axios console logs the response data therefore the server and the frontend both are working. It is just the issue with the Nodemailer.
Any help is appreciated. Thanks!
const express = require("express");
const app = express();
const cors = require("cors");
const nodemailer = require("nodemailer");
const path = require("path");
const fs = require("fs");
const readData = path.join(__dirname, "../email_take2/data.json");
const { v4: uuidv4 } = require("uuid");
app.use(express.json());
app.use(cors());
const port = process.env.PORT || 5000;
app.listen(5000, () => console.log(`Listening at port ${port}`));
if (process.env.NODE_ENV === "production") {
// Set static folder
app.use(express.static("../client/build"));
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "../client", "build", "index.html"));
});
}
function listUserData() {
const data = fs.readFileSync(readData);
return JSON.parse(data);
}
app.post("/sendEmail", function (req, res) {
console.log(req.body);
const emailInfo = {
id: uuidv4(),
email: req.body.email,
cc: req.body.cc,
message:req.body.message,
};
const dataArray = listUserData();
dataArray.push(emailInfo);
fs.writeFileSync(readData, JSON.stringify(dataArray));
res.send(emailInfo);
console.log("SentBody", emailInfo);
let transporter = nodemailer.createTransport({
sendmail:true,
host: "smtp.outlook.com",
port: 587,
secure: false, // true for 465, false for other ports
tls: {
ciphers: "SSLv3",
},
auth: {
user: "memail#outlook.com", // generated ethereal user
pass: "mypw", // generated ethereal passwordAccount.pass,
},
});
// send mail with defined transport object
let info = transporter.sendMail({
from: '"Fred Foo 👻" <foo#example.com>', // sender address
to: "garbageacc7878#outlook.com", // list of receivers
subject: "Hello ✔", // Subject line
text: "Hello world?", // plain text body
html: "<b>Hello world?</b>", // html body
});
console.log("Message sent: %s", info.messageId);
return emailInfo;
});
transporter.sendMail returns a promise, that's why your console log has undefined. So either attach a .then and .catch.
transporter.sendMail(...)
.then((data)=>{console.log('Mail sent', data)})
.catch(err => {console.error('Failure',err)})
Or make your request handler an async function and use async await and use tryCatch.
try{
let data = await transporter.sendMail(...)
console.log('Mail sent', data)
} catch (err) {
console.error('Failure',err)
}

Nodemailer not sending e-mail after successful stripe payment charge

I am trying to send an email to myself after a purchase has been made via stripe. I currently have a personal and business email that I am using for this. I am new to node.js, and I'm confused as to why this is not working.
What makes sense to me is to add this code as an argument to the .then callback. When testing this out locally, the success page renders, however no emails are sent and the two console.log's at the bottom are not being outputted to the console. The following is my app.js
const express = require('express');
const stripe = require('stripe')('mystripekey');
const bodyParser = require('body-parser');
const exphps = require('express-handlebars');
const nodemailer = require('nodemailer')
var app = express();
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'myemail#gmail.com',
pass: 'mypassword'
}
});
app.engine('handlebars', exphps({defaultLayout: 'main'}));
app.set('view engine', 'handlebars')
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static(`${__dirname}/public`));
app.get('/', (req, res) => {
res.render('index');
});
app.post('/charge', (req, res) => {
const amount = 25000;
stripe.customers.create({
email: req.body.stripeEmail,
source: req.body.stripeToken
})
.then(customer => stripe.charges.create({
amount,
description: 'Advertisement',
currency: 'usd',
customer: customer.id
}))
.then(charge => {
// This is where I'm getting confused
res.render('success')
var mailOptions = {
from: req.body.stripeEmail,
to: 'mybizemail#gmail.com',
subject: 'A purchase was made',
text: req.body.stripeEmail + ' made a purchase!'
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
});
});
I expected either an error message to be logged or the email sent to be logged but that is not happening. Any help is greatly appreciated.
I think the node mailer code is never getting called. Try putting the res.render in callback in transporter.sendMail.
Like so:
.then(charge => {
console.log("charge>", charge);
var mailOptions = {
from: req.body.stripeEmail,
to: 'mybizemail#gmail.com',
subject: 'A purchase was made',
text: req.body.stripeEmail + ' made a purchase!'
};
console.log("mailOptions>", mailOptions);
transporter.sendMail(mailOptions, function(error, info){
console.log("error1>", error);
console.log("info>", info);
if (error) {
console.log(error);
res.render('error')
} else {
console.log('Email sent: ' + info.response);
res.render('success')
}
});
});

Sending data with vanilla JS ajax and reading it with Node api

I have this code on my client side:
sendMail(e) {
e.preventDefault();
var name = document.getElementById('name').value;
var contactReason = document.getElementById('contactReason').value;
var email = document.getElementById('email').value;
var additionalInfo = document.getElementById('additionalInfo').value;
var body = {
name: name,
contactReason: contactReason,
email: email,
additionalInfo: additionalInfo,
};
console.log(body);
fetch('http://localhost:4000/', {
method: 'POST',
body: body.toString(),
}).then(r => console.log(r)).catch(e => console.log(e));
}
And this kind of works. It logs the object to the console, and sends something to the back end.
Here's my Node call:
var express = require('express');
var router = express.Router();
var cors = require('cors');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({extended: true}));
app.use(cors());
app.options('*', cors());
var a = '=';
router.post('/', (req, res, next) => {
console.log('mailing');
console.log(a);
console.log(req.body);
a += '=';
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
host: "smtp.gmail.com", // hostname
auth: {
user: '******',
pass: '******'
}
});
let mailOptions = {
from: `${req.body.name} ${req.body.email}`, // sender address
to: 'alexander.ironside#mygeorgian.ca', // list of receivers
subject: 'Email from UczSieApp contact form', // Subject line
text: 'Hello world ', // plaintext body
html: `
<h4>Imie: ${req.body.name}</h4>
<h4>Email: ${req.body.email}</h4>
<h4>Powod kontaktu: ${req.body.contactReason}</h4>
<p>Wiadomosc: ${req.body.additionalInfo}</p>
`
};
// send mail with defined transport object
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
return console.log(error);
}
console.log('Message sent: ' + info.response);
});
}
);
module.exports = router;
So what the code does right now:
The object is being created, something (not sure what exactly) is being send to Node back-end, and an email is being sent. But req.body is logged as {}.
What I want to do:
Read the values sent to the back-end as body and send an email with this data.
What am I missing?
I used GET instead of POST and this solved my problems. It is kind of a cheat but it works.
should add to fetch
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(body),
all correct code
frontend
sendMail(e) {
e.preventDefault();
var name = document.getElementById('name').value;
var contactReason = document.getElementById('contactReason').value;
var email = document.getElementById('email').value;
var additionalInfo = document.getElementById('additionalInfo').value;
var body = {
name: name,
contactReason: contactReason,
email: email,
additionalInfo: additionalInfo,
};
console.log(body);
fetch('http://localhost:4000/', {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(body),
method: 'POST',
}).then(r => console.log(r)).catch(e => console.log(e));
}
backend
var express = require('express');
var router = express.Router();
var cors = require('cors');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({extended: true}));
app.use(cors());
app.options('*', cors());
var a = '=';
router.post('/', (req, res, next) => {
console.log('mailing');
console.log(a);
console.log(req.body);
a += '=';
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
host: "smtp.gmail.com", // hostname
auth: {
user: '******',
pass: '******'
}
});
let mailOptions = {
from: `${req.body.name} ${req.body.email}`, // sender address
to: 'alexander.ironside#mygeorgian.ca', // list of receivers
subject: 'Email from UczSieApp contact form', // Subject line
text: 'Hello world ', // plaintext body
html: `
<h4>Imie: ${req.body.name}</h4>
<h4>Email: ${req.body.email}</h4>
<h4>Powod kontaktu: ${req.body.contactReason}</h4>
<p>Wiadomosc: ${req.body.additionalInfo}</p>
`
};
// send mail with defined transport object
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
return console.log(error);
}
console.log('Message sent: ' + info.response);
});
}
);
module.exports = router;

Node js post authentication req.username & password is undefined

So after more or less 4 hours i have finally made some of my calls to work :P
Now i have a problem here is a picture of what i am sending my server using postman:
If you cannot tell from the picture i am using form-data sending
username = arvind#myapp.com
password = pass123
Pretty standard.
The result of this is:
{
"status": 401,
"message": "Invalid credentials"
}
Now my server looks like this:
Server.js
// BASE SETUP
// =============================================================================
var express = require('express'),
bodyParser = require('body-parser');
var app = express();
var router = express.Router();
var es = require('express-sequelize');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
// =============================================================================
//Secure
app.all('/*', function(req, res, next) {
// CORS headers
res.header("Access-Control-Allow-Origin", "*"); // restrict it to the required domain
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
// Set custom headers for CORS
res.header('Access-Control-Allow-Headers', 'Content-type,Accept,X-Access-Token,X-Key');
if (req.method == 'OPTIONS') {
res.status(200).end();
} else {
next();
}
});
var auth = require('./auth.js');
app.all('/login', auth.login);
app.all('/api/*', [require('./middlewares/validateRequest')]);
// If no route is matched by now, it must be a 404
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
var env = app.get('env') == 'development' ? 'dev' : app.get('env');
var port = process.env.PORT || 8080;
var Sequelize = require('sequelize');
// db config
var env = "dev";
var config = require('./database.json')[env];
var password = config.password ? config.password : null;
// initialize database connection
var sequelize = new Sequelize(
config.database,
config.user,
config.password,
{
logging: console.log,
define: {
timestamps: false
}
}
);
//Init models
var division_model = require('./lb_models/division/division_model')(express,sequelize,router);
var user_model = require('./lb_models/user/user_model')(express,sequelize,router);
var team_model = require('./lb_models/Team')(express,sequelize,router);
app.use(division_model);
app.use(user_model);
app.use(team_model);
// START THE SERVER
app.listen(port);
console.log('Magic happens on port ' + port);
And my auth.js:
var jwt = require('jwt-simple');
var auth = {
login: function(req, res) {
var username = req.body.username || '';
var password = req.body.password || '';
if (username == '' || password == '') {
res.status(401);
res.json({
"status": 401,
"message": "Invalid credentials"
});
return;
}
// Fire a query to your DB and check if the credentials are valid
var dbUserObj = auth.validate(username, password);
if (!dbUserObj)
{ // If authentication fails, we send a 401 back
res.status(401);
res.json({
"status": 401,
"message": "Invalid credentials"
});
return;
}
if (dbUserObj) {
// If authentication is success, we will generate a token
// and dispatch it to the client
res.json(genToken(dbUserObj));
}
},
validate: function(username, password) {
// spoofing the DB response for simplicity
var dbUserObj = { // spoofing a userobject from the DB.
name: 'arvind',
role: 'admin',
username: 'arvind#myapp.com'
};
return dbUserObj;
},
validateUser: function(username) {
// spoofing the DB response for simplicity
var dbUserObj = { // spoofing a userobject from the DB.
name: 'arvind',
role: 'admin',
username: 'arvind#myapp.com'
};
return dbUserObj;
}
}
// private method
function genToken(user) {
var expires = expiresIn(7); // 7 days
var token = jwt.encode({
exp: expires
}, require('../config/secret')());
return {
token: token,
expires: expires,
user: user
};
}
function expiresIn(numDays) {
var dateObj = new Date();
return dateObj.setDate(dateObj.getDate() + numDays);
}
module.exports = auth;
using the debugger in line 4 in the auth.js i am able to find that both username & password is undefined. (therefore turned into empty strings)
Can anyone tell me why this is happening ?
Try putting the Header as Content-Type: application/json in POSTMan.

Categories