I created few functions in the same index.js file, which is sendEmail
, sendEmailByDbStatusChange
and sendEmailConfirmation
.
sendEmail
- To be call via HTTP/API
sendEmailByDbStatusChange
- listening to DB while value change, but the action is hardcoded
sendEmailConfirmation
- Listing to DB while value change, the action subject to the snapshot.
Below is my codes:
const functions = require('firebase-functions');
const nodemailer = require('nodemailer');
const gmailEmail = functions.config().gmail.email;
const gmailPassword = functions.config().gmail.password;
const mailTransport = nodemailer.createTransport({
service: 'gmail',
auth: {
user: gmailEmail,
pass: gmailPassword,
},
});
// Sends an email confirmation when a user changes his mailing list subscription.
exports.sendEmail = functions.https.onRequest((req, res) => {
if (req.body.subject === undefined || req.body.recipient === undefined) {
// This is an error case, as "message" is required.
//res.status(400).send('subject/body/recipient is missing!');
return false
} else {
const mailSubject = req.body.subject;
const mailHtmlBody = req.body.htmlBody;
const mailRecipient = req.body.recipient;
const mailOptions = {
from: '"Food Ninja." <[email protected]>',
to: mailRecipient,
subject: mailSubject,
html: mailHtmlBody
};
//res.status(200).send('Success: ' + mailSubject + ' to ' + mailRecipient);
return mailTransport.sendMail(mailOptions)
.then(() => {
console.log(`${mailSubject}subscription confirmation email sent to: `, mailRecipient)
return res.status(200).send('Success: ' + mailSubject + ' to ' + mailRecipient)
})
.catch((error) => console.error('There was an error while sending the email:', error));
}
});
exports.sendEmailByDbStatusChange = functions.database.ref('/users/{uid}').onWrite((event) => {
//const snapshot = event.data;
//const val = snapshot.val();
//if (!snapshot.changed('subscribedToMailingList')) {
// return null;
//}
const mailSubject = 'Sending email with Cloud Function - by DB onWrite Trigger';
const mailHtmlBody = '<h1>Hello Jerry</h1><p>If you receiving this means that you have successfully deployed a customized firebase function</p><p>Be Happy!<br><br>Food Ninja Team</p>';
const mailRecipient = '[email protected]';
const mailOptions = {
from: '"Food Ninja." <[email protected]>',
to: mailRecipient,
subject: mailSubject,
html: mailHtmlBody
};
//const subscribed = val.subscribedToMailingList;
// Building Email message.
//mailOptions.subject = subscribed ? 'Thanks and Welcome!' : 'Sad to see you go :`(';
//mailOptions.text = subscribed ? 'Thanks you for subscribing to our newsletter. You will receive our next weekly newsletter.' : 'I hereby confirm that I will stop sending you the newsletter.';
return mailTransport.sendMail(mailOptions)
.then(() =>
console.log(`${mailSubject}subscription confirmation email sent to: `, mailRecipient)
//return res.status(200).send('Success: ' + mailSubject + ' to ' + mailRecipient)
)
.catch((error) => console.error('There was an error while sending the email:', error));
});
exports.sendEmailConfirmation = functions.database.ref('/users/{uid}').onWrite((event2) => {
console.log(event2)
console.log(event2.val())
console.log(event2.val().data)
console.log(event2.data)
console.log(event2.data.val())
const snapshot = event2.data;
console.log(snapshot)
const val = snapshot.val();
console.log(val)
if (!snapshot.changed('subscribedToMailingList')) {
return null;
}
const mailOptions = {
from: '"Spammy Corp." <[email protected]>',
to: val.email,
};
const subscribed = val.subscribedToMailingList;
// Building Email message.
mailOptions.subject = subscribed ? 'Thanks and Welcome!' : 'Sad to see you go :`(';
mailOptions.text = subscribed ? 'Thanks you for subscribing to our newsletter. You will receive our next weekly newsletter.' : 'I hereby confirm that I will stop sending you the newsletter.';
return mailTransport.sendMail(mailOptions)
.then(() => console.log(`New ${subscribed ? '' : 'un'}subscription confirmation email sent to:`, val.email))
.catch((error) => console.error('There was an error while sending the email:', error));
});
My problem is, after i deploy the code to firebase function, the console shows that the sendEmailConfirmation
unable to execute smoothly due to event2.val
is not a function.
My current code combined with my customize code and the original code, which sendEmailConfirmation
is the original code. When run the original code independently it did work (original was event
instead of event2
for the snapshot).
Please advise.
Cloud Firestore function triggersTriggered when a document is written to for the first time. Triggered when a document already exists and has any value changed. Triggered when a document with data is deleted. Triggered when onCreate , onUpdate or onDelete is triggered.
Cloud Functions for Firebase is a serverless framework that lets you automatically run backend code in response to events triggered by Firebase features and HTTPS requests. Your JavaScript or TypeScript code is stored in Google's cloud and runs in a managed environment.
With Cloud Functions you write simple, single-purpose functions that are attached to events emitted from your cloud infrastructure and services. Your Cloud Function is triggered when an event being watched is fired.
It looks like you updated to v1.0 of the Firebase SDK for Cloud Functions, but didn't upgrade your code to match.
The entire process is explained in this documentation page. Right now you're being hit by the changes in database triggers, which shows that:
Event data now a DataSnapshot
In earlier releases,
event.data
was aDeltaSnapshot
; now in v 1.0 it is aDataSnapshot
.For
onWrite
andonUpdate
events, thedata
parameter hasbefore
andafter
fields. Each of these is aDataSnapshot
with the same methods available inadmin.database.DataSnapshot
. For example:Before (<= v0.9.1)
exports.dbWrite = functions.database.ref('/path').onWrite((event) => { const beforeData = event.data.previous.val(); // data before the write const afterData = event.data.val(); // data after the write });
Now (v1.0.0)
exports.dbWrite = functions.database.ref('/path').onWrite((change, context) => { const beforeData = change.before.val(); // data before the write const afterData = change.after.val(); // data after the write });
According to that example, you'll need something along these lines:
exports.sendEmailConfirmation = functions.database.ref('/users/{uid}').onWrite((change, context) => {
const snapshot = change.after;
const val = snapshot.val();
console.log(val)
if (!snapshot.changed('subscribedToMailingList')) {
return null;
}
const mailOptions = {
from: '"Spammy Corp." <[email protected]>',
to: val.email,
};
const subscribed = val.subscribedToMailingList;
// Building Email message.
mailOptions.subject = subscribed ? 'Thanks and Welcome!' : 'Sad to see you go :`(';
mailOptions.text = subscribed ? 'Thanks you for subscribing to our newsletter. You will receive our next weekly newsletter.' : 'I hereby confirm that I will stop sending you the newsletter.';
return mailTransport.sendMail(mailOptions)
.then(() => console.log(`New ${subscribed ? '' : 'un'}subscription confirmation email sent to:`, val.email))
.catch((error) => console.error('There was an error while sending the email:', error));
});
Since version 1.0.0 of the firebase-functions module, database onWrite events now deliver a Change object rather than a DataSnapshot object as the first parameter. You can read about all the breaking changes in 1.0.0 in the documentation. You should use this change object instead to choose if you want to examine the contents of the database before or after the change that invoked it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With