0

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

https://medium.com/@binhchung48/create-a-contact-form-with-nodemailer-react-js-and-express-js-7757d41e2448


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.

Jenna
  • 1,159
  • 2
  • 10
  • 16

1 Answers1

0

As per ethereal docs there is no emails will be sent to your email, instead you can view emails here and login with the generated email and password

from ethereal website.

Instead, you can generate a vanity email account right from Nodemailer, send an email using that account just as you would with any other SMTP provider and finally preview the sent message here as no emails are actually delivered

Also you have an error in sendMail function in server.js file

    sendMail({ email, name, text: message })... 

As per nodemailer docs send mail take the below parameters

{
        from: '"Fred Foo " <foo@example.com>', // sender address
        to: 'bar@example.com, baz@example.com', // list of receivers
        subject: 'Hello ✔', // Subject line
        text: 'Hello world?', // plain text body
        html: '<b>Hello world?</b>' // html body
    }

So you have to change your function to be like below

    message = `From : "${name}" <${email}> 
               Message : ${message}
               `;
    sendMail({ from: '"kristoffer78" <kristoffer78@ethereal.email>'  , to : '"Your name" <your@email.com>' , text: message , html: message })... 
Yasser Mas
  • 1,652
  • 1
  • 10
  • 14
  • I've been checking the messages page of Ethereal for new messages, but nothing comes through when I submit the form. I have also updated the sendMail function, and thank you for the clarification. I've edited my original post/JS fiddles to reflect the changes. I feel the issue lies with obtaining the information from the form and sending that information through a POST request with axios, but I'm not 100% sure about that. – Jenna Sep 15 '19 at 16:59
  • Please remove `.js` in `app.post('/contact.js',` to be `app.post('/contact',` – Yasser Mas Sep 15 '19 at 20:22
  • I've deleted `.js` from `app.post('/contact.js',`. All code has been updated and inserted into my question, instead of JS Fiddle – Jenna Sep 15 '19 at 20:27
  • I've been updating my question. It seems like there's an issue with CORS, according to the errors I'm getting from the DevTools console. I'll keep working on it. – Jenna Sep 15 '19 at 21:46