Reputation: 5039
I'm trying to send some data to Node using React. Here's my React code:
sendMail(e) {
e.preventDefault();
// fetch('/https://uczsieapp-mailer.herokuapp.com/', {
var name = document.getElementById('name').value;
var contactReason = document.getElementById('contactReason').value;
var email = document.getElementById('email').value;
var additionalInfo = document.getElementById('additionalInfo').value;
var body = {
name: name,
contactReason: contactReason,
email: email,
additionalInfo: additionalInfo,
};
body = JSON.stringify(body);
console.log(body);
fetch('http://localhost:4000/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
content: body,
}).then(r => console.log(r)).catch(e => console.log(e));
}
Here's my Node code:
var cors = require('cors');
var app = express();
app.use(cors());
var a = '=';
router.post('/', (req, res, next) => {
console.log('mailing');
console.log(a);
a += '=';
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
host: "smtp.gmail.com", // hostname
auth: {
user: '[email protected]',
pass: 'testgmail'
}
});
console.log(req.body.content);
let mailOptions = {
from: `${req.body.name} ${req.body.email}`, // sender address
to: '[email protected]', // list of receivers
subject: 'Email from UczSieApp contact form', // Subject line
text: 'Hello world ', // plaintext body
html: `
<h4>Imie: ${req.body.name}</h4>
<h4>Email: ${req.body.email}</h4>
<h4>Powod kontaktu: ${req.body.contactReason}</h4>
<p>Wiadomosc: ${req.body.additionalInfo}</p>
`
};
// send mail with defined transport object
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
return console.log(error);
}
console.log('Message sent: ' + info.response);
});
}
);
So as you can see I'm using the cors module, which is supposed to handle all the cors
issues.
But that's not enough. When I get rid of the headers
property passed to fetch()
, the call is being done, but no data is being sent. When I add the headers
, I get the fun
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:4000/. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
error again.
How can I get around it and what am I missing?
I used this answer when writing my code: https://stackoverflow.com/a/42965820/7055769
Upvotes: 3
Views: 2533
Reputation: 5039
Ok there were numerous reasons this didn't work. I'm leaving this answer for the future developers to ease their pain.
This is the method that worked on the client side:
$.ajax({
type: "POST",
url: 'http://localhost:4000/',
data: body,
success: data=>{console.log(data)},
dataType: 'json',
});
Here's my whole server side code:
var express = require('express');
var router = express.Router();
var cors = require('cors');
var app = express();
app.use(cors());
app.options('*', cors());
var a = '=';
router.post('/', (req, res, next) => {
console.log('mailing');
console.log(a);
a += '=';
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
host: "smtp.gmail.com", // hostname
auth: {
user: '[email protected]',
pass: 'testgmail'
}
});
console.log(req.body);
let mailOptions = {
from: `${req.body.name} ${req.body.email}`, // sender address
to: '[email protected]', // list of receivers
subject: 'Email from UczSieApp contact form', // Subject line
text: 'Hello world ', // plaintext body
html: `
<h4>Imie: ${req.body.name}</h4>
<h4>Email: ${req.body.email}</h4>
<h4>Powod kontaktu: ${req.body.contactReason}</h4>
<p>Wiadomosc: ${req.body.additionalInfo}</p>
`
};
// send mail with defined transport object
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
return console.log(error);
}
console.log('Message sent: ' + info.response);
});
}
);
module.exports = router;
So in my case I had to add these:
app.use(cors());
app.options('*', cors());
No idea why, but it just breaks without the app.options('*', cors());
parameter. If someone knows a better answer to this, and/or sees any security flaws please leave a comment and let me know. Thank you everybody once more for all the help!
Upvotes: 1
Reputation: 870
You mind trying this as follow, this should solve the problem :
app.use(function (req, res, next) {
//set headers to allow cross origin requestt
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
Upvotes: 1
Reputation: 1590
It turns out that CORS only allows some specific content types.
The only allowed values for the Content-Type header are:
The origin parameter specifies a URI that may access the resource. The browser must enforce this. For requests without credentials, the server may specify "*" as a wildcard, thereby allowing any origin to access the resource.
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
fetch('http://localhost:4000/', {
method: 'POST',
mode: 'cors',
headers: {
'Access-Control-Allow-Origin': '*',
'Accept': 'application/json',
'Content-Type': 'application/json',
},
content: body,
}).then(response => response.json()).then(r => console.log(r)).catch(e => console.log(e));
Upvotes: 4