Connection closed unexpectedly: Nodemailer - smtp

const express = require('express');
const app = express();
const nodemailer = require('nodemailer');
//Middleware
app.use(express.static('frontend'));
app.use(express.json());
app.get('/',(req,res)=>{
res.sendFile(__dirname + '/frontend/index.html');
});
app.post('/', (req,res)=>{
console.log(req.body);
const transporter1 = nodemailer.createTransport({
service:"gmail",
host: "smtp.gmail.com", // hostname
secure: false, // use SSL
port: 587, // port for secure SMTP
auth: {
user: "my email id",
pass: "mypassword"
},
tls: {
ciphers: "SSLv3",
rejectUnauthorized: false,
},
});
const mailOptions = {
from:req.body.email,
to: 'prahlad.hsrao#gmail.com',
cc: '24septanjali#gmail.com',
subject: 'Form Information',
text:"firstName: "+ req.body.fname+"\n" + "lastName"+req.body.lname+"email" + req.body.email+"phone"+req.body.phone+"message"+req.body.message,
}
transporter1.sendMail(mailOptions,(error,info)=>{
if(error){
console.log(error);
res.send('error');
transporter1.close();
}
else{
console.log('Email sent' + info.response);
res.send('success');
res.redirect('/');
transporter1.close();
}
})
})
app.listen(3000,()=>console.log('Server started...'));
firstly it was working perfectly, I send the email successfully 5-6 time, then while trying to send the mail, it is giving following error.
Error: Connection closed unexpectedly
at SMTPConnection._onClose (D:\official\SendEmailProject\nodeContactForm\node_modules\nodemailer\lib\smtp-connection\index.js:827:34)
at TLSSocket.SMTPConnection._onSocketClose (D:\official\SendEmailProject\nodeContactForm\node_modules\nodemailer\lib\smtp-connection\index.js:193:42)
at Object.onceWrapper (node:events:628:26)
at TLSSocket.emit (node:events:525:35)
at node:net:757:14
at TCP.done (node:_tls_wrap:584:7) {
code: 'ECONNECTION',
command: 'CONN'

I also got this error. After searching I guess it's a problem with the email server. I got about 5% of all my auto emails to fail. Maybe we can try to change one.

Related

Why is this POST request failing from Postman?

Backend of my app is deployed on Heroku using Cleardb addon.
Below is the Backend code: For what I can tell it is hitting the POST requst.
const express = require('express');
const cors = require('cors');
//const mysql = require("mysql");
//this was the old way and did not support secure password
mysql = require('mysql2');
const app = express();
const port = process.env.PORT || 8000
/*
local connection
const db = mysql.createConnection({
connectionaLimit: 50,
user:'root',
host: 'localhost',
password:'',
database:'sys',
port: 3306
});
*/
const db = mysql.createConnection({
connectionaLimit: 120,
user: process.env.DB_USER,
host: process.env.DB_HOST,
password: process.env.DB_PASSWORD,
database: process.env.DATABASE,
port: 3306
});
app.use(cors());
app.use(express.urlencoded({extended: true}));
app.use(express.json());
//SQL connection test
db.connect((err) => {
if (err) console.error(err);
console.log('MySQL Connection Established.');
});
/* not used get request
app.get('/', (req,res) => {
res.header("Access-Control-Allow-Origin", "*");
res.send('Hello back');
}
);
*/
app.post('/' , (req,res) => {
const {email, name, question} = req.body;
res.header("Access-Control-Allow-Origin", "*");
console.log(`Your Email is ${email} and your name is ${name} and your ${question}`);
//MYSQL updating table
db.query("INSERT INTO customer_questions (name, email, question) VALUES (?,?,?)",
[name, email, question], (err,result)=> {
if (err) {
console.log(err)
}else {
res.send('data sent')
}
db.end();
}
);
});
app.listen(port);
console.log(`server is listing on ${port}`);
This is the error log. From what I can tell it the server runs and then stops and the post request hits status 500. I can tell why this is happening.
Post request using POSTMAN showing body.
Any help on this would be helpful. The MYSQL connection works both locally and through Heroku.
Use a connection pool and don't close the connection:
db.end();
You can run querys on the pool object and it will take care of opening/closing connections for you.

Nodejs: Post method url body parser shows undefined

I want to use url post params to execute mysql query. I am getting error during mysql command when I post through postman. I dont know what is problem with this code. Here is my code
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mysql = require('mysql');
var md5 = require('MD5');
var con = mysql.createConnection({
host: "localhost",
user: "shoaib",
password: "",
database: "watch"
});
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
});
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var port = process.env.PORT || 8080;
var router = express.Router();
router.post('/',function(req, res) {
con.connect(function(err) {
var query = "Select * From user Where email=? AND password=?";
var table = [req.body.email,req.body.password ];
console.log(req.body);
query = mysql.format(query, table);
con.query(query, function (err, rows) {
if (err) {
res.json({ "Error": true, "Message": "Error executing MySQL query" });
} else if(rows!=0) {
res.json({ "Error": false, "Message": "Success","Users": rows });
} else {
res.json({ "Error": true,});
}
});
});
});
app.use('/api', router);
app.listen(port);
console.log('Magic happens on port ' + port);
Node is working perfectly but when I execute command url I face error.
Make sure on your request that you set the Content-Type header to application/json or application/x-www-form-urlencoded since your app supports either. Without a Content-Type header with either of these values body-parser will not read the request body and res.body will be undefined.
Example POST Request with Content-Type: application/json
const {request} = require('http')
const requestBody = {email: 'abc#gmail.com', password: 'abcdef123456'}
const jsonPostRequest = request({
method: 'POST',
host: 'localhost',
port: 8080,
path: '/api/',
headers: {'Content-Type': 'application/json'}
}, res => {
let chunks = ''
// Handle Response Chunk
res.on('data', chunk => (chunks += chunk))
// Handle Response Ended, print response body
res.on('end', () => console.log(chunks))
})
jsonPostRequest.write(requestBody)
jsonPostRequest.end()

