Search code examples
firebaseexpressnodemailer

Firebase functions with nodemailer POST request: Error: Process exited with code 16


I'm running a Firebase cloud function whose purpose is to handle the backend of a "contact me" form. The Express framework is being used for middleware functions. When the submit button is clicked, a POST request is made to the /submit endpoint.

index.js in the functions folder is as below:

const functions = require("firebase-functions");
const admin = require("firebase-admin");
const bodyParser = require("body-parser");
const express = require("express");
const emailRoute = require("./routes/email");

// Initialize Firebase in order to access its services.
admin.initializeApp();

const app = express();

// Automatically allow cross-origin requests.
app.use(cors({ origin: true }));

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

app.use(emailRoute);

// Expose Express API as a single Cloud Function.
exports.app = functions.https.onRequest(app);

The imported router from email.js is as follows:

const nodemailer = require("nodemailer");
const express = require("express");
const router = express.Router();

router.post("/submit", (req, res) => {
  
  const transporter = nodemailer.createTransport({
    service: "gmail",
    auth: {
      user: "email@gmail.com",
      pass: "password",
    },
  });

  const myEmail = {
    to: "myemail@gmail.com",
    subject: `A new message from ${req.body.name}`,
    text: `${req.body.name} sent the following message:
          \n\n ${req.body.message}
          \n\n Senders email: ${req.body.email}`,
  };

  const sendersEmail = {
    to: req.body.email,
    subject: "A copy of your message to me",
    text: `You just sent me the following message:\n\n${req.body.message}`,
  };

  console.log("SUBMIT REQUEST PROCESSING");

  transporter.sendMail(myEmail);
  transporter.sendMail(sendersEmail);

  res.redirect("/#contact");

  console.log("PROCESSING COMPLETE");
});

module.exports = router;

There is no issue when running this in the local environment - the email gets sent to both parties. However, when run in the hosted environment as a Firebase function the following error is thrown: Error: Process exited with code 16 (as displayed in the function logs section of the Firebase console). A previous SO answer indicates an uncaughtException or unhandledRejection.

Before the error, both console.log() statements are logged. Then the function finishes with a 302 status code (as it does when run locally and successfully). After that, there is the unhandled rejection followed by Error: Invalid login and a link to my Google account and a statement "Please log in via your web browser and then try again".

Could this be a Firebase security measure against automated mailing that nodemailer is attempting to execute?


Solution

  • I needed to both enable less secure apps and display unlock captcha on the gmail account, only the former of which I had previously done.

    I also needed to set the gmail.email and gmail.password Google cloud environment variables. This can be done with the following shell command: firebase functions:config:set gmail.email="myusername@gmail.com" gmail.password="secretpassword"

    A great resource I found on this is an official Firebase function sample that utilises Nodemailer, where the above is covered.