Express backend dropping data when passed from Angular 5 App - node.js

I am building a little demo app to send emails from a form using Node Mailer. I've connected an Angular 5 app to an Express 4 backend. I am running things very simply, with a server.js express file in my project referencing the angular dist file. I then build the angular app and run the server.
Everything is working fine, and the email even sends, but somehow the express backend is losing the data (or I am just not accessing it correctly). The email sends with "undefined" everywhere that I try to use data.
I fill out form fields for name, phone, email, and address. Then I pull the data into a service and send it to the backend. This is my service in Angular that sends the data:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable()
export class ClientService {
headers: any;
clientInfo = '';
constructor(private http: HttpClient) { }
sendEmail(clientData) {
console.log(clientData);
return this.http.post('/send-email', clientData);
}
}
When I send this http post it looks good. The request url is correct, the header is application/json, and the payload data is correct: {name: "John Doe", email: "john#johndoemail.com", phone: "18005555555", message: "test"}
Here is my server.js: (sub in a valid gmail account info where there are x's)
// Get dependencies
const express = require('express');
const nodemailer = require("nodemailer");
const path = require('path');
const http = require('http');
const bodyParser = require('body-parser');
const app = express();
const port = 4300;
// Start server
app.listen(port, function(req, res) {
console.log('Server is running at port: ', port);
})
// Point static path to dist
app.use(express.static(path.join(__dirname, 'dist')));
// Home route to serve the index file
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
// Parsers for POST data
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/send-email', function (req, res) {
console.log(req.body);
let transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
user:'xxxxxx#gmail.com',
pass: 'xxxxxxxx',
}
});
let message = {
from: 'mailer#nodemailer.com',
to: 'xxxxx#gmail.com',
subject: 'New Client Message ' + req.body.name,
text: 'Name: ' + req.body.name + '\nEmail: ' + req.body.email + '\nPhone: ' + req.body.phone + '\n ' + req.body.message,
html: '<p>' + req.body.message + '</p>'
};
transporter.sendMail(message);
res.json(req.body);
});
In the server console req.body shows up as "{}".
Using my own email, I get a message sent from nodemailer, but all of the data used simply says "undefined".
Do I need to access the data differently? Maybe use another property of req? Anyway, it looks like the issue is in my express file, so let me know if you see any issues there.

I found the solution. I was not implementing a header with my post data. I added these changes to my service and the issue was resolved:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
#Injectable()
export class ClientService {
httpHeader = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
})
};
constructor(private http: HttpClient) { }
sendEmail(clientData) {
console.log(clientData);
this.http.post('/send-email', clientData, this.httpHeader);
}
}
If you want to see the full demo look here: https://github.com/xTumulus/NodeMailer_AngularExpress_Demo

Related

CORS blocking post requests - react and node.js

