I’m trying to set up a contact form using Nodemailer, Express, and Formik. I’m using React for the front-end. I’m having trouble with the form information being emailed when the submit button is clicked.
I'm using Ethereal email for testing. I'm logged in with my credentials from Ethereal, and checking for new messages on the messages section of their website.
When I fill out my form with test information and click the submit button, I don’t receive an email with the input information. I used to have an alert set up that would pop up in the browser with the form information, so I know the form is taking in the information okay, I’m just having a problem with the information being emailed to me.
I have set server.js
to listen to port 3001. I receive these errors in the Chrome DevTools console after clicking submit:
contact:1
Access to XMLHttpRequest at 'http://localhost:3001/contact' from origin
'http://localhost:3000' has been blocked by CORS policy: Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
contactForm.js:37
Error: Network Error
at createError (createError.js:17)
at XMLHttpRequest.handleError (xhr.js:80)
From these errors, I gather that there's a problem with CORS. For this, I'm going to consult this SO question: No 'Access-Control-Allow-Origin' header is present on the requested resource—when trying to get data from a REST API
I have a feeling there is something wrong with my POST method, or something wrong with my axios configuration (...or both). I also wonder if it has anything to do with Formik and what I'm trying to achieve with it.
In my quest for answers, I’ve found the following information regarding the use of action
and method=“POST”
with Formik forms, but it didn’t help me:
https://github.com/jaredpalmer/formik/issues/556#issuecomment-472158007
I have also followed a few Nodemailer tutorials to a T. These tutorials used plain HTML forms instead of Formik forms, but even when I followed them exactly (using HTML and not Formik), I didn’t receive any of the test messages I had sent through my form. Here are some of the tutorials I consulted so far:
https://tylerkrys.ca/blog/adding-nodemailer-email-contact-form-node-express-app
server.js
const express = require('express');
const app = express();
const port = 3001;
const bodyParser = require('body-parser');
const nodemailer = require('nodemailer');
const cors = require('cors');
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
var appURL = 'http://localhost:3001/contact';
app.all(appURL, function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next()
});
app.post(appURL, (req, res) => {
let transporter = nodemailer.createTransport({
host: 'smtp.ethereal.email',
port: 587,
secure: false,
auth: {
user: 'kristoffer78@ethereal.email',
pass: '3qBsadVVpeaK6dAw26'
},
tls: {
rejectUnauthorized: false
}
});
// verify connection configuration
transporter.verify(function(error, success) {
if (error) {
console.log(error);
} else {
console.log("Server is ready to take our messages");
}
});
const output = `
<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>
`;
let mailOptions = {
from: '"Nodemailer" <kristoffer78@ethereal.email>',
to: 'kristoffer78@ethereal.email',
subject: 'New message from Redux Co. contact form',
text: 'There is a new message',
html: output
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
reject(error)
return
}
resolve(info)
});
});
app.listen(port, function () {
console.log(`Listening on port ${port}...`);
});
contactForm.js
import React from 'react';
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as yup from 'yup';
import axios from 'axios';
const schema = yup.object().shape({
name: yup.string().required('Name required'),
email: yup.string().email().required('Valid email required'),
message: yup.string().min(10).max(600).required('Message required')
});
class ContactForm extends React.Component {
render() {
return (
<div className="contact-form-content">
<Formik
validationSchema={schema}
initialValues={{
name: '',
email: '',
message: ''
}}
onSubmit={(values, { setSubmitting }) => {
alert('Form submitted!');
setTimeout(() => {
// axios POST
const appURL = 'http://localhost:3001/contact'
axios.post(appURL, {
name: values.name,
email: values.email,
message: values.message
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
setSubmitting(false);
}, 400)
}}
>
{({ isSubmitting }) => (
<Form id="contact-form" role="form">
<label for name="name">Name</label>
<Field type="name" name="name" id="name" />
<ErrorMessage name="name" component="span" />
<label for name="email">Email</label>
<Field type="email" name="email" id="email" />
<ErrorMessage name="email" component="span" />
<label for name="message">Message</label>
<Field component="textarea" name="message" id="message" />
<ErrorMessage name="message" component="span" />
<button type="submit" disabled={isSubmitting} >
Submit
</button>
</Form>
)}
</Formik>
</div>
);
}
}
export default ContactForm;
Please let me know if my provided code is sufficient, and I will upload additional files if necessary.