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
Related
Using the Following Stack Express,Vue,SQL,Axios
GET request is working fine in postman as well from Axios
POST request created error in both attached screenshots
To make sure the Backend is working fine I have tried sending the Data directly from
<form action="url" method="POST">
it is Working fine and data is storing in the database
I have Tried few workaround like disabling SSL setting in postman and Played with proxy setting Also having CORS enabled in the backend and tried some Allow content and header things. Nothing worked
Not able to figure out the Problem in the POST Request. Please Help
--Request Error in the browser from Axios ----
Axios Browser Error
-postman Error when doing POST Request---
Postman Error
---Backend Index.js file---
// const express = require("express");
"use strict";
import express from "express";
const app = express();
import cors from "cors";
//listening on this port
app.listen(3000);
app.use(cors()); // to get Data from Other Domains
app.get("/", function (req, res) {
res.send("Application Started");
console.log("Application Started");
});
//Routes
app.use("/product", require("./routes/product"));
---product.js routes files---
import express from "express";
const router = express.Router();
import bodyParser from "body-parser";
//Middleware
router.use(bodyParser.urlencoded({ extended: true })); // To Parse the body data
//Importing Main Controller
import conProduct from "../controllers/ConProduct";
//Defining functions as per Routes
router.post("/add", conProduct.add); //Showing all the products
router.get("/get", conProduct.get); //Showing all the products
//Exporting Router
module.exports = router;
---Controller for Product file ConProducts.js ---
import sqlConfig from "../database/dbConfig";
let sql = sqlConfig.mysql_pool;
exports.add = (req, res) => {
console.log(req.body);
const { name, shortDescription, price, discount } = req.body;
let addQuery =
"INSERT INTO products(name,short_description,price,discount) VALUES('" +
name +
"','" +
shortDescription +
"','" +
price +
"','" +
discount +
"');";
sql.query(addQuery, (err, result) => {
if (err) throw err;
console.log(result);
res.send("product uploaded");
});
};
--Frontend axios Request --
let formData = {
name: this.name,
shortDescription: this.shortDescription,
price: this.price,
discount: this.discount,
};
console.log(formData);
axios
.post("/product/add", formData)
.then((res) => console.log(res))
.catch((error) => console.log(error));
I got the Answer I was missing a middleware app.use(bodyParser.json) in index.js and because of that there was no value going into database and thus, there was a network error.
I realized that, you are sending a PUT request to backend but your API controller receiving POST requests. So, Don't they have to be same type of request ?
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
I deployed an app on heroku with angular for the front-end and node(express) as the back-end. On the contact page, I have a form that will be sent via email once the send button is pressed, which then sends the info via HTTP to node for the user inputs to be passed through the node function - I'm using SendGrid addon for the email process to send the email. I tried multiple time, but I just can't get it to work and can't find a tutorial with angular. It worked before with nodemailer on the localhost, but I can't figure it out once it is deployed. Thank you a lot for your time.
node code app.js
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const sgMail = require('#sendgrid/mail');
const port = process.env.PORT || 3000;
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, 'client')));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'client/index.html'));
});
app.post('/client-contact', (req, res) => {
const clientMsg = `
<p> Email sent from your portfolio website</p>
<h3>Contact details</h3>
<ul>
<li>Name ${req.body.name}</li>
<li>Email: ${req.body.email}</li>
</ul>
<h3>Message</h3>
<p>${req.body.message}</p>
`;
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const msg = {
to: 'mrwanzein#outlook.com',
from: 'mrwanzein#outlook.com',
subject: 'Angular portfolio form user response',
html: clientMsg,
};
sgMail.send(msg);
});
app.listen(port, () => {
console.log(`Server is on on port ${port}`);
});
the function that register the user input and then sends it to node (and handles some validations, the interest is the last line) contact.component.ts
sendMail() {
var name = <HTMLInputElement>document.getElementById('inputName'),
email = <HTMLInputElement>document.getElementById('inputEmail'),
msg = <HTMLInputElement>document.getElementById('inputMsg');
var obj = {
name: name.value,
email: email.value,
message: msg.value
}
let validateEmail = () => {
const re = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?
^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])/;
return re.test(email.value);
}
if(!name.value || !email.value || !msg.value || !validateEmail()) {
this.bool = true;
} else {
this.bool = false;
setTimeout(() => {
window.location.reload()
}, 1500);
return this.http.post('https://mrwanzein.herokuapp.com/client-contact', obj).subscribe();
}
}
You need to configure an SMTP server for your application.
The easiest way is with a heroku addin such as mailgun
I fixed it, basically the code is fine, I had to remove the res.send() around sgMail.send(msg) and I forgot to ng build(angular) to update the HTTP address when I changed it. I was pushing changes to the repo without the missing updated code, oh dear... :P
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
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());
});