CRON Node.js Gmail API script - node.js

How do I properly setup Gmail API script that sends emails?
I am about to use this method and I started building my script from this quickstart guide.
Is there alternative way to do this without using OAuth 2 validation? Or a way to validate once for all?

Well, in using Gmail APi with your app, you need to use OAuth 2.0 because all request to the Gmail API must be authorized by an authenticated user. And if you notice the quickstart, there is a step here that you need to create a credentials/Outh client ID to make this API work.
For more information, there is another way to authorize your app with Gmail. You can do it with the help of Google+ Sign-in that provide a "sign-in with Google" authentication method for your app.

While asking for authorization from GMail, OAuth 2.0 gives one access token and one refresh token. To avoid validation every time, store the access token. Use the refresh token to get the new access token after it is expired (access token expires every one hour).
Read about this process here: https://developers.google.com/identity/protocols/OAuth2

I found solution using JWT to authorize OAuth2.
You need to have admin account to create Domain wide delegation service account. Then in Developer console you need to download service key JSON file which you load as credentials.
First fetch all users like this: (here you need to use account with admin directory rights)
const google = require('googleapis');
const gmail = google.gmail('v1');
const directory = google.admin('directory_v1');
const scopes = [
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/admin.directory.user.readonly'
];
const key = require('./service_key.json');
var authClient = new google.auth.JWT(
key.client_email,
key,
key.private_key,
scopes,
"authorized#mail.com"
);
authClient.authorize(function(err, tokens){
if (err) {
console.log(err);
return;
}
directory.users.list(
{
auth: authClient,
customer: 'my_customer',
maxResults: 250,
orderBy: 'email'
}, (err, resp) => {
if (err) {
console.log(err);
return;
}
console.log(resp);
});
});
Then you need to fetch Thread lists (100 per request (page)). And for each thread object you need to call get method for full thread. When using Gmail API authorize as user you want to fetch emails from. In request as userId use value 'me'.

Related

How to get a refresh token using the Microsoft Graph Javascript client library?

I am using the Microsoft graph Javascript client library to get a refresh token for a user. I created an app that connects doctors and patients. I want to create and delete events on the doctors' calendars. I first need their authorization to access their outlook account. Unfortunately, when I make the api call to get the refresh token, I get back an access token and an id token but no refresh token. Can someone please help?
Here's my code
const msalConfig = {
auth: {
clientId: process.env.OUTLOOK_OAUTH_CLIENT_ID,
authority: process.env.OUTLOOK_OAUTH_AUTHORITY,
clientSecret: process.env.OUTLOOK_OAUTH_CLIENT_SECRET
},
system: {
loggerOptions: {
loggerCallback(loglevel, message, containsPii) {
console.log(message);
},
piiLoggingEnabled: false,
logLevel: msal.LogLevel.Verbose,
}
}
};
// Create msal application object
const ouathClient = new msal.ConfidentialClientApplication(msalConfig);
const response = await ouathClient.acquireTokenByCode(tokenRequest);
I am using node js.
This method can also be used to get the refresh token, Please refer this Microsoft documentation.To get refresh token
Client Credentials flow does not support user context thus no refresh token is supported in this case.
If you are using MSAL depending on whether you are using Public client (Mobile, Desktop or Single Page apps) where users sign-in to your app then you may need a refresh token and you should be using flows listed here
If you are using a private client like a serveside daemon then you dont need a refresh token.

Is there is a way to grant my nodejs application access to my google calendar?

so I have a nodejs application that sends invites to an event in google calendar to some people, for now I am using my gmail account and OAuth Playground to get a temporary Access token and it works, but the access token is just available for minutes and each time I need to refresh the Access token manually and give access to my google account calendar and this is the problem, now I want to make something dynamic without me interfering in the process.
This application is hosted in wix.
any suggestions ?
Thanks
IF you are only letting them access a calendar that you own and control then you can use a service account.
let google = require('googleapis');
let privatekey = require("./privatekey.json");
  Now let’s use the private key to configure a JWT auth client and authenticate our request.
// configure a JWT auth client
let jwtClient = new google.auth.JWT(
privatekey.client_email,
null,
privatekey.private_key,
['https://www.googleapis.com/auth/calendar']);
//authenticate request
jwtClient.authorize(function (err, tokens) {
if (err) {
console.log(err);
return;
} else {
console.log("Successfully connected!");
}
});
Create service account credentials in google developer console. then take the service account email address and share the calendar with it via the google calendar website. The rest of the code you have should be the same just swap out the auth section with this.
To access the calendar API please follow the Quickstart
The code provided creates a refresh token that will automatically generate a new access token for you, whenever the old one expires.
Be careful with unnecessary using service accounts, especially for adding invitees to a calendar event - there are currently issues with this feature.

