Cloud Function For Sending Mail On Badge Generation in Badgeyay
The task of badgeyay is to generate badges for events and if the user has provided a large data set, then the system will take time to generate badges and we cannot hold the user on the same page for that time. So instead of showing the user the link of the generated badge on the form, what we can do is that we can send a mail to user with the link of generated badge. However listening for the completion of generated badge from the cloud function is not possible, as cloud functions are based on serverless architecture. This can be done using the listeners for the realtime database events.
Generated badge from the backend will be uploaded to the Firebase Storage, but applying a listener for storage events, will not give us the information of the sender and some other metadata. So after uploading the link on the database, we can use the public link generated and can push a dict to the realtime database with the necessary user information for sending mail.
Procedure
- Fetching the necessary information to be pushed on the Firebase realtime database.
def send_badge_mail(badgeId, userId, badgeLink): ref = firebase_db.reference(‘badgeMails’) print(‘Pushing badge generation mail to : ‘, badgeId) ref.child(userId).child(datetime.datetime.utcnow().isoformat().replace(‘-‘, ‘_’).replace(‘:’, ‘U’).replace(‘.’, ‘D’)).set({ ‘badgeId’: badgeId, ‘badgeLink’: badgeLink }) print(‘Pushed badge generation mail to : ‘, badgeId) |
Payload consists of the downloadable link of the badge and the root node is the userID. So whenever any node gets created in this format them the cloud function will be called.
- Listening for the database changes at the state of node.
exports.sendBadgeMail = functions.database.ref(‘/badgeMails/{userId}/{date}’) .onCreate((snapshot, context) => { const payload = snapshot.val(); const uid = context.params.userId; return admin.auth().getUser(uid) .then(record => { return sendBadgeGenMail(uid, record.email, record.displayName, payload[‘badgeId’], payload[‘badgeLink’]); }) .catch(() => { return -1 }); }); |
For the realtime database listener, it should listen to node in the form of badgeMails/<user_id>/<date> as whenever a node of such form will be created in the database the function will get triggered and not for any other data insertions in db. This will save the quota for the cloud function execution.
- Sending mail to the user from the payload
function sendBadgeGenMail(uid, email, displayName, badgeId, badgeLink) { const mailOptions = { from: `${APP_NAME}<noreply@firebase.com>`, to: email, }; mailOptions.subject = `Badge Generated ${badgeId}`; mailOptions.html = `<p> Hello ${displayName || ”}! Your badge is generated successfully, please visit the <a href=${badgeLink}>link</a> to download badge</p>`; return mailTransport.sendMail(mailOptions).then(() => { writeMailData(uid, “success”, 3); return console.log(‘Badge mail sent to: ‘, email) }).catch((err) => { console.error(err.message); return -1; }); } |
This will send the mail to the user with the generated link.
Pull Request for the above feature at link : Link
Outcome:
Resources
- Python Admin SDK for writing data to firebase – https://firebase.google.com/docs/database/admin/save-data
- Extending realtime database with cloud function – https://firebase.google.com/docs/database/extend-with-functions
- Managing users for getting details – https://firebase.google.com/docs/auth/admin/manage-users
You must be logged in to post a comment.