Firebase Functions cannot get request values sent from a simple contact form in Angular9

Tags: , , , ,



I am developing a simple contact form by using Angular9 + Firebase. I have no idea how to get the values from the contact form in the Firebase Function.

I tried it in many ways, but I always get the “undefined” value. The following is my code. Please give me the solution if anybody knows how to do. Thank you.

Frontend

import { AngularFireFunctions } from '@angular/fire/functions';
 constructor(
    private angularFireFunctions: AngularFireFunctions
  ) {}
submitContact(e: Event) {
    e.preventDefault();
      // Send Email Setup
      const contactJson = JSON.stringify(this.contact);
      const mailer = this.angularFireFunctions.httpsCallable('sendMail');
      mailer(contactJson).subscribe(
        (resp) => {
          console.log({ resp });
        },
        (err) => {
          console.error({ err });
        }
      );
      return;
}

When the submit button is clicked, contactJson looks like this:

{"name":"Your Name","email":"youremailaddress@gmail.com","message":"Hello This is your message"}

Firebase Functions – index.ts

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import * as nodemailer from 'nodemailer';
const cors = require('cors')({ origin: true });
admin.initializeApp();

const transporter = nodemailer.createTransport({
  host: 'Your Host',
  port: 465,
  secure: true,
  auth: {
    user: 'Your Email Account',
    pass: 'Your Password',
  },
});

export const sendMail = functions.https.onRequest((request, response) => {
  const name = request.body.name;
  const email = request.body.email;
  const message = request.body.message;
  return cors(request, response, () => {

    const text = `
          Name - ${name}
          Email - ${email}
          Message - ${message}`;

    const mailOptions = {
      from: 'Your Email Address', 
      to: 'Customers Email Address',
      subject: 'We received your inquiery',
      text: text,
    };

    transporter.sendMail(mailOptions, (erro, info) => {
      console.info(erro, info);
      if (erro) {
        response.send({ error: 'error' });
      }
      response.send({ data: 'success' });
    });
  });
});

The following is the email body I receive. Each value is “undefined”.

Name - undefined Email - undefined Message - undefined

In the end of the process, the google chrome console get the success message

{resp: "success"}

Version Info

Angular CLI: 9.0.7
Node: 10.15.3     
OS: win32 x64     

Angular: 9.0.7    
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, router
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.7
@angular-devkit/build-angular     0.900.7
@angular-devkit/build-optimizer   0.900.7
@angular-devkit/build-webpack     0.900.7
@angular-devkit/core              9.0.7
@angular-devkit/schematics        9.0.7
@angular/fire                     6.0.2
@ngtools/webpack                  9.0.7
@schematics/angular               9.0.7
@schematics/update                0.900.7
rxjs                              6.5.5
typescript                        3.7.5
webpack                           4.41.2

Answer

The way you’re gathering the information only works for the Content-Type of application/json, so first to determine if you’re indeed sending this specific content type, you can do that with request.get('content-type'):

export const sendMail = functions.https.onRequest((request, response) => {
    response.send(req.get('content-type'));
)};

Or by using this example on the documentation that emcompasses almos all types of HTTP requests:

const escapeHtml = require('escape-html');

/**
 * Responds to an HTTP request using data from the request body parsed according
 * to the "content-type" header.
 *
 * @param {Object} req Cloud Function request context.
 * @param {Object} res Cloud Function response context.
 */
exports.helloContent = (req, res) => {
  let name;

  switch (req.get('content-type')) {
    // '{"name":"John"}'
    case 'application/json':
      ({name} = req.body);
      break;

    // 'John', stored in a Buffer
    case 'application/octet-stream':
      name = req.body.toString(); // Convert buffer to a string
      break;

    // 'John'
    case 'text/plain':
      name = req.body;
      break;

    // 'name=John' in the body of a POST request (not the URL)
    case 'application/x-www-form-urlencoded':
      ({name} = req.body);
      break;
  }

  res.status(200).send(`Hello ${escapeHtml(name || 'World')}!`);
};

The only type that seems to be missing is the case of Multipar-Form, this specific type could be done with this example on the documentation



Source: stackoverflow