Mailchimp: Register user via API: can't set a custom field - node.js

My NodeJS backend communicates with the Mailchimp API (v3) in order to register new subscribers. I'm unable to find the value that allows setting a simple "YES" or "NO" in this case.
From the list settings UI, here is my custom field:
The following code properly registers the user but the custom "WEB3JS" field isn't set (with npm install mailchimp-api-v3 installed).
What could I be doing wrong?
var Mailchimp = require('mailchimp-api-v3')
var mailchimp = new Mailchimp(/* API key */);
return function handler(req, res){
const email = req.body.email;
const name = req.body.name;
const web3 = req.body.web3;
const body = {
email_address : email,
status : 'subscribed'
};
body.WEB3JS = web3 ? 'YES' : 'NO';
body.WEB3JS = 'YES'; // Debug: force "yes"
mailchimp.post('/lists/**LIST_ID**/members', body)
.then(function(results) {
res.json({});
})

Related

I have the create and saving of the user's email, but I can't do an email update. Use firebase, firestore and react

This is my code:
exports.saveUserEmail = functions.region('europe-central2').auth.user().onCreate((user) => {
const email = user.email;
const uid = user.uid;
const dt = dateTime.create();
const formatted = dt.format("Y-m-d H:M:S");
return admin.firestore().collection('users').doc(uid).set({uid: uid, email: email, created_at: formatted});
});
and i tried do update like this:
exports.saveEditedEmail = functions.region('europe-central2').auth.user().updateUser((user, uid) => {
const email = user.email;
return admin.firestore().collection('users').doc(uid).set({uid: uid, email: email,});
})
Where is my mistake?
There isn't any onUpdate() auth trigger for Cloud functions. Instead your can create a callable function and call it directly from client side to update your user.
exports.addMessage = functions.https.onCall((data, context) => {
const { email } = data;
// update email in Firebase Auth and Firestore
});
Alternatively, you can directly update the document in Firestore if the user tries to update their own profile. You can setup the following security rules so a user can update their own profile only:
match /users/{userId} {
allow update: if request.auth.uid == userId;
}

how can i add the sendgrid webhook event Json response in a firebase cloud firestore using node.js

I have no idea how to implement this thing but before that, I have done a part of SendGrid where any document is created then it will send the email to the user. but this part what I am asking I has no idea how to proceed.this is my first part of this implementation wherein any collection if a new record is created then it will send email to the particular email and there is a response called event Object I want to write a cloud function to store the data. and I don't know how to start this function or proceed with this problem.
"use strict";
const functions = require("firebase-functions");
const admin = require("firebase-admin");
var serviceAccount1 = require("./key.json");
const newProject = admin.initializeApp({
credential: admin.credential.cert(serviceAccount1),
databaseURL: "xyz"
});
const sgMail = require("#sendgrid/mail");
const sgMailKey = "key";
sgMail.setApiKey(sgMailKey);
exports.sentMail = functions.firestore
.document("/Offices/{officeId}")
.onCreate((documentSnapshot,event) => {
const documentData = documentSnapshot.data()
const officeID = event.params.officeId;
console.log(JSON.stringify(event))
const db = newProject.firestore();
return db.collection("Offices").doc(officeID).get()
.then(doc => {
const data = doc.data();
const msg = {
to: "amarjeetkumars34#gmail.com",
from: "singhamarjeet045#gmail.com",
text: "hello from this side",
templateId: "d-8ecfa59aa9d2434eb8b7d47d58b4f2cf",
substitutionWrappers: ["{{", "}}"],
substitutions: {
name: data.name
}
};
return sgMail.send(msg);
})
.then(() => console.log("payment mail sent success"))
.catch(err => console.log(err));
});
and the expected output of my question be like a collection name XYZ wherein an object there are three fields like
{email:"xyz#gmail.com",
event:"processed",
timestamp:123555558855},
{email:"xyz#gmail.com",
event:"recieved",
timestamp:123555558855},
{email:"xyz#gmail.com",
event:"open",
timestamp:123555558855}
As you will read in the Sendgrid documentation:
SendGrid's Event Webhook will notify a URL of your choice via HTTP
POST with information about events that occur as SendGrid processes
your email
To implement the HTTP endpoint in your Firebase Project, you will implement an HTTPS Cloud Function that will be called by the Sendgrid webhook through an HTTPS POST request.
Each call from the Sendgrid webhook will concern a specific event and you will be able, in your Cloud Function, to get the value of the event (processed, delivered, etc...).
Now, you need in your Cloud Function to be able to link a specific event with a specific email that was previously sent through your Cloud Function. For that you should use custom arguments.
More precisely, you would add to your msg object (that you pass to the send() method) a unique identifier. A classical value is a Firestore document ID, like event.params.officeId but could be any other unique ID that you generate in you Cloud Function.
Example of implementation
In your Cloud Function that sends the email, pass the officeId in a custom_args object, as shown below:
exports.sentMail = functions.firestore
.document("/Offices/{officeId}")
.onCreate((documentSnapshot,event) => {
const documentData = documentSnapshot.data();
const officeId = event.params.officeId;
const msg = {
to: "amarjeetkumars34#gmail.com",
from: "singhamarjeet045#gmail.com",
text: "hello from this side",
templateId: "d-8ecfa59aa9d2434eb8b7d47d58b4f2cf",
substitutionWrappers: ["{{", "}}"],
substitutions: {
name: documentData.name
},
custom_args: {
"officeId": officeId
}
};
return sgMail.send(msg)
.then(() => {
console.log("payment mail sent success"));
return null;
})
.catch(err => {
console.log(err)
return null;
});
});
Note that you get the data of the newly created document (the one which triggers the Cloud Function) through documentSnapshot.data(): you don't need to query for the same document in your Cloud Function.
Then, create a simple HTTPS Cloud Function, as follows:
exports.sendgridWebhook = functions.https.onRequest((req, res) => {
const body = req.body; //body is an array of JavaScript objects
const promises = [];
body.forEach(elem => {
const event = elem.event;
const eventTimestamp = elem.timestamp;
const officeId = elem.officeId;
const updateObj = {};
updateObj[event] = true;
updateObj[event + 'Timestamp'] = eventTimestamp;
promises.push(admin.firestore().collection('Offices').doc(officeId).update(updateObj));
});
return Promise.all(promises)
.then(() => {
return res.status(200).end();
})
})
Deploy it and grab its URL as shown in the terminal: it should be like https://us-central1-<your-project-id>.cloudfunctions.net/sendgridWebhook.
Note that here I use admin.firestore().collection('Offices').... You may use const db = newProject.firestore(); ... db.collection('Offices')...
Also note that the body of the HTTPS POST request sent by the Sendgrid webhook contains an array of JavaScript objects, therefore we will use Promise.all() to treat these different objects, i.e. write to the Firestore document with officeId the different events.
Then you need to set-up the Webhook in the Sendgrid platform, in the "Mail Settings/Event Notification" section, as explained in the doc and as shown below.

