CONNECTION SOCKET.IO - javascript

I've been stuck for a few days now with a socket.io problem, more precisely between server to client.
On the client side, (Angular) I can emit an event, the server can grab and execute all the logic, but after the server to the client it doesn't show signs of life.
I've already expressed all the events, I've reformulated all the settings as it says in the documentation and nothing works, can anyone see where I'm going wrong?
"socket.io": "^4.5.1"
"socket.io-client": "^4.5.1",
ANGULAR (CLIENT-SIDE)
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs';
import { io, Socket } from 'socket.io-client';
import { environment } from 'src/environments/environment';
#Injectable({
providedIn: 'root'
})
export class SocketIoService {
socket: Socket;
constructor() {}
connect(token: string, userName: string){
this.socket = io(environment.path.hermsUrl, {
query: {
token,
userName
}
});
}
disconnect(){
this.socket.disconnect();
}
sendMessage(msg: any) {
this.socket.emit('send-message', (msg));
}
getConversation(){
this.socket.on('update-conversation', (conversation)=> {
console.log('############################################');
});
}
}
NODE.JS (SERVER-SIDE)
require('dotenv').config();
require('./Helpers/init_mongodb');
const express = require('express');
const cors = require('cors');
const createError = require('http-errors');
const chatController = require('./Controllers/chat.controller');
const Chat = require('./Models/chat.model');
const app = express();
const httServer = require('http').createServer(app);
const { verifyAccessToken } = require('./Helpers/jwt_token');
const userRoute = require('./Routes/user.routes');
const eventRoute = require('./Routes/event.routes');
const chatRoute = require('./Routes/chat.routes');
const decode = require('jwt-decode');
const PORT = process.env.PORT || 5005;
const io = require('socket.io')(httServer, {
cors: {
origins: ["*"]
}
});
app.use(express.json({ limit: '50mb' }));
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use('/path/user', userRoute);
app.use('/path/event', eventRoute);
app.use('/path/chat', chatRoute);
app.use(async (req, res, next) => {
next(createError.NotFound('THIS ROUTE DOES NOT EXIST'))
});
app.get('/', verifyAccessToken, async (req, res, next) => {
res.send('HELLO THERE')
});
app.use((err, req, res, next) => {
res.status(err.status || 500)
res.send({
error: {
status: err.status || 500,
message: err.message,
},
})
});
io.on("connection", (socket) => {
const decodedObj = decode(socket.handshake.query.token);
socket.id = decodedObj.aud;
const userName = socket.handshake.query.userName;
console.log("========= SOCKET.IO CONNECTED =========");
console.log("");
console.log("USERNAME: " + userName);
console.log("ID: " + socket.id);
console.log("");
console.log("=======================================");
socket.on('send-message', async (message) => {
try{
const chatId = message.chatId;
const decodedObj = decode(message.sender);
const senderId = decodedObj.ID;
const userSocketId = message.userId;
const date = new Date();
const day = date.getDate();
const month = date.getMonth();
const year = date.getFullYear();
const hour = date.getHours();
const minuts = date.getMinutes();
const sendingDate = day + "/" + month + "/" + year + " " + hour + ":" + minuts;
const newMsg = {
msgType: message.typeOfMsg,
message: message.msg,
date: sendingDate,
sender: senderId
}
const conversation = await Chat.findById(chatId);
if(!conversation){
throw createError.NotFound();
}
conversation.messages.push(newMsg);
const updateConversation = await Chat.findByIdAndUpdate(chatId, conversation);
if(!updateConversation){
throw createError.InternalServerError();
}
console.log("!!!!!!!!!!! SEND EMIT FROM SOCKET/SERVER !!!!!!!!!!!!!!!");
io.emit('update-conversation', 'FROM SERVER');
io.emit('update-conversation');
io.local.emit('update-conversation');
io.local.emit('update-conversation', 'FROM SERVER');
socket.emit('update-conversation', 'FROM SERVER');
socket.emit('update-conversation');
socket.broadcast('update-conversation', 'FROM SERVER');
console.log("!!!!!!!!!!! EMIT SENDED !!!!!!!!!!!!!!!");
} catch (error) {
console.log(error);
}
});
socket.on("disconnect", () => {
console.log("########### SOCKET.IO DISCONNECTED ###########");
console.log("");
console.log("USERNAME: " + userName);
console.log("ID: " + socket.id);
console.log("");
console.log("##############################################");
});
});
httServer.listen(PORT, () => {
console.log(`SERVER RUNNING ON PORT ${PORT}`);
})

