Skip to content

Instantly share code, notes, and snippets.

@mosampaio
Last active Jan 13, 2021
Embed
What would you like to do?
Gmail Api OAuth Using Node.js Express - part 2

How to Run?

  • Make sure there is a mongodb instance running locally.

  • First export the environment variables.

export CLIENT_ID=your-client-id
export CLIENT_SECRET=your-client-secret
export DOMAIN_URL=your-domain-url

export TWILIO_ACCOUNT_SID=your-twilio-account-sid
export TWILIO_AUTH_TOKEN=your-twilio-auth-token
export TWILIO_PHONE_NUMBER=your-twilio-phone-number
export CELLPHONE=your-cell-phone
  • Then install the dependencies.
npm install
  • Run the app.
npm start
  • List labels
npm run list-labels
  • Edit the check-inbox.js file adding the label id and then run:
npm run check-inbox
const express = require('express')
, http = require('http')
, path = require('path')
, cookieParser = require('cookie-parser')
, bodyParser = require('body-parser')
, mongoose = require('mongoose')
, port = 3000
, Token = require('./token')
, google = require('googleapis')
, clientId = process.env.CLIENT_ID
, clientSecret = process.env.CLIENT_SECRET
, redirectUrl = process.env.DOMAIN_URL + '/create'
, oauth2Client = new google.auth.OAuth2(clientId, clientSecret, redirectUrl)
, authConfig = {
access_type: 'offline',
scope: [
'https://www.googleapis.com/auth/plus.me',
'https://www.googleapis.com/auth/calendar',
'https://www.googleapis.com/auth/gmail.modify'
],
approval_prompt: 'force'
}
, app = express();
app.set('port', port);
app.set('views', path.join(__dirname));
app.set('view engine', 'pug');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.get('/', (req, res) => {
const url = oauth2Client.generateAuthUrl(authConfig);
res.send(`<a href="${url}">Click here to login with your Google Account</a>`);
});
app.get('/create', (req, res, next) => {
oauth2Client.getToken(req.query.code, (err, tokens) => {
if (err) return next(err);
oauth2Client.setCredentials(tokens);
const query = { accessToken: tokens['access_token'] };
const entity = {
accessToken: tokens['access_token'],
refreshToken: tokens['refresh_token'],
expiresAt: new Date(tokens['expiry_date'])
};
const opts = { upsert: true };
const cb = (err, info) => {
if (err) next(err);
Token.findOne((err, token) => (err) ? next(err) : res.send(token));
};
Token.update(query, entity, opts, cb);
});
});
mongoose.connect('mongodb://localhost/gmail-alerts-node');
http.createServer(app).listen(port);
console.log(`App up and running on port ${port}`);
module.exports = app;
const _ = require('underscore')
, gmailFactory = require('./gmail-factory')
, twilioClient = require('twilio')()
, SMS_LABEL_ID = 'Label_37';
gmailFactory((err, gmail) => {
if (err) throw err;
const emails = gmail.users.messages.list({
userId: "me",
labelIds: ['INBOX', SMS_LABEL_ID]
}, (err, results) => {
if (err) throw err;
console.log(results);
});
});
const _ = require('underscore')
, gmailFactory = require('./gmail-factory')
, twilioClient = require('twilio')()
, SMS_LABEL_ID = 'Label_37';
gmailFactory((err, gmail) => {
if (err) throw err;
const emails = gmail.users.messages.list({
userId: "me",
labelIds: ['INBOX', SMS_LABEL_ID]
}, (err, results) => {
if (err) throw err;
if (_.isEmpty(results.messages)) {
console.log('there is no message to be sent');
}
_.each(results.messages, (message) => {
getDetail(gmail, message, (err, detail) => {
sendSms(`${detail.from}\n${detail.subject}`);
removeLabel(gmail, message.id)
});
});
});
});
const getDetail = (gmail, message, cb) => {
gmail.users.messages.get({
userId: 'me',
id: message.id
}, (err, msg) => {
if (err) return cb(err);
const from = extractHeader(msg, 'From');
const subject = extractHeader(msg, 'Subject');
return cb(undefined, { from: from, subject: subject});
});
};
const extractHeader = (msg, headerName) => {
return _.chain(msg.payload.headers)
.filter((header) => { return header.name == headerName})
.first().value().value;
}
var sendSms = function(msg) {
twilioClient.sms.messages.create(
{
to: process.env.CELLPHONE,
from: process.env.TWILIO_PHONE_NUMBER,
body: msg
},
(err, message) => {
if (err) throw err;
console.log('msg has been sent successfully');
}
);
};
var removeLabel = function(gmail, msgId) {
gmail.users.messages.modify({
userId: "me", id: msgId, resource: { addLabelIds: [], removeLabelIds: ['Label_37'] }
}, (err, results) => {
if (err) throw err;
console.log(`label removed from ${msgId} successfully`);
});
};
const mongoose = require('mongoose')
, Token = require('./token')
, google = require('googleapis')
, clientId = process.env.CLIENT_ID
, clientSecret = process.env.CLIENT_SECRET
, redirectUrl = process.env.DOMAIN_URL + '/create'
, oauth2Client = new google.auth.OAuth2(clientId, clientSecret, redirectUrl);
module.exports = function(cb) {
mongoose.connect('mongodb://localhost/gmail-alerts-node', (err) => {
if (err) return handleError(err, cb);
Token.findOne({}, (err, token) => {
if (err) return handleError(err, cb);
token.freshToken((err, accessToken) => {
if (err) return handleError(err, cb);
oauth2Client.setCredentials({
access_token: accessToken,
refresh_token: token.refreshToken
});
const gmail = google.gmail({ auth: oauth2Client, version: 'v1' });
mongoose.disconnect();
return cb(undefined, gmail);
})
});
});
};
var handleError = function(err, cb) {
mongoose.disconnect();
return cb(err);
}
const gmailFactory = require('./gmail-factory');
gmailFactory((err, gmail) => {
if (err) throw err;
const emails = gmail.users.labels.list({
userId: "me"
}, (err, results) => {
if (err) throw err;
console.log(results.labels);
});
});
{
"name": "gmail-alerts-node",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./app",
"check-inbox": "node check-inbox",
"list-labels": "node list-labels"
},
"dependencies": {
"body-parser": "~1.13.2",
"cookie-parser": "~1.3.5",
"express": "~4.13.1",
"googleapis": "^12.4.0",
"moment": "^2.14.1",
"mongoose": "^4.5.10",
"pug": "^2.0.0-beta6",
"request": "^2.74.0",
"twilio": "^2.9.2",
"underscore": "^1.8.3"
}
}
'use strict';
const mongoose = require('mongoose')
, request = require('request')
, moment = require('moment')
, schema = new mongoose.Schema({
accessToken: String,
refreshToken: String,
expiresAt: Date
});
schema.methods.refresh = function(callback) {
const url = 'https://accounts.google.com/o/oauth2/token';
const params = {
'refresh_token': this.refreshToken,
'client_id': process.env.CLIENT_ID,
'client_secret': process.env.CLIENT_SECRET,
'grant_type': 'refresh_token'
};
const that = this;
request.post(url, params, (error, response, body) => {
if (error) {
return callback(error, undefined);
}
const data = JSON.parse(body);
this.accessToken = data.access_token;
this.expiresAt = moment().add(data.expires_at, 'seconds').toDate();
this.update((err) => {
if (err) {
callback(err, undefined);
} else {
callback(undefined, that.accessToken);
}
});
});
};
schema.methods.freshToken = function(callback) {
if (moment().isAfter(this.expiresAt)) {
this.refresh(callback);
} else {
callback(undefined, this.accessToken);
}
};
module.exports = mongoose.model('token', schema);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment