I have a contact form and am trying to use the values to send an email to myself. The server is receiving the req.body and it appears in the console, however, my nodemailer file is unable to use the data. I get a status code "Need at least one of 'text' or 'html' parameters specified..." Both mail.js and server.js are in the root directory and I pass the data to server.js using jQuery then module.exports mail.js to server.js but somewhere in the exchange the client side data is not getting into the object I created in mail.js even though it only gets invoked in server.js.
Here is what is in my mail.js minus the sensitive info:
const nodemailer = require("nodemailer");
const mailGun = require("nodemailer-mailgun-transport");
const auth = {
auth: {
api_key: "...",
domain: "..."
}
};
const transporter = nodemailer.createTransport(mailGun(auth));
const sendMail = (name, subject, email, phone, message, cb) => {
const mailOptions = {
from: email,
to: "...", // TODO: the receiver email has to be authorized for the free
tier
name,
phone,
subject,
message
};
transporter.sendMail(mailOptions, function (err, data) {
if (err) {
cb(err, null);
console.log("error occurs");
console.log(err)
} else {
cb(null, data);
console.log("Message sent");
}
});
};
newFunction();
function newFunction() {
module.exports = sendMail;
}
Here is my HTML and my server.js:
// Chunk 1
const express = require('express');
const path = require('path');
const sendMail = require('./mail');
const log = console.log;
const app = express();
const PORT = 8080;
// Data parsing
app.use(express.urlencoded({
extended: false
}));
app.use(express.json());
//STATIC FOLDER
app.use("/public", express.static(path.join(__dirname, "public")));
// Render home page
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'views', 'index.html'));
});
// field data
app.post('/email', (req, res) => {
const {
name,
subject,
email,
phone,
message
} = req.body;
log('Data: ', req.body);
sendMail(name, subject, email, phone, message, function(err, data) {
if (err) {
res.status(500).json({
message: 'Internal Error'
})
} else {
res.json({
message: "Email sent!!!!"
})
}
});
});
// Error page
app.get('/error', (req, res) => {
res.sendFile(path.join(__dirname, 'views', 'error.html'));
});
// Email sent page
app.get('/email/sent', (req, res) => {
res.sendFile(path.join(__dirname, 'views', 'emailMessage.html'));
});
// Start server
app.listen(PORT, () => log(`Server is starting on PORT, ${PORT}`));
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Contact Me</title>
</head>
<body>
<div class="container">
<h1 class="brand"><span>King</span> Major</h1>
<div class="wrapper animated zoomIn">
<div class="subject-info">
<ul>
<li><i class="fa fa-road"></i>...</li>
<li><i class="fa fa-phone"></i>...</li>
<li><i class="fa fa-envelope"></i>...</li>
<li>
<a class="navbar-brand" href="#home"><img src="../public/images/mstile-
150x150.png" alt="King's Brand Logo"></a>
</li>
</ul>
</div>
<div class="contact">
<h3>Contact Me</h3>
<form method="POST" action="send">
<p>
<label>Name</label>
<input type="text" name="name" id="name">
</p>
<p>
<label>Subject</label>
<input type="text" name="subject" id="subject">
</p>
<p>
<label>Email Address</label>
<input type="email" name="email" id="email">
</p>
<p>
<label>Phone Number</label>
<input type="text" name="phone" id="phone">
</p>
<p class="full">
<label>Message</label>
<textarea name="message" rows="5" id="message"></textarea>
</p>
<p class="full">
<button type="submit" value="Submit">SEND</button>
</p>
</form>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<script>
$("form").on("submit", e => {
e.preventDefault();
const name = $("#name")
.val()
.trim();
const subject = $("#subject")
.val()
.trim();
const email = $("#email")
.val()
.trim();
const phone = $("#phone")
.val()
.trim();
const message = $("#message")
.val()
.trim();
const data = {
name,
subject,
email,
phone,
message
};
$.post('/email', data, function() {
console.log('Server received our data.')
.then(() => {
window.location.href = "/email/sent";
})
.catch(() => {
window.location.href = "/error";
});
});
});
</script>
</body>
</html>
Based on the error message (expecting fields text
or html
to exist) and the general nodemailer docs (which do not include a message
field), it looks like you'd just need to rename your message
field to text
in your mailOptions
object. So you'd have:
const mailOptions = {
from: email,
to: "...", // TODO: the receiver email has to be authorized for the free
tier
name,
phone,
subject,
text: message // <-- Simple change!
};