0
votes

i am trying to send a mail through nodemailer with Firebase functions. The data for the mail will be supplied from the form but i get this errors

Access to XMLHttpRequest at 'my-firebase-functions' from origin 'my-angugular-web-app' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

this is my Firebase functions

app.use((req, res, next) => {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', 'https://stanleyogbonna-5228d.web.app');
    res.setHeader('Access-Control-Allow-Origin', 'https://stanleyogbonna-5228d.firebaseapp.com');

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,Content-Type');

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader('Access-Control-Allow-Credentials', true);

    // Pass to next layer of middleware
    next();
});

//to make it work you need gmail account
const gmailEmail = functions.config().gmail.login;
const gmailPassword = functions.config().gmail.pass;
admin.initializeApp();

app.post('/visitor/contact', (req, res, next) => {

    //transporter is a way to send your emails
    const transporter = nodemailer.createTransport({
        service: 'gmail',
        auth: {
            user: gmailEmail,
            pass: gmailPassword
        }
    });

    const mailOptions = {
        from: gmailEmail,
        to: req.body.email,
        subject: 'Full stack developer',
        html: `<h1 style="color:blue;">Welcome ${req.body.firstName}</h1>
               <p style="font-size:25px;">Thank you very much for contacting me. i hope you are 
having a great time where ever you may be.</p>
            <p style="font-size:25px;">I am a full stack developer by training and i am available at the moment for a MEAN stack job That will challenge me to be better.</p>
            <p style="font-size:23px;">Thanks ${req.body.firstName}</p>`
    };

    transporter.sendMail(mailOptions);
})


// catch 404 and forward to error handler
app.use((req, res, next) => {
  next(createError(404));
});

// error handler
app.use((err, req, res, next) => {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

exports.app = functions.https.onRequest(app);
1
It will probably be easier if you use the cors middleware to handle this. expressjs.com/en/resources/middleware/cors.htmlDoug Stevenson
In your cors middleware, check for request method OPTIONS and send 204 with res.sendStatus(204) after setting the header. Browsers send an OPTIONS request for checking cors.Abrar Hossain

1 Answers

0
votes

You should use cors package to solve CORS issue. In your node, please setup cors. I can show you my firebase cloud function of sending mail that is using cors. I used sendgrid instead of node mailer by the way. I am gonna show how you should implement cors wrapping your functions by showing my code as I am usually using this way to pack my functions with cors.

exports.sendEmail = functions.https.onRequest((req, res) => {
  if (!req.body) return res.sendStatus(400);
  return cors(req, res, () => {
    var to = req.body.to;
    var from = req.body.from;
    var sender_name = req.body.sender_name;
    var message = req.body.message;
    var pkgname = req.body.pkgname;
    var html = "<h2>" + sender_name + "</h2>" + message;
    const sgMail = require("@sendgrid/mail");

    const subject = "Pre registration - " + pkgname + " - " + sender_name;
    sgMail.setApiKey(
      "sendgrid api key"
    );
    const msg = {
      to: to,
      from: from,
      subject: subject,
      html: html,
    };
    sgMail.send(msg, (sendError, sendRes) => {
      if (sendError) return res.status(500).send(sendError);
      else return res.status(200)(sendRes);
    });
  });
});

FYI sendgrid is free!