I'm building a contact form using nodemailer
.
To post it I'm using the fetch
API.
But for some reason, I get req.body
as undefined
.
Here's the frontend code:
form.onsubmit = function (e) {
// Stop the regular form submission
e.preventDefault();
const name = document.querySelector("form#contactForm #name").value;
const email = document.querySelector("form#contactForm #email").value;
const textarea = document.querySelector("form#contactForm #textarea").value;
// Collect the form data while iterating over the inputs
var data = {};
data = { name, email, textarea };
console.log(data);
fetch("/mail", {
method: "POST", // or 'PUT'
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
})
.then(async (response) => {
if (response.ok) {
return response.json();
} else {
const resJson = await response.json();
console.log(resJson);
if (typeof resJson.errors === "undefined") {
formStatus.className += " alert-danger";
formStatus.innerText =
"An error occured, Please refresh the page. Or email us at ravchesed@kehilasbelz.be";
return;
}
let ul = document.createElement("ul");
resJson.errors.forEach((err) => {
const li = document.createElement("li");
li.innerText = `${err.msg}: ${err.param} `;
ul.append(li);
console.log(`${err.msg}: ${err.param} `);
});
formStatus.className += " alert-danger";
formStatus.innerText = "";
formStatus.append(ul);
throw response;
}
})
.then((data) => {
console.log("Success:", data);
})
.catch((error) => {
console.error("Error:", error);
});
};
Here's the backend:
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const { check, validationResult } = require("express-validator");
const rateLimit = require("express-rate-limit");
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 10, // limit each IP to 100 requests per windowMs
});
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const mail = express.Router();
// app.post("/mail", (req, res) => {
// console.log(req.body);
// const result = {
// hellop: 5
// };
// res.send(JSON.stringify(result));
// });
mail.post(
"/mail",
// limiter,
[
// username must be an email
check("email").trim().isEmail(),
check("textarea").trim().isLength({ max: 6000 }),
check("name").trim().isLength({ min: 2, max: 20 }),
],
(req, res) => {
console.log(req.body); //undefined
// Finds the validation errors in this request and wraps them in an object with handy functions
const errors = validationResult(req);
if (!errors.isEmpty()) {
console.log(errors); //this returns empty values.
return res.status(422).json({ errors: errors.array() });
}
const mailInfo = {
name: req.body.name,
email: req.body.email,
message: req.body.testarea,
};
main(mailInfo).catch(console.error);
res.json({ success: true });
}
);
const nodemailer = require("nodemailer");
// async..await is not allowed in the global scope, must use a wrapper
async function main(data) {
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: "xxx.xxx.com",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: "email@example.com", // generated ethereal user
pass: "abc123456", // generated ethereal password
},
});
// send mail with defined transport object
let info = await transporter.sendMail(
{
from: '"John Doe 👍" <robot@Doe.dev>', // sender address
to: "Doe@gmail.com", // list of receivers
subject: `📧 Mail from ${data.name}`, // Subject line
html: `
<b>${data.name}, ${data.email}</b><br>
Phone: ${data.phone}<br>
<br>
Message:
<br>
${data.message}
`, // html body
},
function (err, info) {
if (err) console.log(err);
else console.log(info);
console.log("Message sent: %s", info);
}
);
}
module.exports = mail;
Looked at a lot of posts, but this seems to be a different problem.
after looking at everything again I know where my mistake was but don't understand why.
My file structure is like this:
app.js
mail.js
mail.js
was imported to app.js
like this:
//handle mail
const mail = require("./mail");
app.use(mail);
in app.js
I didn't import body-parser
and the middleware because it was already imported in mail.js
.
but looks like for some reason that I also have to import it in app.js
before mail.js
.