0

I have a contact form which submits data to the Firestore Database. My intention is, that as soon as there's another entry in the collection requests, Firestore shall fire a function via Cloud Function, which contains the configuration for SendGrid, which again is supposed to send the data of this specific entry to an e-mail.

I've also tried to deploy this function, which was successful - but the console shows the following errors, which I reckon won't be the only one:

Cannot read property 'requestId' of undefined

const functions = require('firebase-functions');

const admin = require('firebase-admin');
admin.initializeApp();

const SENDGRID_API_KEY = functions.config().sendgrid.key;

const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(SENDGRID_API_KEY);

exports.firestoreEmail = functions.firestore
  .document('requests/{requestId}')
  .onCreate(event => {

    const requestId = event.params.requestId;

    const db = admin.firestore();

    return db.collection('requests').doc(requestId)
      .get()
      .then(doc => {

        const requestId = event.params.requestId;

        const request = doc.data();

        const msg = {
          to: 'fuh@gmx.net',
          from: 'hello@angularfirebase.com',

          templateId: 'd-',
          substitutionWrappers: ['{{', '}}'],
          substitutions: {
            name: request.name,
            lastname: request.lastname,
            email: request.email,
            package: request.package,
            date: request.date,
            text: request.text
            // and other custom properties here
          }
        };

        return sgMail.send(msg)
      })
      .then(() => console.log('email sent!') )
      .catch(err => console.log(err) )


  });

Edit:

const functions = require('firebase-functions');

const admin = require('firebase-admin');
admin.initializeApp();

const SENDGRID_API_KEY = functions.config().sendgrid.key;

const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(SENDGRID_API_KEY);

exports.request = functions.firestore
  .document('requests/{requestId}')
  .onCreate((snap, context) => {

    const db = admin.firestore();

    return db.collection('requests').doc(requestId)
      .get()
      .then(doc => {

        const requestId = snap.id;

        const request = doc.data();

        const msg = {
          to: 'fuhr@gmx.net',
          from: 'hello@angularfirebase.com',

          templateId: 'd-3cd6b40ad6674f33702107d2',
          substitutionWrappers: ['{{', '}}'],
          substitutions: {
            name: request.name,
            lastname: request.lastname,
            email: request.email,
            package: request.package,
            date: request.date,
            text: request.text
            // and other custom properties here
          }
        };

        return sgMail.send(msg)
      })
      .then(() => console.log('email sent!') )
      .catch(err => console.log(err) )


  });

1 Answers1

1

The .onCreate() method doesn't return event, it returns the snapshot of the object and from it you get the id of the new object.

So in your case, it has to be:

exports.firestoreEmail = functions.firestore.document('requests/{requestId}')
  .onCreate((snap, context) => {

    const requestId = snap.id; // get the id
    const db = admin.firestore();

    return db.collection('requests').doc(requestId)
        .get()
        .then(doc => {
           const request = doc.data();
           const msg = {
             to: 'fuhr@gmx.net',
             from: 'hello@angularfirebase.com',

             templateId: 'd-3cd6b40ad6674f33702107d2',
             substitutionWrappers: ['{{', '}}'],
             substitutions: {
                 name: request.name,
                 lastname: request.lastname,
                 email: request.email,
                 package: request.package,
                 date: request.date,
                 text: request.text
                 // and other custom properties here
             }
         };

         return sgMail.send(msg)
     })
     .then(() => console.log('email sent!') )
     .catch(err => console.log(err) )
  });
Hristo Eftimov
  • 13,845
  • 13
  • 50
  • 77
  • 1
    Just note that `functions.firestore .document('requests/{requestId}') .onCreate(event => {});`is the old syntax, for version < 1.0, see https://firebase.google.com/docs/functions/beta-v1-diff#cloud-firestore – Renaud Tarnec Mar 18 '19 at 14:41
  • Thanks for the help. I've deployed the new code and the errors on Firebase are gone, but still the email won't be send to the "to: ' '" string. –  Mar 18 '19 at 14:49
  • are you trying to send an email to `fuh@gmx.net` or to some dynamic email address got from firestore? – Hristo Eftimov Mar 18 '19 at 15:10
  • @HristoEftimov I‘m trying to send to fuh@gmx.net –  Mar 18 '19 at 15:19
  • @HristoEftimov The following error just showed up: ReferenceError: the event is not defined –  Mar 18 '19 at 15:39
  • you already have a declared `requestId`... remove the `const requestId = event.params.requestId;` in the `then()` method of the get request `db.collection('requests').doc(requestId).get()`. After the previous changes, `event` doesn't exist anymore :) – Hristo Eftimov Mar 18 '19 at 15:58
  • @HristoEftimov Thank's again for your help! Now there's the old error again: ReferenceError: requestId is not defined - you can see my current code in the edit above. –  Mar 18 '19 at 16:22
  • @TimFuhrmann in `db.collection('requests').doc(requestId)` you are passing `requestId` which is declared in the `then()` ... of course that will be undefine. You need to declare it before that... please check my updated post :) – Hristo Eftimov Mar 18 '19 at 16:29
  • @HristoEftimov That definetly helped, the function ended with "ok", but there is still a info: { Error: getaddrinfo ENOTFOUND api.sendgrid.com api.sendgrid.com:443 at errnoException (dns.js:28:10) at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:76:26) code: 'ENOTFOUND', errno: 'ENOTFOUND', syscall: 'getaddrinfo', hostname: 'api.sendgrid.com', host: 'api.sendgrid.com', port: 443 } I think that may be why no email is being send. –  Mar 18 '19 at 16:51
  • I am not sure. For external request you need to turn on the paid plan. See the following post: https://stackoverflow.com/a/42775841 – Hristo Eftimov Mar 18 '19 at 17:50
  • @HristoEftimov I‘ll test it in near future. Thanks for your help. Appreciate it! –  Mar 18 '19 at 21:16