NaomiCreate / cnss-app

0 stars 0 forks source link

Adding email sending functionality #38

Open NaomiCreate opened 3 years ago

NaomiCreate commented 3 years ago

Step one: Initialize folders and modules

We used the link: https://firebase.google.com/docs/functions/get-started

npm install -g firebase-tools
firebase login
firebase login --reauth
firebase init firestore
firebase init functions

We decided to implement sending emails first with emulators provided by firebase. And then we'll deploy it. firebase init emulators firebase emulators:start- This is how we will run the emulators

Step two: Adding a new node to a particular route prints a message

index.js:

const functions = require("firebase-functions");
exports.test = functions.database.ref(*********)
    .onWrite((snapshot, context) => {
        //check that onWrite is not onDelete or onUpdate
        const { before, after } = snapshot;  // snapshot contains before and after documents snapshots

        if (before.val()==null) {
            //send email
            functions.logger.info('created event');
            return;
        }
        if (after.val()==null) {
            functions.logger.info('deleted event');
            return;
        }
        else{
            functions.logger.info('update event');
           return;
        }
    });

Step three: Sending an email to a specific user

We will create an .env file that will contain the details of the email from which emails were sent. And in order to use it we will install:

npm install nodemailer --save
npm i dotenv

index.js:

const functions = require("firebase-functions");
const nodemailer = require('nodemailer');
require('dotenv').config()

const {SENDER_EMAIL,SENDER_PASSWORD} = process.env;

exports.test = functions.database.ref(*********)
    .onWrite((snapshot, context) => {
        const { before, after } = snapshot;
        if (before.val()==null) {
            //send email
            const mailTransport = nodemailer.createTransport({
                service: 'gmail',
                auth: {
                  user: SENDER_EMAIL,
                  pass: SENDER_PASSWORD,
                },
              });
            var mailOptions = {
                from: ********,
                to: **********,
                subject: 'Sending Email using Node.js',
                text: 'That was easy!'
              };

            mailTransport.sendMail(mailOptions, function(error, info){
                if (error) {
                  console.log(error);
                } else {
                  console.log('Email sent: ' + info.response);
                }
              });
            functions.logger.info('created event');
            return;
        }
        if (after.val()==null) {
            functions.logger.info('deleted event');
            return;
        }
        else{
            functions.logger.info('update event');
           return;
        }
    });

We checked on the emulator, and we saw that new email is sent only when new alert id is added to : ********* .

NaomiCreate commented 3 years ago

Step 4: Getting the user's ID from the device ID

We learned how to Initialize Cloud Firestore with Initialize on Cloud Functions: https://firebase.google.com/docs/firestore/quickstart:

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

The function we wrote:

async function getUidFromDeviceID(deviceID)
    {
      const uidRef = db.collection('*********').doc(*********);
      const doc = await uidRef.get();
      if (!doc.exists) {
        console.log('getUidFromDeviceID No such document!');
        return null;
      } else {
        console.log('getUidFromDeviceID Document data[*********]:', doc.data()[*********]);
        return doc.data()[*********];//the Uid
      }
    }
NaomiCreate commented 3 years ago

Step 5: Getting the user's email from the user's ID

We pulled out the email to which we want to sent the alert, from firestore .

   const emailRef =  db.collection('*********').doc(uidRef.data()[*********]).collection('*********').get().then((doc)=>{
                  doc.forEach((emailAddress) => {
                    console.log('email=',emailAddress.id);
                   });
   });

Step 6: Sending an alert to the email we achieved in step 5

We succeeded to send an email to the user when a new alert is added to his history in the realtime database.

The code:

exports.test = functions.database.ref("*********")
    .onWrite((snapshot, context) => {
        const { before, after } = snapshot;

        if (before.val()==null) {//New alert created
            functions.logger.info('context.params.device_ID=',context.params.device_ID);
            //Get the user's ID from the device ID:
            const uidReff = db.collection('*********').doc(*********).get().then((uidRef)=>{
              if (!uidRef.exists) {
                console.log('No such document!');
                return null;
              } else {
                console.log('Document data[*********]:', uidRef.data()[*********]);
                //Get the user's email from the user's ID:
                const emailRef =  db.collection('*********').doc(uidRef.data()[*********).collection('*********').get().then((doc)=>{
                  doc.forEach((emailAddress) => {
                    console.log('email=',*********);
                    //Send alert email to the user's email:
                    const mailTransport = nodemailer.createTransport({
                        service: 'gmail',
                        auth: {
                          user: SENDER_EMAIL,
                          pass: SENDER_PASSWORD,
                        },
                      });
                    var mailOptions = {
                        from: 'CNSS <noreply@firebase.com',
                        to: emailAddress.id,
                        subject: 'Sending Email using Node.js',
                        text: 'That was easy!'
                      };
                    mailTransport.sendMail(mailOptions, function(error, info){
                        if (error) {
                          console.log(error);
                        } else {
                          console.log('Email sent: ' + info.response);
                        }
                    });
                    return emailAddress.id;
                  });
                });
              }
            });
            functions.logger.info('created event');
            return;
        }
        if (after.val()==null) {
            functions.logger.info('deleted event');
            return;
        }
        else{
            functions.logger.info('update event');
           return;
        }
    });

Note: We implemented this in the firebase emulator.