Nodemailer Email sending not working

I'm trying to send an email from my application. I tried the below code. Can someone please help me where I'm wrong?
When I'm submitting my form, I'm not getting any error. But, I'm not able to get the email on the recipient side.
Thank you
'use strict';
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
// host: 'smtp.gmail.com',
service: "Gmail",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: 'xyz#gmail.com',
pass: '**********'
}
});
/**
* Module dependencies.
*/
var path = require('path'),
mongoose = require('mongoose'),
Enquire = mongoose.model('Enquire'),
errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller')),
_ = require('lodash');
exports.sendMail = function(req, res) {
var data = req.body;
rand=Math.floor((Math.random() * 100) + 54);
host=req.get('host');
console.log("send MailData :: " + data)
var link="http://"+req.get('host')+"/verify?id="+rand;
var mailOptions={
from: data.contactEmail,
to : 'abc#gmail.com',
subject : "Please confirm your Email account",
html : "Hello,<br> This is your test email for the Inquiry Form."
}
console.log(mailOptions);
transporter.sendMail(mailOptions, function(error, response){
if(error){
console.log(error);
res.end("error");
}else{
console.log("Message sent: " + response.message);
res.end("sent");
}
});
res.json(data);
};

How to create login endpoint using express-session and express-mysql-session