It appears you aren't yet listening for the update-conversation message in the client. Thus, when the server sends it, you don't have any client code to actually receive it.
You need to register the listener this.socket.on('update-conversation', ...) on the client-side when you first create the socket.io connection. Then, it will be ready to receive that message whenever the server sends that message.

Related

Cannot POST /api/sentiment

I'm testing the endpoint for /api/sentiment in postman and I'm not sure why I am getting the cannot POST error. I believe I'm passing the correct routes and the server is listening on port 8080. All the other endpoints run with no issue so I'm unsure what is causing the error here.
server.js file
const express = require("express");
const cors = require("cors");
const dbConfig = require("./app/config/db.config");
const app = express();
var corsOptions = {
origin: "http://localhost:8081"
};
app.use(cors(corsOptions));
// parse requests of content-type - application/json
app.use(express.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));
const db = require("./app/models");
const Role = db.role;
db.mongoose
.connect(`mongodb+srv://tami00:MEUxClWqUNbLz359#cluster0.gmvao.mongodb.net/test?retryWrites=true&w=majority`, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
console.log("Successfully connect to MongoDB.");
initial();
})
.catch(err => {
console.error("Connection error", err);
process.exit();
});
// simple route
app.use('/api/favourite', require('./app/routes/favourite.routes'));
app.use('/api/review', require('./app/routes/review.routes'));
app.use('/api/sentiment', require('./app/routes/sentiment-analysis.routes'));
// routes
// require(".app/routes/favourite.routes")(app);
require("./app/routes/auth.routes")(app);
require("./app/routes/user.routes")(app);
// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
function initial() {
Role.estimatedDocumentCount((err, count) => {
if (!err && count === 0) {
new Role({
name: "user"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'user' to roles collection");
});
new Role({
name: "creator"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'creator' to roles collection");
});
new Role({
name: "watcher"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'watcher' to roles collection");
});
}
});
}
sentiment-analysis routes file
const express = require('express');
const router = express.Router();
const getSentiment = require('../sentiment-analysis/sentimentAnalysis')
router.post('/api/sentiment', (req, res) => {
const data = req.body.data
const sentiment = getSentiment(data)
return res.send({sentiment})
})
module.exports = router;
sentimentAnalysis.js file
const aposToLexForm = require("apos-to-lex-form");
const {WordTokenizer, SentimentAnalyzer, PorterStemmer} = require("natural");
const SpellCorrector = require("spelling-corrector");
const stopword = require("stopword");
const tokenizer = new WordTokenizer();
const spellCorrector = new SpellCorrector();
spellCorrector.loadDictionary();
const analyzer = new SentimentAnalyzer('English', PorterStemmer, 'afinn')
function getSentiment(text){
if(!text.trim()) {
return 0;
}
const lexed = aposToLexForm(text).toLowerCase().replace(/[^a-zA-Z\s]+/g, "");
const tokenized = tokenizer.tokenize(lexed)
const correctSpelling = tokenized.map((word) => spellCorrector.correct(word))
const stopWordsRemoved = stopword.removeStopwords(correctSpelling)
console.log(stopWordsRemoved)
const analyzed = analyzer.getSentiment(stopWordsRemoved);
console.log(analyzed)
}
module.exports = getSentiment;
console.log(getSentiment("Wow this is fantaztic!"))
console.log(getSentiment("let's go together?"))
console.log(getSentiment("this is so bad, I hate it, it sucks!"))
I see that you use your routes like: app.use('/api/sentiment', require('./app/routes/sentiment-analysis.routes'));. But then in your sentiment-analysis you again use /api/sentiment so your request URL should be /api/sentiment/api/sentiment
Shouldn't it be:
const data = req.body.data

Agenad job is not getting start again after nodejs (express) server restart