Auth0 & Dialogflow Authentication

I would like to use Auth0 to gain access for Google APIs. Was trying to follow the instructions on this post
Currently to trigger Auth0, I used conv.ask(new SignIn()); and app.intent("actions_intent_SIGN_IN", (conv, params, signin) => { ... })
I get a token from const code = conv.user.access.token; in my actions_intent_SIGN_IN.
However, it seems that this token isn't the token that is used to gain an access_token for Google, aka thru POST /oauth/token. Whatever this token is, it seems like it doesn't work for any of the requests except GET /userinfo. On Google Cloud Functions, I get this on my log:
{ error: 'invalid_grant', error_description: 'Invalid authorization code' }
I played around for a bit with Postman and managed to retrieve the (seemingly?) correct authorization code that can be used for POST /oauth/token thru GET /authorize and building my own url like https://[APP NAME].auth0.com/authorize?response_type=code&client_id=[CLIENT ID]&redirect_uri=[REDIRECT URI]. The authorization code appeared in https://[APP NAME].auth0.com/login/callback?code=[CODE HERE]
The issue is - how do I retrieve the code=[CODE HERE] from dialogflow?
You can authenticate with service accounts that use OAuth2.0 -- you can read more about that in general here and they'll save you a network call. You'll also need to find the appropriate Google API scope(s) here. Dialogflow has samples that show how this is done on Github, for example.
const {google} = require('googleapis');
const serviceAccount = { }; // Enter Service Account private key JSON
const client = new google.auth.JWT({
email: serviceAccount.client_email,
key: serviceAccount.private_key,
scopes: ['https://www.googleapis.com/auth/spreadsheets', 'https://www.googleapis.com/auth/drive']
});

Getting contacts from Google api in node

