skip to Main Content

i’m trying to find an efficient way to get an email with user changes to their profile using Firebase Cloud functions and Javascript. A user profile has over 20 fields and i need an easy way of seeing user changes alone, not the entire profile.

I used to email the before and after of the profile but that’s alot of code and its not easy to tell what changed.

My code:

exports.profileUpdateEmail = functions.firestore
  .document(`profiles/{profile}`)
  .onUpdate(async (changes) => {
    const oldProfile = changes.before.data();
    const newProfile = changes.after.data();

    const profileInfo = [
      "userName",
      "name",
      "email"...
    ];

      profileInfo.map(async (info) => {
        if (oldProfile.info !== newProfile.info) {
          try {
            const mailOptions = {
              from: ` "Admin" ${process.env.REACT_OUTGOING_EMAIL}`,
              to: `${process.env.REACT_OUTGOING_EMAIL}`,
              subject: `Professional Profile Update of ${oldProfile.userName}`,
              html: `<h1>Profile Changes</h1>
                                     <p>
                                        <b>UserID: </b>${oldProfile.user}<br>
                                     </p>
                                     <p>
                                       <b>${info}</b>
                                       <b>Before: ${oldProfile.info}
                                       <b>After: ${newProfile.info}
                                     </p>`,
            };
            await transporter.sendMail(mailOptions);
            console.log("Profile Update Email Sent!");
            return null;
          } catch (error) {
            console.log("Error from sending mail: ", error);
            return null;
          }
        }
      })
  });

When i run this code, no email comes through and GCP logging says severity: DEBUG.

  1. This function will send an email for every field that’s changed by a user so if a user makes 5 changes, that’s 5 emails. How do i add on to the same email so that 5 changes made at once to a profile results in just one email?

2

Answers


  1. As suggested by @Frank van Puffelen in this Stackoverflow Link it is not possible to get the mail for each update in the user profile.

    This isn’t possible in Cloud Functions, as there’s no trigger when the user object changes.

    Having a trigger when the user profile changes would be a useful addition to Cloud Functions, so I recommend you file a feature request for it.

    The only workaround is to detect the emailVerified status client-side, call a callable or HTTPS Cloud Function with the ID token, verify that ID token, and then store the emailVerified value to Firestore from there.

    Also have a look at this Stackoverflow Link for reference.

    Login or Signup to reply.
  2. The following should do the trick.

    exports.profileUpdateEmail = functions.firestore
      .document(`profiles/{profile}`)
      .onUpdate(async (changes) => {
        try {
          const oldProfile = changes.before.data();
          const newProfile = changes.after.data();
    
          const profileInfo = ["userName", "name", "email"];
    
          // Check if we need to send an email
          let emailToBeSent = false;
          profileInfo.forEach((elem) => {
            if (oldProfile.elem !== newProfile.elem) emailToBeSent = true;
          });
    
          if (emailToBeSent) {
            const mailOptions = {
              from: ` "Admin" ${process.env.REACT_OUTGOING_EMAIL}`,
              to: `${process.env.REACT_OUTGOING_EMAIL}`,
              subject: `Professional Profile Update of ${oldProfile.userName}`,
              html: `<h1>Profile Changes</h1>
                                       <p>
                                          <b>UserID: </b>${oldProfile.user}<br>
                                       </p>
                                       <p>
                                         <b>${info}</b>
                                         <b>Before: ${oldProfile.info}
                                         <b>After: ${newProfile.info}
                                       </p>`,
            };
            await transporter.sendMail(mailOptions);
            console.log("Profile Update Email Sent!");
          }
          return null;
        } catch (error) {
          console.log("Error from sending mail: ", error);
          return null;
        }
      });
    

    Note that you could use the Lodash library to compare the elements of the two oldProfile and newProfile Objects, see https://stackoverflow.com/a/76463834/3371862.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search