I am using node agenda while scheduling I am able to successfully save job and its running fine. But while restarting the server the previous jobs are not getting start again. Not sure why, I tried few solutions found online but unable to make it work.
Can anyone help me with this.
I am using Nodemon with node express.
I am creating schedule using API calls
Below is app.js file
'use strict';
require('dotenv').config();
const express = require('express');
const { initialize_mongodb_database_connection } = require('./helpers/mongodb_database');
const bodyParser = require('body-parser');
const Agenda = require('agenda');
const app = express();
let logger = require('logger');
let chalk = require('chalk');
let moment = require('moment');
let mongoose = require('mongoose');
const agenda = new Agenda({
db: {address: process.env.MONGODB_URI, collection: 'scheduled_reports'},
processEvery: '30 seconds'
});
app.use(bodyParser.json());
//
// Parse application/x-www-form-urlencoded
//
app.use(bodyParser.urlencoded({extended: false}));
app.use(require('./routes/v1/schedule_report/schedule_report_routes'));
initialize_mongodb_database_connection();
sequr_app(app, [dummy_routes], {
staticDir: true,
});
let gracefulExit = function() {
if (mongoose.connection.readyState === 0) {
return process.exit(0);
}
mongoose.connection.close(function() {
return agenda.stop(function() {
logger.info({});
logger.info(chalk.bold("---------------------[ Server stopped at %s Uptime: %s ]---------------------------"), moment().format("YYYY-MM-DD HH:mm:ss.SSS"), moment.duration(process.uptime() * 1000).humanize());
return process.exit(0);
});
});
};
process.on("SIGINT", gracefulExit).on("SIGTERM", gracefulExit);
And this is my agenda file where I am routing API calls to create schedule
const Agenda = require('agenda');
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
service: 'gmail',
host: 'smtp.gmail.com',
auth: {
user: 'xx-xx#gmail.com',
pass: 'xx-xx-xx'
}
});
var mailOptions = {
from: 'example#example.com',
to: 'Example#gmail.com',
subject: 'Sending Email using Node.js',
text: 'Agenda Test'
};
const agenda = new Agenda({
db: {address: process.env.MONGODB_URI, collection: 'agendaJobs'},
processEvery: '30 seconds'
});
agenda.start();
agenda.defaultConcurrency(5);
const scheduleReport = async(report_data) => {
// HERE SCHEDULING/CREATING AGENDA SCHEDULE
agenda.on('start', job => {
console.log('-------------------------------------STARTED-----------------------------------------------');
console.log('Job %s starting', job.attrs.name);
console.log('-------------------------------------------------------------------------------------------');
});
const {
report_name,
priority
} = report_data;
agenda.define(report_name, {priority: priority, concurrency: 10}, (job, done) => {
const dateNow = new Date();
const data = job.attrs.data;
// The job.attrs.data is stored in our MongoDB collection so that it can be used to run the jobs.
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
//const date = new Date.now();
console.log('Email sent: ' + info.response + dateNow);
console.log(`Job ${job.attrs.name} finished`);
}
},done());
});
// HERE CREATING SCHEUDLE
await createWeeklySchedule(report_data);
agenda.on('complete', job => {
console.log('---------------------------------------FINISHED---------------------------------------------');
console.log(`Job ${job.attrs.name} completed succesfully...`);
console.log('--------------------------------------------------------------------------------------------');
});
}
const createWeeklySchedule = async(data) => {
const {
report_name,
schedule_info,
scheduled_timezone,
time_cron
} = data;
const weeklyReport = agenda.create(report_name, {data: schedule_info});
await agenda.start();
await agenda.every(time_cron,report_name);
console.log('Job successfully saved');
}
module.exports = scheduleReport;
Also I am starting app with app.js as main

Update user balance in realtime in the browser from private ethereum blockchain

