Issue with form submission - Node.js - javascript

I am experiencing an issue with submitting a form on my website. When I fill out the form and click the submit button, nothing happens and I do not see any network requests in the browser console.
The form is supposed to submit to the URL https://example.com/, but it seems that the form is not able to send a POST request to this URL.
I have checked the JavaScript console and there are no error messages, and I have also verified that the form fields have the correct names and that the submit button has the correct type.
I am using a shared hosting plan with PHP 7.3.33, and my website was built with WordPress. Recently, I decided to change the design of my website and I did it with Node.js v18.14.0.
I followed the advice of technical support, and I deployed the app to the server. using the application manager.
Now, the technical support answered me this: "What I can confirm is that it's making a successful POST request to "/" (e.g the same page), however there are no errors". But there is no post at the console, and the message I get always is: "Error al enviar el formulario" (error sending form).
This is my js and form:
const form = document.querySelector('#form');
const spinner = document.querySelector('#spinner');
const formMessage = document.querySelector('#form-message');
form.addEventListener('submit', (event) => {
event.preventDefault();
spinner.style.display = 'block';
formMessage.style.display = 'none';
const formData = new FormData(form);
fetch('/', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
spinner.style.display = 'none';
formMessage.style.display = 'block';
formMessage.textContent = data.message;
form.reset();
})
.catch(error => {
spinner.style.display = 'none';
formMessage.style.display = 'block';
formMessage.textContent = 'Error al enviar el formulario.';
});
});
<form method="post" action="/" id="form">
<div class="row gtr-uniform">
<div class="col-6 col-12-xsmall"><input type="text" name="name" id="name" placeholder="Nombre" /></div>
<div class="col-6 col-12-xsmall"><input type="email" name="email" id="email" placeholder="Email" /></div>
<div class="col-12">
<select id="type" name="type">
<option value="" selected>Selecciona Tipo</option>
</select>
</div>
<div class="col-12">
<select id="make" name="make" disabled>
<option value="" selected>Selecciona Marca</option>
</select>
</div>
<div class="col-12">
<select id="model" name="model" disabled>
<option value="" selected>Selecciona Modelo</option>
</select>
</div>
<div class="col-12">
<select id="year" name="year" disabled>
<option value="" selected>Selecciona Año</option>
</select>
</div>
<div class="col-12"><textarea name="message" id="message" placeholder="Tu mensaje" rows="4"></textarea></div>
<div class="col-12">
<ul class="actions special">
<li><input type="submit" value="Enviar" class="primary" /></li>
</ul>
<div id="spinner" style="display: none;">
<svg class="spinner" width="65px" height="65px" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg">
<circle class="path" fill="none" stroke-width="6" stroke-linecap="round" cx="33" cy="33" r="30"></circle>
</svg></div>
<span id="form-message" style="display: none;">Consulta enviada con éxito</span>
</div>
</div>
</form>
And this is my backend in Node.js:
const path = require('path');
const nodemailer = require('nodemailer');
const bodyParser = require('body-parser');
const sanitizer = require('sanitizer');
const rateLimit = require("express-rate-limit");
const app = express();
app.use('/assets', express.static(path.join(__dirname, 'assets'), {
setHeaders: function (res) {
res.set('Content-Type', 'text/css');
}
}));
app.use('/images', express.static(path.join(__dirname, 'images'), {
setHeaders: function (res, path) {
if (path.endsWith('.jpg')) {
res.set('Content-Type', 'image/jpeg');
} else if (path.endsWith('.png')) {
res.set('Content-Type', 'image/png');
}
}
}));
app.use('/assets/css/images', express.static(path.join(__dirname, 'assets/css/images')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// create a rate limiter middleware
const submissionLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: "Too many submissions from this IP, please try again later"
});
// apply the rate limiter middleware to the / endpoint
app.use('/', submissionLimiter);
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.post('/', (req, res) => {
const name = sanitizer.sanitize(req.body.name);
const email = sanitizer.sanitize(req.body.email);
const type = sanitizer.sanitize(req.body.type) || 'No especifica';
const make = sanitizer.sanitize(req.body.make) || 'No especifica';
const model = sanitizer.sanitize(req.body.model) || 'No especifica';
const year = sanitizer.sanitize(req.body.year) || 'No especifica';
const message = sanitizer.sanitize(req.body.message);
const transporter = nodemailer.createTransport({
host: 'hydra.vivawebhost.com',
port: 995,
auth: {
user: 'info#calverasparts.com',
pass: 'Diplodocus1986!'
}
});
const mailOptions = {
from: 'calverasparts#gmail.com',
to: 'info#calverasparts.com',
subject: 'Nueva Consulta',
text: `Recibiste una nueva consulta. Nombre: ${name}. Email: ${email}. Tipo: ${type}. Marca: ${make}. Modelo: ${model}. Año: ${year}. Mensaje: ${message}.`
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
console.log(error);
res.status(500).json({ status: 'error', message: 'Error al enviar el correo' });
} else {
console.log('Email sent: ' + info.response);
res.status(200).json({ status: 'success', message: 'Consulta enviada con éxito' });
}
});
});
const port = process.env.PORT || 3000;
console.log(`Server running on port ${port}`); // Add this line
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
I really don't know where is the problem.
Thank you for your help.
Best regards.

