I am trying to use firebase functions in reactjs to create a trigger that sends a mail when information is uploaded to the firestore database.
A bridge is created with nodemailer and a function is executed when a new document is loaded into the db.
This is the code:
const functions = require("firebase-functions");
const nodemailer = require("nodemailer");
/* const admin = require('firebase-admin');
admin.initializeApp(); */
// GmailAccount
const gmailUser = "myname#gmail.com"; //example mail, use another
const gmailPassword = "mypass"; //example pass, it is not the real one that I use.
const transport = nodemailer.createTransport({
service: "gmail",
auth: {
user: gmailUser,
pass: gmailPassword
}
});
exports.newContact = functions.firestore
.document("/Contacts/{documentId}")
.onCreate((snap, contentxt) => {
const name = snap.data().name;
return sendEmail(name);
});
const sendEmail = (name) => {
return transport
.sendMail({
from: gmailUser,
to: "myEmail#gmail.com",
subject: "test",
html:name
})
.then(r => console.log(r))
.catch(e => console.log(e));
}
So far so good. The problem occurs when I want to deploy: I execute the command:
firebase deploy --only functions and the console gives me the following:
Functions deploy had errors with the following functions:
newContact(us-central1)
i functions: cleaning up build files...
Error: There was an error deploying functions
A more detailed error would be the following:
{"code":3,"message":"Function failed on loading user code.
When running: firebase emulators:start --only functions
It tells me: function ignored because the firestore emulator does not exist or is not running
Related
I had an error in deploying Firebase functions after I changed my laptop and also transferred ownership of my Firebase account to another for a 3-month free Blaze plan. While deploying any functions, I am getting this error. All Firebase functions are successfully running locally.
Error code
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message> The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message>
<StringToSign GET 1670330017 /uploads-abc.zip</StringToSign></Error>
index.js
`
const functions = require("firebase-functions");
const admin = require("firebase-admin");
var handlebars = require("handlebars");
var fs = require("fs");
const nodemailer = require("nodemailer");
var serviceAccount = require("../service_account.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
storageBucket: "gs://xyz.com",
databaseURL: "https://xyz",
});
transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: "username",
pass: "password",
},
});
readHTMLFile = function (path, callback) {
fs.readFile(path, { encoding: "utf-8" }, function (err, html) {
if (err) {
callback(err);
throw err;
} else {
callback(null, html);
}
});
};
exports.sendWelcomeMail = functions.https.onCall(async (data, context) => {
// Grab the text parameter.
const email = data.email;
const name = data.name;
readHTMLFile(`./welcome_page.html`, function (err, html) {
var template = handlebars.compile(html);
var replacements = {
name: name,
};
var htmlToSend = template(replacements);
var mailOptions = {
from: "from-mail",
to: email,
subject: "Welcome to boom boom",
html: htmlToSend,
};
transporter.sendMail(mailOptions, (erro, info) => {
if (erro) {
console.log(erro.toString());
return erro.toString();
}
console.log("Sended");
return "Sended";
});
});
});
`
I had tried different service account private keys which we can get from firebase project settings, with that I had tried deploying functions from different account ex. owners account, other account with service admin access.
Please check that SHA keys (SHA-1 and SHA-256) in your Firebase project (Project Settings -> General -> Your Apps -> Select your android app -> SHA certificate fingerprints) are same as in Google Play Console (Setup -> App integrity -> App Signings -> App Signing Key Certificate).
Specially if you are using Google play signing to release your app.
try in your terminal :
login with your firebase account firebase login:ci you will be redirected to your browser, you have to login
come back to the terminal (now you are logged in) and type firebase projects:list to list all the projects that you can access with your logged in firebase account
choose the project you want to deploy your function to : firebase use
NB: you are assumed to have npm and firebase-tools already installed in your terminal
I'm trying to notify every user subscribed to a topic in the app once a part of my database is updated. I uploaded the following cloud function:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.PushNotification =
functions.firestore.document("/Alert_places/{alert}").onCreate(
(snapshot, context) =>
{
admin.messaging().sendToTopic("helper",{
notification: {
title: "MyApp",
body: "Body"
}
}
)
}
);
The function uploaded fine, but following an event I get the following messages on the logs:
So no user gets the notification.
I implemented the code below and it works perfectly fine when I run it in on local machine with npm start
However, when I deploy it on Firebase, the sendOrderEmail function doesn't work.
I don't even get any logs.
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const {email, password} = require('./config');
const nodemailer = require('nodemailer');
const htmlToText = require('nodemailer-html-to-text').htmlToText;
admin.initializeApp();
const mailTransport = nodemailer.createTransport({
service: 'gmail',
auth: {
user: email,
pass: password
}
});
mailTransport.use("compile", htmlToText());
const APP_NAME = 'the.Travelest';
exports.sendUserEmail = functions.database
.ref("/lettersRequest/{pushId}")
.onCreate(request => {
return sendOrderEmail(request.val().email);
});
async function sendOrderEmail(email){
const mailOptions = {
from: `${APP_NAME}`,
to: email,
subject: `Your order from ${APP_NAME}`,
html: `
<div>
<strong> Hello </strong>
World
</div>
`
};
return await mailTransport.sendMail(mailOptions);
}
UPDATE
After checking the logic, I believe that I've found the issues in another place.
So, the logic is - when I click on SUBMIT in form, I send the data to Firebase Runtime Database. And this action triggers the function above and send the email.
However, the SUBMIT button doesn't trigger the process it should trigger. I don't see even console.log result in the console, when I click on SUBMIT
Again, it works locally, when I run nom start
Here is the submit handler:
const handleSubmit = event => {
event.preventDefault();
setErrors(validate(values))
setIsSubmitting(true)
try{
const newRequestRef = database.ref('lettersRequest').push();
const newRequest = {
country: values.country,
travelersAmount: values.travelersAmount,
introExtro: values.introExtro,
comments: values.comments,
email: values.email,
phone: values.phone
};
newRequestRef.set({
email: values.email,
request: newRequest
});
console.log("no error")
}catch(e){
console.log("error")
}
}
You are not handling the promise returned by set(). Try this:
const handleSubmit = event => {
event.preventDefault();
setErrors(validate(values))
setIsSubmitting(true)
const newRequestRef = database.ref('lettersRequest').push();
const newRequest = {
country: values.country,
travelersAmount: values.travelersAmount,
introExtro: values.introExtro,
comments: values.comments,
email: values.email,
phone: values.phone
};
newRequestRef.set({
email: values.email,
request: newRequest
}).then(() => {
console.log("Request Added in Database")
}).catch(e => console.log(e));
}
If it logs 'Request Added in Database' then it has been added successfully and your function should trigger.
Additionally, this can also be done by a Callable Function which means you call the function directly from the client, do all the validation, add the data in database and send the email instead of using database triggers.
So, the issue was even more trivial than I could expect :D
I did deploy to firebase, but I've never did commit and build project...
As a result, nothing was updated after each deploy.
Stupid mistake
I have a firebase database where onCreate Google Cloud Functions calls nodemailer and sends me an email. It all works fine but now I am trying to also include the data that was added to the database in the email. I can't get it to work, seemingly because it is not in a text format and I've tried converting to text and that doesn't seem to do it. What am I doing wrong?
const functions = require('firebase-functions');
const nodemailer = require('nodemailer');
// Configure the email transport using the default SMTP transport and a GMail account.
// For other types of transports such as Sendgrid see https://nodemailer.com/transports/
// TODO: Configure the `gmail.email` and `gmail.password` Google Cloud environment variables.
const gmailEmail = functions.config().gmail.email;
const gmailPassword = functions.config().gmail.password;
const mailTransport = nodemailer.createTransport({
service: 'gmail',
auth: {
user: gmailEmail,
pass: gmailPassword,
},
});
exports.sendWelcomeEmail = functions.database.ref('/PickupRequests/{pushId}')
.onCreate(async(snapshot, context) => {
const val = snapshot.data;
const mailOptions = {
from: '<noreply#firebase.com>',
to: "mike#puravidalaundry.com",
subject: "New Pickup Request",
text: val //How do i convert this to a text format?
};
try {
await mailTransport.sendMail(mailOptions);
console.log('email sent');
} catch(error) {
console.error('There was an error while sending the email:', error);
}
return null;
});
To get the value from the snapshot, use snapshot.val(). So:
const val = snapshot.val();
Note that this is shown in an example in the documentation on handling event data for Realtime Database triggered Cloud Functions.
figured it out. I had to create a new variable const newvar = JSON.stringify(val) and then i said text: newvar
I feel like I might be missing something simple, but I can't get a Cloud Function for Firebase to respond to a Pub/Sub published message. It works fine when I deploy using cloud and opt for the Admin SDK for Node.js, but Auth is tricky; it works for the first write and then it fails to authenticate.
With the release of Cloud Function for Firebase, I decided to try again. My function code is as follows:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
function pushOrderToFirebase(completedOrder) {
admin.initializeApp(functions.config().firebase);
//setters and getters for the message that will be pushed to firebase
admin.database().ref('/orders').push({
name: curDriverName,
recipient: recipient,
address: address,
details: details,
isDelivered: isDelivered,
failureReason: failureReason,
time: formattedTime
}).then(snapshot => {
console.log(snapshot);
});
}
exports.firebasePusherAlpha = functions.pubsub.topic('test-topic').onPublish(event => {
const pubSubMessage = event.data;
let parsedMessage = null;
try {
parsedMessage = pubSubMessage.json;
console.log(parsedMessage);
} catch (e) {
console.error('PubSub message was not JSON', e);
}
pushOrderToFirebase(parsedMessage);
callback();
});
Unfortunately, it doesn't get called when I publish a pubsub message.