I would like to have a website that updates live the user's wealth from a private Ethereum blockchain.
Current Solution (broken)
I opened a websocket to a private Ethereum blockchain that is mining, I would like to update my Coinbase balance on the front end. My code is as follow:
const express = require("express");
const Web3 = require("web3");
var app = express();
app.get("/", (req, res) => res.send("hello world from ping ether application"));
app.get("/ping-ether", function(req, res){
var web3 = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546'));
var event_newBlockHeaders = web3.eth.subscribe("newBlockHeaders", function(err, result){
if (err){
console.log(err)
} else {
let acctPromise = web3.eth.getAccounts().then(function(accts){
let balance = web3.eth.getBalance(accts[0]).then(function(bal){
console.log("user: ", accts[0]);
console.log("balance: ", bal);
res.end("new balance for user: " + bal)
});
});
}
});
});
// run the server
app.listen(3000, () => console.log("web app listening on port 3000"));
Clearly this is not updating live in the frontend even though the inner most callback is firing constantly as I can confirm on the console. I would like three things:
How should I change this code so that the front end has a live ticker of the coinbase balance
The code in general just smells bad with its nested promises. How can I refactor it so that I do not have to establish a websocket connection each time I navigate to /ping-ether?
Untested, but something like this should work:
const express = require("express");
const Web3 = require("web3");
var app = express();
var web3 = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546'));
var balance = -1;
web3.eth.getAccounts().then(accounts => {
return web3.eth.subscribe("newBlockHeaders", (err, result) => {
if (err) {
console.log(err);
} else {
web3.eth.getBalance(accounts[0]).then(bal => {
console.log("user: ", accounts[0]);
console.log("balance: ", bal);
balance = bal;
});
}
})
}).then(() => {
app.listen(3000, () => console.log("web app listening on port 3000"));
});
app.get("/", (req, res) => res.send("hello world from ping ether application"));
app.get("/ping-ether", function (req, res) {
res.end("new balance for user: " + balance);
});
The main idea is to set up the websocket connection and subscription once, and then just respond to incoming web requests with the current balance. I also tried to clean up the nested promises by returning the subscription promise.
Update: I ended up using websocket, here's the solution:
import * as Web3 from 'web3' ;
import * as express from 'express' ;
import * as socketIO from 'socket.io';
import * as http from 'http' ;
const CLIENT_PATH = 'path/to/directory'
var app = express();
var server = http.Server(app);
var io = socketIO(server);
var web3 = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546'));
app.get('/', (req,res) => {
res.sendFile(CLIENT_PATH + '/index.html');
});
web3.eth.getAccounts().then(accounts => {
display_account(accounts)
})
function display_account(accounts){
var user_0 = accounts[0]
web3.eth.subscribe('newBlockHeaders', (err, ret) => {
if (err){
console.log("error: ", err)
} else {
web3.eth.getBalance(user_0).then(bal => {
var msg = 'Balance for user ' + user_0 + ' is ' + bal
io.emit('message-1', msg)
console.log('emitted message: ', msg)
})
}
})
}
// use this instead of app.listen
server.listen(3000, () => {
console.log('listening on 3000')
});
And this is index.html.
<html>
<head></head>
<body>
<div id="message"></div>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
socket.on('message-1', function(msg){
console.log(msg);
document.getElementById("message").innerHTML = msg;
});
</script>
</body>
</html>

Why don't I get the push notification pop up?