change the URL in the JavaScript code to match the correct URL that the form should be submitted to.
In your JavaScript code, change this line:
fetch('/', {})
To:
fetch('https://example.com/', {})

Related

React Contact Form 404 not Found

I'm trying to create a contact form in react with node mailer but Im having the following issue:
Error shown in console on the browser
It says that 404 NOT FOUND but I dont know where is the mistake i have tried changing the listening part of the server file but no luck:
import React from 'react';
import { useState } from 'react';
import './contactForm.css';
import { Footer } from '../../containers';
const FORM_ENDPOINT = "";
const ContactForm = () => {
const [status, setStatus] = useState("Submit");
const handleSubmit = async (e) => {
e.preventDefault();
setStatus("Sending...");
const { name, email, message } = e.target.elements;
let details = {
name: name.value,
email: email.value,
message: message.value,
};
let response = await fetch("http://localhost:3000/contactForm", {
method: 'POST',
headers: {
"Content-type": "application/json;charset=utf-8",
},
body: JSON.stringify(details),
});
setStatus("Submit");
// let result = await response.json();
// alert(result.status);
};
return (
<div className='RO__ContactForm' id='contactForm'>
<div className='RO__ContactForm-title'>
<h3>Contact</h3>
<h1>I'm here to help you level up</h1>
</div>
<div className='RO__ContactForm-content'>
<div className='RO__ContactForm-content_description'>
<p>I'm just on click away to help you take your company
to the next level. Fill in the form to share more
details about the project or your favorite movie.
Either way, I'd love to talk.</p>
<p></p>
</div>
<form
className='RO__ContactForm-content_form'
action = {FORM_ENDPOINT}
onSubmit = {handleSubmit}
method = 'POST'
target='_blank'
>
<div className='RO__ContactForm-content_form_name'>
<div className='RO__ContactForm-content_form_nameTitle'>
<h5>What's your name?</h5>
</div>
<input
className='RO_ContactForm-content_form_nameInput'
type= 'text'
id='name'
name='name' required
/>
</div>
<div className='RO__ContactForm-content_form_email'>
<div className='RO__ContactForm-content_form_emailTitle'>
<h5>Your email</h5>
</div>
<input
className='RO__ContactForm-content_form_emailInput'
type='email'
id='email['
name='email' required
/>
</div>
<div className='RO__ContactForm-content_form_info'>
<div className='RO__ContactForm-content_form_infoTitle'>
<h5>What can I help you with?</h5>
</div>
<textarea
className='RO__ContactForm-content_form_infoContent'
id='message'
name='message' required
/>
</div>
<div className='RO__ContactForm-content_form_button'>
<button type='submit'>{status}</button>
</div>
</form>
</div>
<div className='RO__ContactForm-footer'>
<Footer />
</div>
</div>
)
}
export default ContactForm
and here is the server file that I use to initialize the server to send the email. That file is made for the contact form front end, and the following file (server.js) its the following;:
const express = require("express");
const router = express.Router();
const cors = require("cors");
const nodemailer = require("nodemailer");
const app = express();
app.use(cors());
app.use(express.json());
app.use('/', router);
app.listen(3000, () => console.log("Server Running"));
const contactEmail = nodemailer.createTransport({
service: "Hotmail",
auth: {
user: '*************#hotmail.com',
pass: '************',
},
});
contactEmail.verify((error) => {
if(error){
console.log(error);
}
else{
console.log("Ready to Send");
}
});
router.post("/contactForm", (req, res) => {
const name = rew.body.name;
const email = req.body.email;
const message = req.body.message;
const mail = {
from: name,
to: 'invariant.rafael.3096#getDefaultNormalizer.com',
subject: 'Contact Form Submission',
hmtl: '<p>Name: ${name} </p> <p>Email: ${email}</p> <p>Message: ${message}</p>',
};
contactEmail.sendMail(mail, (error) => {
if(error){
res.json({ status: 'Error'});
}
else{
res.json({ status: 'Message Sent' });
}
});
});
React typically hosts on port 3000. Change the express server to run on a different port: app.listen(CHANGEME, () => console.log("Server Running"));
If that doesn't work try making some fetch requests somewhere else e.g. https://api.publicapis.org/entries which is a free testing API. Then you will know whether the problem is with your server or not.

