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
Related
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!
I have an express server that gets a list of podcasts, from an endpoint.
This apart works fine, but there is a token that I use in requests to authorize entry to the endpoints.
the response when gaining an access token looks like:
{ access_token: '8c9d31761cbd32da25f1f1b988b527cde01c9d8a',
expires_in: 604800,
token_type: 'Bearer',
scope: 'podcast_read episode_read podcast_update episode_publish' }
I have a refresh token that I use when refreshing the token and works well.
The way I'm doing it at the moment is, I have a text file that holds the token, the app reads from this when making a request, I have set up a function, that is called every time the podcasts route is called router.get('/podcasts', checkIfTokenValid, (req, res, next) => { to check if the token is valid or expired if so, refresh the token and write the new token to the file.
The only thing about this is; the write to file function is executed after the podcasts route connects to the endpoint, so the old access token is used.
Logging to the console, the functions are executed before the podcasts route gets all the podcasts, except for the writeAccessTokenToFile() function.
Just wondering, is there a better way to do this?
var express = require('express');
var router = express.Router();
var app = express();
var path = require('path');
var fs = require('fs');
const request = require('request');
var refreshToken = '425153ed4ddb4aee5sjsjsfaeffc46ab9944aece0400f';
var clientId = 'myId';
var client_secret = 'secret';
var isAccessTokenValid;
var access_token_file = path.join(__dirname, 'access_token.txt');
function refreshAccessToken() {
console.log('refreshAccessToken')
var body = { 'grant_type': 'refresh_token', 'refresh_token': refreshToken }
var options = {
url: `https://api.podbean.com/v1/oauth/token`,
headers: { 'Authorization': 'Basic ' + new Buffer(clientId + ":" + client_secret).toString('base64') },
json: body
}
request.post(options, (err, response, body) => {
// console.log(body.expires_in*1000)
if (err) {
return response.status(500).json({
title: 'An error has occured',
error: err
})
}
console.log(body)
writeAccessTokenToFile(body.access_token);
})
}
function getAccessToken() {
return fs.readFileSync(access_token_file, 'utf8');
}
function writeAccessTokenToFile(token) {
console.log('writeAccessTokenToFile = '+ token)
var data = getAccessToken();
var result = data.replace(data, token);
fs.writeFileSync(access_token_file, result, 'utf8');
}
function checkIfTokenValid (req, res, next) {
console.log('checkIfTokenValid')
var options = {
url: `https://api.podbean.com/v1/oauth/debugToken?access_token=${getAccessToken()}`,
headers: { 'Authorization': 'Basic ' + new Buffer(clientId + ":" + client_secret).toString('base64') }
}
request(options, (err, response, body) => {
if (err) {
return res.status(500).json({
title: 'An error has occured',
error: err
})
}
// console.log(JSON.parse(body))
isAccessTokenValid = JSON.parse(body).is_valid;
if (isAccessTokenValid) {
refreshAccessToken();
}
next();
})
};
router.get('/podcasts', checkIfTokenValid, (req, res, next) => {
var options = {
url: `https://api.podbean.com/v1/podcasts?access_token=${getAccessToken()}`
}
request(options, (err, response, body) => {
if (err) {
return res.status(500).json({
title: 'An error has occured',
error: err
})
}
res.json(JSON.parse(body));
next();
})
});
module.exports = router;
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')
}
});
});
Problem
Setting up Auth Controllers
Using Bcrypt and JWT
All POST Calls to Koa 404ing
Calls to other routes working fine
Possibly a issue with scope of code.
import * as Router from 'koa-router';
import * as bcrypt from 'bcrypt';
import User from '../models/user';
const router: Router = new Router();
/**
* Signup new Users
*/
router.post('/signup', async ctx => {
const { username, password, email } = ctx.request.body;
bcrypt.hash(password, 10, (err, hash) => {
if (err) {
ctx.status = 500;
} else {
const user = new User({
username,
password: hash,
email,
});
user.save()
.then(result => {
ctx.status = 201;
})
.catch(err => {
if (err) {
ctx.response.status = 500;
}
});
}
});
});
/**
* Log in users
*/
router.post('/login', async ctx => {
const { email, password } = ctx.request.body;
User.findOne({ email }, (err, user) => {
if (err) {
ctx.status = 401;
ctx.body = 'Auth Failed.';
}
bcrypt.compare(user.password, password, (err, result) => {
if (err) {
ctx.status = 401;
ctx.body = 'Auth Failed.';
}
if (result) {
ctx.status = 200;
ctx.body = 'Auth Successful';
} else {
ctx.status = 401;
ctx.body = 'Auth Failed';
}
});
});
});
export default router;
I am not struggling to
generate passwords or save users to
the DB and I am receiving data into the
server from the controllers the only thing
is my server is not sending back anything but
a 404 error.
import * as Koa from 'koa';
import * as dotenv from 'dotenv';
import * as mongoose from 'mongoose';
import * as cors from '#koa/cors';
import * as bodyParser from 'koa-body';
import bookRouter from './routes/book';
import userRouter from './routes/user';
dotenv.config();
const app: Koa = new Koa();
mongoose.connect(process.env.MGO_URI, { useNewUrlParser: true }).catch(error => {
console.log(error);
console.log('\n application shutting down for safety \n');
process.exit(1);
});
// application wide middleware
app.use(cors());
app.use(bodyParser());
// application routes
app.use(userRouter.routes());
app.use(bookRouter.routes());
app.listen(3000);
console.log('Server running on port 3000');
First off, if you are using an async request handler you should use await. It makes the code a lot cleaner. I think this should work (although I'm not positive if bcrypt return a promise, but I think it does), for example:
router.post('/signup', async ctx => {
const { username, password, email } = ctx.request.body;
try {
let hash = await bcrypt.hash(password, 10);
const user = new User({ username, password: hash, email });
await user.save();
ctx.status = 201;
} catch(err) {
console.log(err); // TODO: handle err
ctx.status = 500;
}
});
Hello all first and foremost this issue may seem like a duplicate but it is not as I have gone through other SO post relating to mine but it still didnt help and hence the reason I am making another. Please I need help, I have a nodejs back-end that is working locally without any issue. I uploaded it to heroku and now only two routes is working. All other routes are not working. I am able register, login and add new users.
This is for my add users routes that is working both locally and on heroku.
import mongoose from 'mongoose';
import { Router } from 'express';
import bodyParser from 'body-parser';
import User from '../model/user';
import { authenticate } from '../middleware/authMiddleware';
export default({ config, db }) => {
let api = Router();
// '/v1/user/add' - Create
api.post('/add', authenticate, (req, res) => {
let newUser = new User();
newUser.username = req.body.username;
newUser.email = req.body.email;
newUser.phonenumber = req.body.phonenumber;
newUser.profilepicurlicUrl = req.body.profilepicurl;
newUser.save(err => {
if (err) {
res.status(500).json({ message: err });
return;
}
res.status(200).json(newUser);
});
});
This is for my register user and login user that is working both locally and on heroku
import mongoose from 'mongoose';
import { Router } from 'express';
import bodyParser from 'body-parser';
import passport from 'passport';
import config from '../config';
import Account from '../model/account';
import UserDataExt from './extensions/userData-ext';
import async from 'async';
import crypto from 'crypto';
import { generateAccessToken, respond, authenticate } from '../middleware/authMiddleware';
var nodeMailer = require('nodemailer');
export default ({ config, db }) => {
let api = Router();
// '/v1/account/register'
api.post('/register', (req, res) => {
UserDataExt.findUserByEmail(req.body.email, (err, userData) => {
if (err) {
res.status(409).json({ message: `An error occured: ${err.message}`});
return;
} else if (userData) {
res.status(300).json({ message: `Email ${req.body.email} is already registered`});
}
// else {
Account.register(new Account({username: req.body.email}), req.body.password, function(err, account) {
if(err) {
res.status(500).json({ message: err });
return;
}
console.log("Registering new account");
passport.authenticate('local', { session: false })(req, res, () => {
res.status(200).send('Successfully created new account');
});
});
// }
});
});
// '/v1/account/login'
api.post('/login', (req, res, next) => {
UserDataExt.findUserByEmail(req.body.email, (err, userData) => {
if (err) {
res.status(409).json({ message: `An error occured: ${err.message}`});
return;
} else {
next();
}
});
}, passport.authenticate('local', { session: false, scope: [] }), (err, req, res, next) => {
if (err) {
res.status(401).json({ message: `Password is incorrect`});
return;
}
}, generateAccessToken, respond);
This is for my category route that is not working on heroku, but is working locally
import mongoose from 'mongoose';
import { Router } from 'express';
import Category from '../model/category';
import bodyParser from 'body-parser';
import { authenticate } from '../middleware/authMiddleware';
export default({ config, db }) => {
let api = Router();
// /v1/category/add Create
api.post('/add', authenticate, (req, res) => {
let newCategory = new Category();
newCategory.submittedById = req.body.submittedById;
newCategory.categoryTitle = req.body.categoryTitle;
newCategory.categoryDescription = req.body.categoryDescription;
newCategory.recommended = req.body.recommended;
newCategory.save(err => {
if (err) {
res.status(500).json({message: err});
return;
}
res.status(200).json({message: 'Category saved successfully'});
});
});
// /v1/category/ Read
api.get('/', authenticate, (req, res) => {
Category.find({}, (err, category) => {
if (err) {
res.status(500).json({message: `An erro has occured ${err.message}`});
return;
}
res.status(200).json(category);
});
});
This is my authenticate middleware code
import jwt from 'jsonwebtoken';
import expressJwt from 'express-jwt';
const TOKENTIME = 60*60*24*90;
const SECRET = "#######";
let authenticate = expressJwt({ secret: SECRET });
let generateAccessToken = (req, res, next) => {
req.token = req.token || {};
req.token = jwt.sign ({
id: req.user.id,
}, SECRET, {
expiresIn: TOKENTIME // 90 days
});
next();
}
let respond = (req, res) => {
res.status(200).json({
user: req.user.username,
token: req.token,
id: req.user._id
});
}
module.exports = {
authenticate,
generateAccessToken,
respond
}