I have the following code for handling & subscribing to the push notification on front-end which runs on port 4000:
var endpoint;
var key;
var authSecret;
// We need to convert the VAPID key to a base64 string when we subscribe
function urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
function determineAppServerKey() {
var vapidPublicKey = 'BAyb_WgaR0L0pODaR7wWkxJi__tWbM1MPBymyRDFEGjtDCWeRYS9EF7yGoCHLdHJi6hikYdg4MuYaK0XoD0qnoY';
return urlBase64ToUint8Array(vapidPublicKey);
}
export default function registerServiceWorker() {
if('serviceWorker' in navigator) {
navigator.serviceWorker.register(`${process.env.PUBLIC_URL}\sw.js`).then(function(register){
console.log("worked", register)
return register.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
// We already have a subscription, let's not add them again
return;
}
return register.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: determineAppServerKey()
})
.then(function(subscription) {
var rawKey = subscription.getKey ? subscription.getKey('p256dh') : '';
key = rawKey ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawKey))) : '';
var rawAuthSecret = subscription.getKey ? subscription.getKey('auth') : '';
authSecret = rawAuthSecret ?
btoa(String.fromCharCode.apply(null, new Uint8Array(rawAuthSecret))) : '';
endpoint = subscription.endpoint;
alert("came here")
return fetch('http://localhost:3111/register', {
method: 'post',
headers: new Headers({
'content-type': 'application/json'
}),
body: JSON.stringify({
endpoint: subscription.endpoint,
key: key,
authSecret: authSecret,
}),
})
});
});
}).catch(function(err){
console.log("Error",err)
})
}
}
and the server code looks like this:
const webpush = require('web-push');
const express = require('express');
var bodyParser = require('body-parser');
var path = require('path');
const app = express();
// Express setup
app.use(express.static('public'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
function saveRegistrationDetails(endpoint, key, authSecret) {
// Save the users details in a DB
}
webpush.setVapidDetails(
'mailto:contact#deanhume.com',
'BAyb_WgaR0L0pODaR7wWkxJi__tWbM1MPBymyRDFEGjtDCWeRYS9EF7yGoCHLdHJi6hikYdg4MuYaK0XoD0qnoY',
'p6YVD7t8HkABoez1CvVJ5bl7BnEdKUu5bSyVjyxMBh0'
);
// Home page
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname + '/index.html'));
});
// Article page
app.get('/article', function (req, res) {
res.sendFile(path.join(__dirname + '/article.html'));
});
// Register the user
app.post('/register', function (req, res) {
var endpoint = req.body.endpoint;
var authSecret = req.body.authSecret;
var key = req.body.key;
// Store the users registration details
saveRegistrationDetails(endpoint, key, authSecret);
const pushSubscription = {
endpoint: req.body.endpoint,
keys: {
auth: authSecret,
p256dh: key
}
};
var body = 'Thank you for registering';
var iconUrl = 'https://raw.githubusercontent.com/deanhume/progressive-web-apps-book/master/chapter-6/push-notifications/public/images/homescreen.png';
webpush.sendNotification(pushSubscription,
JSON.stringify({
msg: body,
url: 'https://localhost:3111',
icon: iconUrl,
type: 'register'
}))
.then(result => {
console.log("came here ")
console.log(result);
res.sendStatus(201);
})
.catch(err => {
console.log(err);
});
});
// The server
app.listen(3111, function () {
console.log('Example app listening on port 3111!')
});
server runs on 3111. When I navigate to 4000 port, I could able to see the Allow/Block pop up comes up and if I give Allow, I expect the server sends Thank you for registering messages as I have done in the server. However the Thank you for registering pop up doesn't comes up and there are no error in the console.
Note: I'm hitting 3111 by enabling CORS using chrome-extension.
I think that that could depend on your server, as i have a python server at home, and when i use the notification api it doesn't notify, unless I am on https sites. If that is not the problem then i would assume there is a code error, but I believe that you could use the broadcast channels and xhr such as : let b = new BroadcastChannel;b.onmessage(function(){XmlHTTPRequest('POST', {Data: "yes"})}; ) and use the xhr to push notifications.

Gmail API sending email error 401:Invalid Credentials