Contact form using nodemailer is not working

I have created a contact form and trying to use nodemailer to send the message to my email, but not sure where is the issue.
I created a server.js and put it in the main folder while Mailer.js that contain the form in components
I am not sure how the server know that I want to use the form
this is my first project on React and I think I still don't understand some basics of React
const express = require('express');
const bodyParser = require('body-parser');
const exphbs = require('express-handlebars');
const path = require('path');
const nodemailer = require('nodemailer');
const app = express();
// View engine setup
app.engine('handlebars', exphbs());
app.set('view engine', 'handlebars');
// Static folder
app.use('/public', express.static(path.join(__dirname, 'public')));
// Body Parser Middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.get('/', (req, res) => {
res.render('contact');
});
app.post('/send', (req, res) => {
const output = `
<p>You have a new contact request</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>
`;
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL, // generated ethereal user
pass: process.env.PASSWORD // generated ethereal password
},
tls:{
rejectUnauthorized:false
}
});
// setup email data with unicode symbols
let mailOptions = {
from: process.env.EMAIL, // sender address
to: email, // list of receivers
subject: 'Node Contact Request', // Subject line
text: 'Hello world?', // plain text body
html: output // html body
};
// send mail with defined transport object
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
res.render('contact', {msg:'Email has been sent'});
});
});
app.listen(3000, () => console.log('Server started...'));
This is the form
import React from 'react';
import "./Mailer.scss";
const Mailer = () =>{
return (
<div className="container">
<div className="section ContactPage">
<div className="ContactPage-banner">
<h1 className="ContactPage-banner__title">Contact Us</h1>
</div>
<div className="ContactPage-content">
<form method="POST" className="form" action="send">
<div className="row">
<label className="labels">Name</label>
<input type="text" name="name" className="input"/>
</div>
<div className="row">
<label className="labels">Email</label>
<input type="email" name="email" className="input"/>
</div>
<div className="row">
<label className="labels">Message</label>
<textarea name="message" rows='4' className="input"/>
<input type="submit" value="Send"/>
</div>
</form>
</div>
</div>
</div>
);
};
export default Mailer;
this is what I get when I click on SEND
From what I could gather, you're posting to the wrong URL.
In your server app, you create a post handler for /send
However, in your React App, you post to /xxxxx/send (You obscured the xxxxx part)
I advise that you replace your
<form method="POST" className="form" action="send">
With
<form method="POST" className="form" action="http://127.0.0.1:3000/send">
And try again

Getting string value of required input (html) on cheerio