How to get user by email?

I am using graph-service to access Microsoft Graph API. Following this document to get user by email. I have write a block of code:
var user = null;
const GraphService = require('graph-service');
const ClientCredentials = require('client-credentials');
const tenant = 'my-company.com';
const clientId = '0b13aa29-ca6b-42e8-a083-89e5bccdf141';
const clientSecret = 'lsl2isRe99Flsj32elwe89234ljhasd8239jsad2sl=';
const credentials = new ClientCredentials(tenant, clientId, clientSecret);
const service = new GraphService(credentials);
service.all('/users').then(response => {
console.log(response.data);
response.data.forEach(function(item) {
if (item.userPrincipalName == "lgomez#my-company.com"){
user = item;
break;
}
});
});
But response.data returns a list of users with cost much resource to get a single user object by email. Please help me to update the code which can return only a single object of user by email.
The operation /users you are using, is for retreiving a list of all users.
You can request as single user by calling:
/users/{id | userPrincipalName}
This operation either accepts an userId or an userPrincipleName
e.g.
/users/foo#bar.com
[more information is in the documentation]
In your case the code could be altered to:
//...
var myUPN = "lgomez#my-company.com"
service.get('/users/' + myUPN).then(response => {
console.log(response.data);
});

Promise not returning value on request

I have been trying to get this to work, but am new to NodeJS. I suspect the issue is due to async, but am not familiar with how it works.
The idea behind this code is that it monitors a firebase database change and sends an email to the users. I am getting everything from the change snapshot, and using the values to check another table for user data. The request is not returning before the email gets sent and I am unsure why.
Edit I should specify that the email function sgMail is firing off before I get the results from the requests. I've tried putting a delay, but I am still not getting the result to return in time.
Here's my index.js
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');
var requestify = require('requestify');
//SendGrid
const SENDGRID_API_KEY = functions.config().sendgrid.key;
const sgMail = require('#sendgrid/mail');
sgMail.setApiKey(SENDGRID_API_KEY);
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.packingListEmail = functions.database.ref('Order/{orderID}')
.onUpdate(event => {
// Grab the current value of what was written to the Realtime Database.
const eventSnapshot = event.data;
//Here You can get value through key
var shipperInfo = eventSnapshot.child("fk_shipper_id").val();
var travelerInfo = eventSnapshot.child("fk_traveler_id").val();
//Print value of string
console.log(shipperInfo);
//Get Shipper Info
const shipperPath = 'https://shlep-me-f516e.firebaseio.com/User/'+shipperInfo+'.json';
requestify.get(shipperPath)
.then(function(response) {
// Get the response body (JSON parsed or jQuery object for XMLs)
shipperResult = response.getBody();
console.log(shipperResult.email);
return shipperResult;
});
function getTravelerData() {
return new Promise(resolve => {
requestify.get('https://shlep-me-f516e.firebaseio.com/User/' + travelerInfo + '.json')
.then(function (response) {
resolve(response.getBody())
});
});
}
var TravelD = getTravelerData();
//Send an email
const msg = {
to: 'andrew#shlepme.com',
from: 'support#shlepme.com',
subject: 'New Follower',
// text: `Hey ${toName}. You have a new follower!!! `,
// html: `<strong>Hey ${toName}. You have a new follower!!!</strong>`,
// custom templates
templateId: 'd1ccfeb9-2e2d-4979-a3ca-c53975fe486e',
substitutionWrappers: ['%', '%'],
substitutions: {
'%shipper_name%': "Test",
'traveler_name': TravelD.name
// and other custom properties here
}
};
console.log('Sending email');
console.log(TravelD);
return sgMail.send(msg)
});
Any ideas? I have been trying to figure this out.
It seems that you need to understand about Promises first.
When you start using promises you will need to ALWAYS use them and chain one with the other.
So I would rewrite your code like this: (not tested)
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require("firebase-functions");
var requestify = require("requestify");
//SendGrid
const SENDGRID_API_KEY = functions.config().sendgrid.key;
const sgMail = require("#sendgrid/mail");
sgMail.setApiKey(SENDGRID_API_KEY);
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require("firebase-admin");
admin.initializeApp(functions.config().firebase);
exports.packingListEmail = functions.database
.ref("Order/{orderID}")
.onUpdate(event => {
// Grab the current value of what was written to the Realtime Database.
const eventSnapshot = event.data;
//Here You can get value through key
var shipperInfo = eventSnapshot.child("fk_shipper_id").val();
var travelerInfo = eventSnapshot.child("fk_traveler_id").val();
//Print value of string
console.log(shipperInfo);
//Get Shipper Info
const shipperPath = "https://shlep-me-f516e.firebaseio.com/User/" + shipperInfo + ".json";
requestify.get(shipperPath)
.then(function(response) {
// Get the response body (JSON parsed or jQuery object for XMLs)
var shipperResult = response.getBody();
console.log(shipperResult.email);
return shipperResult;
})
.then(function (shipperResult) {
//Send an email
const msg = {
to: "andrew#shlepme.com",
from: "support#shlepme.com",
subject: "New Follower",
// text: `Hey ${toName}. You have a new follower!!! `,
// html: `<strong>Hey ${toName}. You have a new follower!!!</strong>`,
// custom templates
templateId: "d1ccfeb9-2e2d-4979-a3ca-c53975fe486e",
substitutionWrappers: ["%", "%"],
substitutions: {
"%shipper_name%": "Test",
traveler_name: shipperResult.name
// and other custom properties here
}
};
console.log("Sending email");
console.log(shipperResult);
return sgMail.send(msg);
});
});