I'm developing with express a web page that when the client clicks in "Send E-mail" redirect to google asking for permission to send email through the client email and after the client gave the permission redirect back and send the email.
The code so far:
'use strict';
const express = require('express');
const googleAuth = require('google-auth-library');
const request = require('request');
let router = express.Router();
let app = express();
const SCOPES = [
'https://mail.google.com/'
,'https://www.googleapis.com/auth/gmail.modify'
,'https://www.googleapis.com/auth/gmail.compose'
,'https://www.googleapis.com/auth/gmail.send'
];
const clientSecret = '***********';
const clientId = '**************';
const redirectUrl = 'http://localhost:8080/access-granted';
const auth = new googleAuth();
const oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);
const authUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES
});
function sendEmail(auth, content, to , from, subject) {
let encodedMail = new Buffer(
`Content-Type: text/plain; charset="UTF-8"\n` +
`MIME-Version: 1.0\n` +
`Content-Transfer-Encoding: 7bit\n` +
`to: ${to}\n` +
`from: ${from}\n` +
`subject: ${subject}\n\n` +
content
)
.toString(`base64`)
.replace(/\+/g, '-')
.replace(/\//g, '_');
request({
method: "POST",
uri: `https://www.googleapis.com/gmail/v1/users/me/messages/send`,
headers: {
"Authorization": `Bearer ${auth}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"raw": encodedMail
})
},
function(err, response, body) {
if(err){
console.log(err); // Failure
} else {
console.log(body); // Success!
}
});
}
app.use('/static', express.static('./www'));
app.use(router)
router.get('/access-granted', (req, res) => {
sendEmail(req.query.code, 'teste email', 'teste#gmail.com', 'teste#gmail.com', 'teste');
res.sendfile('/www/html/index.html', {root: __dirname})
})
router.get('/request-access', (req, res) => {
res.redirect(authUrl);
});
router.get('/', (req, res) => {
res.sendFile('/www/html/index.html', { root: __dirname });
});
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
module.exports = app;
Every time I try to send a simple E-mail I receive the error 401: Invalid Credentials. But I'm passing in Authorization the client code auth that google sends just gave me...
The recommended way to use google APIs is to use Google API nodejs client which also provides Google OAuth flow. You can then use google.gmail('v1').users.messages.send to send the email :
const gmail = google.gmail('v1');
gmail.users.messages.send({
auth: oauth2Client,
userId: 'me',
resource: {
raw: encodedMail
}
}, function(err, req) {
if (err) {
console.log(err);
} else {
console.log(req);
}
});
auth is OAuth2, the OAuth object that can be populated with your token. You can get the token in the express session :
var oauth2Client = getOAuthClient();
oauth2Client.setCredentials(req.session["tokens"]);
which you've already stored in your OAuth callback endpoint :
var oauth2Client = getOAuthClient();
var session = req.session;
var code = req.query.code;
oauth2Client.getToken(code, function(err, tokens) {
// Now tokens contains an access_token and an optional refresh_token. Save them.
if (!err) {
oauth2Client.setCredentials(tokens);
session["tokens"] = tokens;
res.send(`<html><body><h1>Login successfull</h1><a href=/send-mail>send mail</a></body></html>`);
} else {
res.send(`<html><body><h1>Login failed</h1></body></html>`);
}
});
Here is a complete example inspired from this google API oauth for node.js example :
'use strict';
const express = require('express');
const google = require('googleapis');
const request = require('request');
const OAuth2 = google.auth.OAuth2;
const session = require('express-session');
const http = require('http');
let app = express();
app.use(session({
secret: 'some-secret',
resave: true,
saveUninitialized: true
}));
const gmail = google.gmail('v1');
const SCOPES = [
'https://mail.google.com/',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/gmail.compose',
'https://www.googleapis.com/auth/gmail.send'
];
const clientSecret = 'CLIENT_SECRET';
const clientId = 'CLIENT_ID';
const redirectUrl = 'http://localhost:8080/access-granted';
const mailContent = "test";
const mailFrom = "someemail#gmail.com";
const mailTo = "someemail#gmail.com";
const mailSubject = "subject";
function getOAuthClient() {
return new OAuth2(clientId, clientSecret, redirectUrl);
}
function getAuthUrl() {
let oauth2Client = getOAuthClient();
let url = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES,
//use this below to force approval (will generate refresh_token)
//approval_prompt : 'force'
});
return url;
}
function sendEmail(auth, content, to, from, subject, cb) {
let encodedMail = new Buffer(
`Content-Type: text/plain; charset="UTF-8"\n` +
`MIME-Version: 1.0\n` +
`Content-Transfer-Encoding: 7bit\n` +
`to: ${to}\n` +
`from: ${from}\n` +
`subject: ${subject}\n\n` +
content
)
.toString(`base64`)
.replace(/\+/g, '-')
.replace(/\//g, '_');
gmail.users.messages.send({
auth: auth,
userId: 'me',
resource: {
raw: encodedMail
}
}, cb);
}
app.use('/send-mail', (req, res) => {
let oauth2Client = getOAuthClient();
oauth2Client.setCredentials(req.session["tokens"]);
sendEmail(oauth2Client, mailContent, mailTo, mailFrom, mailSubject, function(err, response) {
if (err) {
console.log(err);
res.send(`<html><body><h1>Error</h1><a href=/send-mail>send mail</a></body></html>`);
} else {
res.send(`<html><body><h1>Send mail successfull</h1><a href=/send-mail>send mail</a></body></html>`);
}
});
});
app.use('/access-granted', (req, res) => {
let oauth2Client = getOAuthClient();
let session = req.session;
let code = req.query.code;
oauth2Client.getToken(code, function(err, tokens) {
// Now tokens contains an access_token and an optional refresh_token. Save them.
if (!err) {
oauth2Client.setCredentials(tokens);
session["tokens"] = tokens;
res.send(`<html><body><h1>Login successfull</h1><a href=/send-mail>send mail</a></body></html>`);
} else {
res.send(`<html><body><h1>Login failed</h1></body></html>`);
}
});
})
app.use('/', (req, res) => {
let url = getAuthUrl();
res.send(`<html><body><h1>Authentication using google oAuth</h1><a href=${url}>Login</a></body></html>`)
});
let port = process.env.PORT || 8080;
let server = http.createServer(app);
server.listen(port);
server.on('listening', function() {
console.log(`listening to ${port}`);
});

Categories