I am a beginner in server side programming. Trying to write code that will allow me to get data from state variable, send it to my backend and use nodemailer service to send it to an email adress. My frontend is as follows :
const handleSubmit = async () => {
try {
await axios.post(
"http://localhost:2525/send_mail",
{
state
}
);
} catch (error) {
console.log(error);
}
};
state gets sent to backend :
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const nodemailer = require('nodemailer');
require('dotenv').config();
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.options('',cors());
app.get('/', (req, res) => {
res.send('Server is running');
});
app.post("/send_mail", cors(), async (req, res) => {
let { state } = req.body;
const transport = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'adress#mail.com',
pass:'password'
}
});
await transport.sendMail({
from: '<myemail.#example.com>',
to: "reciever#example.com",
subject: "test email",
html: `<div><p>${state.Message}</p></div>`
});
});
app.listen(process.env.PORT || 2525, () => { console.log("Server is running"); });
If it matters, state is an object that gets filled from form data, it looks something like :
const data = {
FirstName: "",
LastName: "",
Message:"",
};
When i visit port 2525, server is indeed running with the message i gave it. But when i try to submit my form with "handleSubmit", i get the following console error:
*>
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:2525/send_mail. (Reason: CORS request did not succeed). Status code: (null).*
And it crashes the server
As you can see i am already using cors middleware to try to handle it.
I tried adding a proxy to the package.json file, as : "proxy": "http://localhost:2525", ( i did not change anything else when i did that, i don't know if that is the correct way). This did not solve anything, but at least the server did not crash any more. Instead, the POST request gets a 404:
*
POSThttp://localhost:2525/send_mail Referrer Policystrict-origin-when-cross-origin*
I tried running it in Chrome, same problem. I tried everything i could read on stackoverfrlow google or chat gpt, really that is cors-related. Even checked if port is maybe taken by something else in windows, checked that in cmd. Im at my wits end really

Nuxt.js and Node.js simple form with nodemailer PROBLEM :(

I am new to Nuxt.js and Node.js. I would like to run a very simple contact form on a 'contact.vue' page. It works very well locally, but as soon as I do an 'npm run generate' to generate the files and upload all of this to an FTP it doesn't work anymore. I have an error in the console: "POST http://website.com/api/message 404 (Not Found)"
I use the POST method on my form with the action that points to 'api / message'. I am using axios in a method (on this same 'contact.vue' page :
async onSubmit (e) {
e.preventDefault()
await this.$axios.post('/api/message', {
name: this.contactForm.name,
firstname: this.contactForm.firstname,
})
.then((res) => {
// On clear le formulaire
this.contactForm.name = ''
this.contactForm.firstname = ''
})
.catch((err) => {
console.log(err)
})
}
I have in the root folder an 'api/' folder with inside 'index.js' and the code :
const app = require('express')()
const bodyParser = require('body-parser')
const nodemailer = require('nodemailer')
module.exports = { path: '/api', handler: app }
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.post('/message', async (req, res) => {
const contenuFormulaireContact = `
<ul>
<li>Nom : ${req.body.name}</li>
<li>Prénom : ${req.body.firstname}</li>
</ul>
`
// NODEMAILER
const transporter = nodemailer.createTransport({
host: '',
port: 465,
secure: true,
auth: {
user: '',
pass: ''
}
})
const info = await transporter.sendMail({
from: '"Website's Name" <hello#website.com>', // sender address
to: 'myemail#website.com', // list of receivers
subject: `NEW MESSAGE : ${req.body.subject}`, // Subject line
text: '', // plain text body
html: contenuFormulaireContact // html body
})
console.log('Message sent: %s', info.messageId)
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info))
res.redirect(200, '/contact')
})
Inside the nuxt.config.js i have :
/*
** Nuxt.js modules
*/
modules: [
'#nuxtjs/pwa',
'#nuxtjs/axios'
],
/*
** Axios cfg
*/
axios: {
baseURL: '/'
},
/*
** Server middleware
*/
serverMiddleware: ['~/api/index.js'],
I'm sorry if for some of you this problem may seem very obvious but I'm completely stuck.
Thank you very much in advance if you take the time to help me.
Actually when you run npm run generate, the website becomes fully static and node doesn't run in the background anymore. This is why your code would works with npm run dev or npm run start since they runs node simultaneously.
I am facing the same issue. A static website is not able to send mail from the client. It has to be sent server-side. To make your code works, you either have to use a node.js server, use serverless functions solutions like AWS Lambda or Netlify functions which will executes the mail sender function or use an external REST API service like Formspree or 99inbound.
See https://stackoverflow.com/a/53560851/2610770.
I hope I helped you a bit!

Nodemailer working on Localhost, not on live Netlify site

I have used nodemailer/axios to get information from a form to be sent to an e-mail address.
When the site is run with localhost:3000 the mail gets sent no problem, although live it does not come through.
I am assuming it has to be something to do with the proxy?
This is what my code looks like which works:
const proxy = require('http-proxy-middleware')
module.exports = function(app) {
app.user(proxy("/api", { target: "http://localhost:3000"}))
}
the live site is at: https://deathless-studio.netlify.com/#/
I tried changing the target to that, as well as: https://deathless-studio.netlify.com/ and also http://deathless-studio.netlify.com/#/, although no mail gets sent through.
I always get these errors:
https://deathless-studio.netlify.com/api/v1/sendMail 404
POST https://deathless-studio.netlify.com/api/v1/sendMail 404
my send mail function looks like this:
const sendEmail = (name, email, message, newsletter) => {
const smtpTransport = mailer.createTransport({
service: "Gmail",
auth: {
user: "(correct email)",
pass: "(correct password)"
}
})
const mail = getEmailData(name, email, message, newsletter)
smtpTransport.sendMail(mail, function(error, response) {
if(error) {
console.log(error)
} else {
alert( "Thank you! We will be in touch shortly!")
}
smtpTransport.close();
})
the handleSubmit function on my Form Component looks like this also:
handleSubmit(event) {
event.preventDefault();
const data = {
name: this.state.name,
email: this.state.email,
message: this.state.message,
newsletter: this.state.newsletter
};
Axios.post("api/v1/sendMail", data)
alert( "Thank you! We will be in touch shortly!")
}
and my index.js looks like this:
const server = require("./server");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
server.use(bodyParser.urlencoded({ extended: true }));
server.use(bodyParser.json());
server.use(cookieParser());
const { sendEmail } = require("../server/routes/mail");
server.post("/api/v1/sendMail", (req, res) => {
sendEmail(req.body.name, req.body.email, req.body.message, req.body.newsletter);
});
const port = process.env.PORT || 3000;
server.listen(port, () => {
// eslint-disable-next-line no-console
console.log("Server listening on port", port);
});
Any ideas on how to fix this?
Greatly appreciated.
So it turns out Netlify doesn't use a Node.js server and you can use their plugins instead.
This article explains it:
https://community.netlify.com/t/node-js-wont-start-trying-to-run-a-server-on-netlify/3454/2?fbclid=IwAR0wc4iLhFdS-_dZF4TGPyzONmfHQxwfEztNFO2oTTlonrsBwCF73Xf7QNY

How to POST from angular 2 to express server

Newbie here trying to get a grasp on sending contact form data from Angular 2 to a Node/Express server... Right now I'm hosting Angular 2 with the built-in server at localhost:4200, and the express server at localhost:3000. I tried the following code but am getting the following error:
Error: ENOENT: no such file or directory, stat 'C:\Users\corey\Desktop\Project\server\api\contact-form-submit'
Here is my contact-form.component.ts file:
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'app-contact-form',
templateUrl: './contact-form.component.html',
styleUrls: ['./contact-form.component.css']
})
export class ContactFormComponent {
constructor(private http: HttpClient) {}
onSubmit(form) {
this.http.post('http://localhost:3000/server/api/contact-form-submit', JSON.stringify(form.value)).subscribe();
console.log(form.value);
}
}
Here is my server.js file:
var express = require('express');
var nodemailer = require('nodemailer');
var mg = require('nodemailer-mailgun-transport');
var bodyParser = require('body-parser');
var app = express();
var path = require('path');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
//trying to get contact form submission from angular 2 form here
app.get('/', function (req, res) {
res.sendfile('./api/contact-form-submit');
console.log('test');
});
//api key and domain for mailgun
var auth = {
auth: {
api_key: 'api-key-here',
domain: 'mailgun#domain here'
}
}
//trying to send email with nodemailer here
app.post('./api/send', function(req, res) {
var transporter = nodemailer.createTransport(mg(auth));
var mailOptions = {
from: 'postmaster#email.com',
to: 'email#goeshere.com',
subject: 'Website submission',
text: 'Name: ' + req.body.name + 'Email: ' + req.body.email + 'Message: ' + req.body.message,
html: '<p>Submission: </p><br><ul><li>Name: ' + req.body.name + '</li><li>Email: ' + req.body.email + '</li><li>Message: ' + req.body.message + '</li></ul>'
};
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
console.log(error);
res.redirect('/');
} else {
console.log('Message sent.');
res.redirect('/');
}
})
});
app.listen(3000, function() {
console.log('Express started on port 3000');
});
I get successful form data to use within Angular 2, and I had the express server sending emails with a regular express post/get with html files... but I'm not understanding a key part of how to integrate Angular with Express and use it to send an email with Nodemailer. Any help here? Thanks. This is my project structure.
I was answering to the similar question How to make post request from angular to node server
When you post from angular you need to configure cross-origin on your server.
Checkout this github repo https://github.com/kuncevic/angular-httpclient-examples for that matter

Ionic2 : POST request not working

I prepared my server with Node.js (tested with Chrome Postman and everything works fine). It is installed in an Ubuntu 16.04 Server virtual machine and Im testing everything from the host machine (win7). Then I added Ionic2 framework on my virtual machine and start the development of the front-end but I have problem in sending the request POST.
I created a provaider with the following code:
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class MyProvider1 {
data: any;
constructor(public http: Http) {
this.data = null;
}
login(id,pwd){
let headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.post('http://localhost:8080/',
JSON.stringify({
username: id ,
password: pwd
}), {headers: headers})
.subscribe(res => {
console.log(res.json());
});
}
}
It should be working but when the login function is called, my node.js server logs a strange request:
OPTION / 200 0.348 ms -13
Instead of a POST request. Moreover, in my host chrome browser the console shows the following failure:
XMLHttpRequest cannot load http://localhost:8080/. Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8100' is therefore not allowed
access.
Just for trial I removed the {headers: headers} and the http.post became:
this.http.post('http://localhost:8080/',
JSON.stringify({
username: id ,
password: pwd
}))
.subscribe(res => {
console.log(res.json());
});
In this way Morgan logs in my Node.js a POST request BUT the req.body is empty (if I do console.log(req.body) the output will be {} ).
Just in case, I post in the following part of my server Node.js code:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var morgan = require('morgan');
var mongoose = require('mongoose');
//------------------------------------
//Configuration
//------------------------------------
var config = require('./config.js');
var port = process.env.PORT || config.SERVICE_PORT;
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
//------------------------------------
//Routes
//------------------------------------
app.use('/admin', require('./app/routes/admin.js'));
app.use('/', require('./app/routes/guest.js'));
app.use('/chat', require('./app/routes/chat.js'));
//------------------------------------
//Server Start
//------------------------------------
mongoose.connect(config.database);
app.listen(port);
console.log('server start at port ' + port);
And my /app/routes/guest.js contains the following code:
...
router.route('/')
.get(function(req,res){
res.end('Welcome');
})
.post(function(req,res){
UsersManager.login(req.body.username,req.body.password,function(err,user){
if(err) throw err;
if(!user){
res.json({
success: false,
message: Const.notificationTokenAccessNOK
});
}else{
var token = TokenManager.createToken(user);
res.json({
success: true,
message: Const.notificationTokenAccessOK,
token: token
});
}
});
});
module.exports = router;
You can not perform network request(atleast not directly) from your ionic2 code while testing it in chrome browser.
But if you want to, You can put proxy in ionic.config.json file as followed:
{
"proxies": [{
"path": "/localhost/",
"proxyUrl": "http://localhost:8080/"
}]
}
then you can perform post request as followed :
this.http.post('/localhost/',
JSON.stringify({
username: id ,
password: pwd
}))
.subscribe(res => {
console.log(res.json());
});

Resources