How to get mail id of twitter account through nodejs

I am trying to get mail id from twitter user through nodejs at the result I only got tweets and other details of users but I don't get mail id. I attach my code anyone tell me whether my code is write way to get mail id
// twitter api script
var config = require("./config");
// In config file I have my consumer_key, consumer_secret, access_token_key,access_token_secret
var fs = require('fs');
var Twitter = require('twitter');
var client = new Twitter(config.twitter);
var writer = fs.createWriteStream('tweets.json')
var start_time = 0;
var handles = "";
fs.readFile('./t_handle.csv', 'utf8', function(err, contents) {
var params = {
'include_email' : true
};
handles = contents.split("\n");
writer.write("[");
handles.forEach(function(handle){
handle = handle.split("/")[3];
if(typeof handle !== 'undefined' && handle){
handle = handle.split("?")[0];
get_handle_tweets(handle,params);
}
});
});
function get_handle_tweets(handle){
client.get('statuses/user_timeline', { screen_name: handle }, function(error, tweets,params,response) {
if(error){
console.log(error);
}else{
tweets.forEach(function(tweet){
writer.write(JSON.stringify(tweet)+",\n");
});
}
});
}
First check if when you Authorize for your app in the Will be able to see field, "see your email address" is there , if not check if you have valid privacy policy and TOS URL since white listing the app is no longer required, also in php I had to Change 'include_email' : true to 'include_email' : 'true' sometime ago when I tried this, so that could be the issue.

Resources