I'm trying to do a notify function in my website. The button his on HTML (client side) and on press calls a node js function to execute a python script that sends an e-mail to myself (tested and working).
This is my code on the client side (index.html)
<body>
...
<div class="form-popup" id="myForm">
<form class="form-container" name="form-owner">
<h1>Notify Owner</h1>
<label><b>Name</b></label>
<input id="name" style="width:90%" type="text" placeholder="Enter your name" required>
<label><b>Message</b></label>
<input id="context" style="width:90%" type="text" placeholder="Enter Reason" required>
<button type="submit" class="btn" onclick="notifyOwner()">Submit</button>
<button type="button" class="btn cancel" onclick="closeForm()">Close</button>
</form>
</div>
</div>
...
The code on the server side (app.js)
const express = require('express');
const child_process = require('child_process')
const app = express()
const cheerio = require('cheerio');
const port = 80
'use strict';
var request = require('request');
...
app.post("/api/notify", async (req, res) => {
try{
const $ = cheerio.load('<input id="name" style="width:90%" type="text" placeholder="Enter your name" required>');
var subject = $('[id=name]').text();
var body = "ok";
child_process.execSync('python3 sendEmail.py ' + subject + " " + body);
}catch(error){
console.error(error);
}
});
The varialbe 'subject' turns out as null and the script is not runned because that argument is missing
I believe there's some confusion here. Cheerio is used to parse and manipulate HTML strings, but that's not what your front end code is sending. The string you're telling Cheerio to manipulate has no relationship to the request form payload in any way, nor is it a necessary tool for processing the POST request.
You appear to be using JS to submit JSON or form data to the server (as opposed to an HTML form action). req.body and req.query would contain this parsed payload respectively, depending on how your server is set up.
Here's an example of how you can set this up using JSON. Note that I've promisified the exec function to avoid blocking the event loop with a synchronous subprocess call.
Also, the form name and context don't seem to correspond well with subject and body--I assume you'll make this consistent.
You'll want to escape and properly quote your subprocess argument string as well.
public/index.html:
<!DOCTYPE html>
<html lang="en">
<head><title>Test</title></head>
<body>
<form>
<h1>Notify Owner</h1>
<label>
<b>Name</b>
<input id="name" placeholder="Enter your name" required>
</label>
<label>
<b>Message</b>
<input id="context" placeholder="Enter Reason" required>
</label>
<button type="submit">Submit</button>
</form>
<script>
document.querySelector("form").addEventListener("submit", event => {
event.preventDefault();
const name = event.target.querySelector("#name").value;
const message = event.target.querySelector("#context").value;
fetch("/api/notify", {
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({name, message})
})
.then(res => {
if (!res.ok) {
throw Error(res.statusText);
}
return res.json();
})
.then(data => {
console.log(data);
event.target.reset();
})
.catch(err => console.error(err));
});
</script>
</body>
</html>
server.js:
const {promisify} = require("util");
const exec = promisify(require("child_process").exec);
const express = require("express");
const app = express();
app.use(express.json());
app.use(express.static("public"));
app.post("/api/notify", async (req, res) => {
const {name, message} = req.body; // TODO validate
// do stuff with name and message
console.log(name, message);
try {
//await exec(`python3 sendEmail.py ${subject} ${body}`);
res.json({message: "email sent"});
}
catch (err) {
res.json({error: "failed to send email"});
}
});
app.listen(8000, () => console.log("listening on port 8000"));

Routing issue with express.js and nodemailer

