Making a post request in React + Express + Nodemailer

Hi everyone,

I have been trying to figure this out and everything I try doesn’t work, I’m not too familiar with dealing backend things. I want on submit to make a post request and pass the data to nodemailer then send out a email but right now I get a error saying “Failed to load http://localhost:3001/send: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:3000’ is therefore not allowed access.” Any help would be much appreciated.

const express = require('express');
const bodyParser = require('body-parser');
const nodemailer = require("nodemailer");
const creds = require("./config.js");
const app = express();


app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
   extended: false
}));

app.post('/send', (req, res) => {
  // create reusable transporter object using the default SMTP transport
    let transporter = nodemailer.createTransport({
        host: "smtp.gmail.com",
        port: 587,
        auth: {
        user: creds.USER,
        pass: creds.PASS
        },
        tls: {
            rejectUnauthorized: false
        }
    });

    // setup email data with unicode symbols
    let mailOptions = {
        from: creds.USER, // sender address
        to: 'someone@test.com', // list of receivers
        subject: 'A Postcard For You!', // Subject line
        text: 'Postcard', // plain text body
        html: '<b>From my app</b>' // 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);
    });
});

const PORT = process.env.PORT || 3001;

app.listen(PORT, () => {
  console.log(`App listening on port ${PORT}!`);
});

and here is the function making the post request with axios:

handleSubmit = async(e) => {
       e.preventDefault();
       await axios.post('http://localhost:3001/send', {
        firstName: 'Fred',
        lastName: 'Flintstone'
      })
      .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        console.log(error);
      });

  };

If I’m not mistaken it’s because you haven’t set up your Node.js/Express to accept CORS requests by allowing certain headers, I think this is meant to be how web servers work by default in order to protect them (allowing anyone to do just about anything with your server would be bad!).

Adding this middleware should solve your problem:

app.use((request, response, next) => {
  response.header("Access-Control-Allow-Origin", "*");
  response.header("Access-Control-Allow-Headers", "Content-Type");
  next();
});

Do keep in mind that "*" means any request origin; you could set this to http://localhost:3000, since you are developing locally, to get a feel for how it works. I’m not familiar with how axios work. The second line for allowing the Content-Type header is there so that, well, the Content-Type header can be set; I’m not sure how axios work but you will likely need it given what you are doing.

I hope that’s not too hand-wavy and I hope that helps! :smile:

Thank you! This worked perfectly.