I want to get the contacts using the google contacts api in nodejs, but there isn't any quickstart on the developer.google page for nodejs.
I have found this wrapper on github https://github.com/hamdipro/google-contacts-api but I don't understand it and I don't know how to use it.
Can anyone tell me what can I do?
Unfortunately, Google's official API for NodeJS doesn't support Contacts API. They instead use the People API. If you need to access "Other Contacts", you will need Contacts API.
You can still connect with Contacts API using the official googleapis library if you're already using it for other purposes by sending a request to the Contacts API after creating the auth client.
Given that you already have the access token of the user (e.g. if you generated it using Passport, here's the code:
const {google} = require("googleapis");
const authObj = new google.auth.OAuth2({
access_type: 'offline',
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
});
Refresh access token automatically before it expires
authObj.on('tokens', (tokens) => {
const access_token = tokens.access_token
if (tokens.refresh_token){
this.myTokens.refreshToken = tokens.refresh_token
// save refresh token in the database if it exists
}
this.myTokens.accessToken = tokens.access_token
// save new access token (tokens.access_token)
}
authObj.setCredentials({
access_token:this.myTokens.accessToken,
refresh_token:this.myTokens.refreshToken,
});
Make the request to Contacts API:
authObj.request({
headers:{
"GData-Version":3.0
},
params:{
"alt":"json",
//"q":"OPTIONAL SEARCH QUERY",
//"startindex":0
"orderby":"lastmodified",
"sortorder":"descending",
},
url: "https://www.google.com/m8/feeds/contacts/default/full"
}).then( response => {
console.log(response); // extracted contacts
});
First thing instead of going with non-official package mentioned in question you should prefer using official package as they are well maintained, every under the hood changes are handled properly and also issues created are taken into considerations.
Official package for same is here.
Now steps to use above package to get contacts of a user :-
Include googleapis using npm install googleapis --save
Create a service client
var google = require('googleapis');
var contacts = google.people('v1');
Authorise client to make request {Link for authentication docs}
Making authenticated requests
contacts.people.connections.list({
auth: oauth2Client //authetication object generated in step-3
}, function (err, response) {
// handle err and response
});
That should be enough to get user's contact data. Also for authentication if you are using this for domain apart from gmail and have admin access you can get all user's contacts using domain wide delegation otherwise you will have to manually allow access for each user.
Hope it helps. Let me know in comments if have any queries.

Nodemailer/Gmail - What exactly is a refresh token and how do I get one?

I'm trying to do a simple contact form in a node app, using nodemailer. I want all the msg to be sent from a gmail account I made for this purpose, to my personnal mail.
on the client side, all I do is to get the name/mail/message of the customer and send it to the server. It works fine locally but fails to work when deployed (on heroku btw).
After a quick search, it seems I have to generate a ClientId and ClientSecret from Google Developers Console - which I did - but when it comes to generating a "refresh token" iI'm completely lost.
var smtpTransport = nodemailer.createTransport("SMTP",{
service:"Gmail",
auth:{
XOAuth2: {
user:"myaccount#gmail.com",
clientId:"",
clientSecret:"",
refreshToken:""
}
}
});
I am confused : What exactly is a refresh token and how do I get one ?
Notes by this answer original's author:
So, I finally managed to figure it out. I'm surprised I couldn't find more ressources about that so for those who need to use Gmail with Nodemailer
I found the answer here: http://masashi-k.blogspot.fr/2013/06/sending-mail-with-gmail-using-xoauth2.html
Try creating a new User if you already had one and things ain't working fine. It was the case for me.
I hope this will be useful to someone,
Cheers
Question 1: What exactly is a refresh token?
From documentation found here:
A refresh token provides your app continuous access to Google APIs while the user is not logged into your application.
(...)
Considerations:
Be sure to store the refresh token safely and permanently, because you can only obtain a refresh token the first time that you perform the code exchange flow.
There are limits on the number of refresh token that are issued—one limit per client/user combination, and another per user across all clients. If your application requests too many refresh tokens, it may run into these limits, in which case older refresh tokens stop working.
See also Offline Access and Using a refresh token.
Question 2: How do I get one?
Step 1: Obtain OAuth 2.0 credentials at Google Developers Console
As stated here, you should:
Go to the Google Developers Console.
Select a project, or create a new one.
In the sidebar on the left, expand APIs & auth. Next, click APIs. Select the Enabled APIs link in the API section to see a list of all your enabled APIs. Make sure that the "Gmail API" is on the list of enabled APIs. If you have not enabled it, select the Gmail API from the list of APIs (under Google Apps APIs), then select the Enable API button for the API.
In the sidebar on the left, select Credentials.
If you haven't done so already, create your project's OAuth 2.0 credentials by clicking Create new Client ID, and providing the information needed to create the credentials.
Look for the Client ID and Client secret in the table associated with each of your credentials.
PAY SPECIAL ATTENTION TO specifying https://developers.google.com/oauthplayground
as a Redirect URI when you create a new User in the console.
Otherwise, you will have an error.
Step 2: Obtain the refresh token at Google OAuth2.0 Playground
Go to the Google Oauth2.0 Playground.
Click the Gear Button on the right-top. Set your Client ID and Client Secret obtained from the Google Developers Console, and select Access token location as Authorization header w/ Bearer prefix. Close this configuration overlay.
Set up the scopes. Use https://mail.google.com/ as it's the one need by nodemailer. Then click the Authorize APIs button.
After OAuth2.0 authorization, exchange authorization code for tokens and voilá! your refresh token is ready-to-use
For those who have been looking around for a working example/code snippet, follow Radioreve's Answer until you are able to get the access token and refresh token. (Basically, go to the playground, make sure it asks for access for sending mail and mail.google.com, give permission, exchange authorization code for tokens)
Note that the expires time I entered was new Date().getTime() + 2000 which was close to the expiration seconds seen on the playground. I am not sure if I had to enter access token and expiration time accurately as it seems to be refreshing the token automatically.
Use this sample code written in ECMAScript 6:
const user_name = 'something#gmail.com';
const refresh_token = '';
const access_token = '';
const client_id = '';
const client_secret = '';
const email_to = 'receiver#gmail.com';
const nodemailer = require('nodemailer');
let transporter = nodemailer
.createTransport({
service: 'Gmail',
auth: {
type: 'OAuth2',
clientId: client_id,
clientSecret: client_secret
}
});
transporter.on('token', token => {
console.log('A new access token was generated');
console.log('User: %s', token.user);
console.log('Access Token: %s', token.accessToken);
console.log('Expires: %s', new Date(token.expires));
});
// setup e-mail data with unicode symbols
let mailOptions = {
from : user_name, // sender address
to : email_to, // list of receivers
subject : 'Hello ✔', // Subject line
text : 'Hello world ?', // plaintext body
html : '<b>Hello world ?</b>', // html body
auth : {
user : user_name,
refreshToken : refresh_token,
accessToken : access_token,
expires : 1494388182480
}
};
// send mail with defined transport object
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
return console.log(error);
}
console.log('Message sent: ' + info.response);
});
You can Simple use Google SMTP to send email. Use nodemailer with smtp.google.com and email and App password (not gmail password).
How to Get App Password.
Now you have to enable 2 Step Verification in Google (How to Enable 2 Step Auth)
You need to generate App Specific Password. Goto Google My Account > Security
Click on App Password > Select Other and you will get App Password
You can use normal smtp with email and App password.

Resources