I want to create a secure login. I'd like to add session but I can't figure out how they should be used together.
I have 2 codes, one code came from express-mysql-session and another code which I wrote and has the login (/api/login) endpoint.
Below is the code which I copied from the readme.md of express-mysql-session and it works.
var express = require('express');
var app = module.exports = express();
var session = require('express-session');
var MySQLStore = require('express-mysql-session')(session);
var options = {
host: 'localhost',
port: 3306,
user: 'root',
password: 'password',
database: 'session_test'
};
var sessionStore = new MySQLStore(options);
app.use(session({
key: 'session_cookie_name',
secret: 'session_cookie_secret',
store: sessionStore,
resave: true,
saveUninitialized: true
}));
Here is the output on the terminal. The code above ran well but not really sure what it did. I see it has established connection to the locally running mysql using netstat command
tcp4 0 0 127.0.0.1.3306 127.0.0.1.52470 ESTABLISHED
tcp4 0 0 127.0.0.1.52470 127.0.0.1.3306 ESTABLISHED
then the output
$ DEBUG=express-mysql-session* node index.js
express-mysql-session:log Creating session store +0ms
express-mysql-session:log Setting default options +2ms
express-mysql-session:log Creating sessions database table +46ms
express-mysql-session:log Setting expiration interval: 900000ms +42ms
express-mysql-session:log Clearing expiration interval +0ms
Then below is the basic login auth endpoint I created using Express. This works but I want to add express-session, express-mysql-session as well as use crypt, bcrypt or scrypt-for-humans but not sure how to integrate it.
const express = require('express');
const bodyParser = require('body-parser');
const mysql = require('mysql');
const app = express();
app.use(bodyParser.json()); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.set('port', (process.env.API_PORT || 8000));
const connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'password',
database : 'authdb'
});
connection.connect(function(err) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
}
console.log('connected as id ' + connection.threadId);
});
app.post('/api/login', function(req, res) {
const user_id = req.body.user_id;
const password = req.body.password;
let response = {};
res.setHeader('Content-Type', 'application/json');
connection.query('SELECT password from user WHERE `username` = "' + user_id + '"' , function(err, rows) {
if (err) throw err;
if (rows.length > 0) {
if (password === rows[0].password) {
response.status = 200;
response.message = "authenticated";
response.authenticated = true;
response.user_id = user_id;
} else {
response.status = 403;
response.message = "Login failed!";
response.authenticated = false;
response.user_id = user_id;
}
} else {
response.status = 403;
response.message = "Login failed!";
response.authenticated = false;
response.user_id = user_id;
}
res.status(response.status).send(JSON.stringify(response));
});
});
app.listen(app.get('port'), () => {
console.log(`Find the server at: http://localhost:${app.get('port')}/`);
});
I got it working and quite happy with the results. My login endpoint is working great! I now have more ideas on how to make it better as well. Here is the screenshot of the REST client - http://i.imgur.com/fJOvmzh.png and below is the endpoint
app.post('/api/login', function(req, res) {
const user_id = req.body.user_id;
const password = req.body.password;
let response = {};
res.setHeader('Content-Type', 'application/json');
connection.query('SELECT * FROM authdb.users as authusers inner join authdb.passwords as hashed on authusers.email = hashed.email WHERE authusers.email = "' + user_id + '"' , function(err, rows) {
if (err) throw err;
Promise.try(function(){
return scrypt.verifyHash(password, rows[0].password);
}).then(function(){
var sess = req.session;
if (sess.views) {
sess.views++;
} else {
sess.views = 1
}
response = { status: 200, message: "Login successful!", authenticated: true, user_id: user_id, views: sess.views }
res.status(response.status).send(JSON.stringify(response));
}).catch(scrypt.PasswordError, function(err){
response = { status: 403, message: "Login failed!", authenticated: false, user_id: user_id }
res.status(response.status).send(JSON.stringify(response));
});
});
});
To make it secure, I'll setup an EC2 behind an ELB which terminates all SSL connections and sends all traffic in clear to the NodeJS running my Express auth API spawned by PM2 or other better balancers. The AWS secgroup will only accept traffic whose source is the ELB.

Nodemailer Sendgrid on Compute Engine

i trying to send emails from my compute engine instance but nothing happen(no error message). When i send mails from my local pc i get the emails.
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
var options = {};
var transporter = nodemailer.createTransport(smtpTransport({
service: 'SendGrid',
auth: {
user: 'username',
pass: 'password'
}
}));
module.exports = {
sendmailto : sendmailto
}
function sendmailto(emailfrom,emailto, message){
var mailOptions = {
from: emailfrom, // sender address
to: emailto, // list of receivers
subject: 'Monitoring', // Subject line
text: message, // plaintext body
html: '<b>Monitoring</b>' +
'<p> '+message+'<p>' // html body
};
transporter.sendMail(mailOptions, function(error, info){
if(error){
return console.log(error);
}else{
console.log('Message send: ', + info.response);
}
});
};
I found the reason be myself:) Service "Sendgrid use as standard port the 25 but is does not work with compute engine so i need to add the port 2525.
var transporter = nodemailer.createTransport(smtpTransport({
service: 'SendGrid',
port: '2525',
auth: {
user: 'username',
pass: 'password'
}
}));