Hi I am attempting to use nodemailer with gmail to create a contact form on my website however, I believe there is a routing issue that is causing the mail to be sent but I cannot mange to fix it.
My about.html page contains the code form below:
<form id="contact" action="/contact" id="contact-form" method="post" role="form">
<h3>Contact Form</h3>
<fieldset>
<input placeholder="Your name" type="text" tabindex="1" id="name" name="name" required autofocus>
</fieldset>
<fieldset>
<input placeholder="Subject" type="text" tabindex="1" id="subject" name="subject" required>
</fieldset>
<fieldset>
<input placeholder="Your Email Address" type="email" tabindex="2" id="email" name="email" required>
</fieldset>
<fieldset>
<textarea placeholder="Type your message here...." tabindex="5" id="message" name="message" required></textarea>
</fieldset>
<fieldset>
<button name="submit" type="submit" id="contact-submit" data-submit="...Sending">Submit</button>
</fieldset>
</form>
And my app.js file that is the node server contains the code
//safe enviroment variables
require('dotenv').config();
//express routing
var express = require("express");
var app = express();
var router = express.Router();
var path = __dirname + '/views/';
app.use(express.static('public'));
router.use(function (req,res,next) {
console.log("/" + req.method);
next();
});
router.get("/",function(req,res){
res.sendFile(path + "index.html");
});
router.get("/about",function(req,res){
res.sendFile(path + "about.html");
});
app.use("/",router);
app.use("*",function(req,res){
res.sendFile(path + "404.html");
});
app.listen(8080, function () {
console.log('Example app listening on port 8080!')
})
//nodemail
const nodemailer = require('nodemailer')
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({extended: true}))
//collecting gmail username and password
const GMAIL_USER = process.env.GMAIL_USER
const GMAIL_PASS = process.env.GMAIL_PASS
// POST route from contact form
app.post("/contact", (req, res) => {
async function main() {
// Instantiate the SMTP server
const smtpTrans = nodemailer.createTransport({
service: 'Gmail',
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
user: GMAIL_USER,
pass: GMAIL_PASS
}
})
// Specify what the email will look like
const mailOpts = {
from: GMAIL_USER , // This is ignored by Gmail
to: GMAIL_USER,
subject: `${req.body.subject}`,
text: `${req.body.name} (${req.body.email}) says: ${req.body.message}`
}
// Attempt to send the email
smtpTrans.sendMail(mailOpts, (error, response) => {
if (error) {
console.log('error email')
res.sendFile(path + "index.html"); // Show a page indicating failure
}
else {
console.log('email sent')
res.sendFile(path + "about.html"); // Show a page indicating success
}
})
}
})
However when clicking the submit button the form it send me to the 404 page indicating that the form cannot find the post function since if it could then it would not redirect me to the post function. I have also added echos into the function to print to console if it is called which does not happen. I have tried changing the routing but can't seem to get it to work.

How to send parameters from a form using Express and Node.js

Sorry for the English, i am Brazilian and I do not know how to write very well.
I am trying to send by post the data of a form using Express:
index.html
<form action="insert" method="post">
<p><h4> Title </h4> <input type="text" name="title" id="title" size="40" maxlength="30" placeholder="Name of task"/> </p>
<p><h4>Description</h4> <textarea name="description" id="description" cols="50" rows="3" placeholder="description of task"></textarea> </p>
<p>
<h4>Grade</h4>
<input type="radio" name="urgency" value="2"> 2
<input type="radio" name="urgency" value="1" checked> 1
<input type="radio" name="urgency" value="0"> 0
</p>
<p>
<h4>How?</h4>
<select name="taskType" id="select">
<option value="2"> N* </option>
<option value="1"> Hour </option>
<option value="0"> Minute </option>
</select>
<input type="text" name="repeats" id="options" size="40" maxlength="5" placeholder="NX?"/> </p>
</p>
<p><button type="submit"> Submit </button></p>
</form>
app.js
const express = require('express');
const bodyParser = require('body-parser');
const mysql = require('mysql');
const app = express();
app.use(bodyParser.urlencoded({ extended: true }))
const db = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database : 'metas'
});
db.connect( (err) => {
if(err) throw err;
console.log('MySQL conected...');
});
app.get('/select', (req, res) => {
let sql = "SELECT * FROM tasks";
db.query(sql, (err, result) => {
if(err) throw err;
res.send(result);
})
})
app.post('/insert', (req, res) => {
let post =
{title: req.body.title,
description: req.body.description,
grau: req.body.urgency,
tipoRealizacao: req.body.taskType,
repeticoes: req.body.repeats
}
let sql = 'INSERT INTO tasks SET ?';
let query = db.query(sql, post, (err, result) => {
if(err) throw err;
res.send("Post added");
})
})
app.listen('3000', () => { console.log("Server initiated") } );
I am using mysql to store tasks, moreover I am using wampp on port 3306, but when I submit the form I have the error:
Not Found
The requested URL /MetaSite/public/insert was not found on this server.
Apache/2.4.35 (Win64) PHP/7.2.10 Server at localhost Port 80
index.html is in public folder and app.js in src.
Can anyone help me please? I do not know what I am doing wrong. Thank you.
It doesn't look like, based on your code, that your index.html is being hosted by the server javascript. In order for express to be able to handle a post request from that file, the file needs to be referenced and hosted by express. If this is what you are doing and you are just not showing it in your code please tell me but otherwise, this looks like your problem. The way you should do this is:
var path = require('path');
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname + 'public/index.html'));
});
to host the index file at http://localhost:3000/.

Categories