-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathemail-service.js
153 lines (136 loc) · 5.27 KB
/
email-service.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import fs from 'fs';
import readline from 'readline';
import chalk from 'chalk';
import { google } from 'googleapis';
export default class EmailService {
static outPutEmail = undefined;
static SCOPES = [
'https://mail.google.com/',
];
static TOKEN_PATH = 'token.json';
static oAuth2Client = null;
static async askOutPutEmail() {
return new Promise((resolve, reject) => {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question(chalk.cyan.bold('Email adress to send new releases to: '), (email) => {
rl.close();
this.outPutEmail = email;
resolve();
});
});
}
/**
* Start oAuth flow
*/
static async authenticateWithGoogle() {
return new Promise((resolve, reject) => {
// Load client secrets from a local file.
fs.readFile('credentials.json', async (err, content) => {
if (err) {
console.log(chalk.red.bold('Error loading client secret file:'), err);
reject();
}
// Authorize a client with credentials
await this.authorize(JSON.parse(content));
console.log(chalk.green.bold('Google Mail Authorization was successful.'));
resolve();
});
});
}
/**
* Create an OAuth2 client with the given credentials
* @param {Object} credentials The authorization client credentials.
*/
static async authorize(credentials) {
return new Promise((resolve, reject) => {
const { client_secret, client_id, redirect_uris } = credentials.installed;
this.oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
// Check if we have previously stored a token.
fs.readFile(this.TOKEN_PATH, async (err, token) => {
if (err) {
await this.getNewToken(this.oAuth2Client);
} else {
this.oAuth2Client.setCredentials(JSON.parse(token));
}
resolve();
});
});
}
/**
* Get and store new token after prompting for user authorization
* @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
*/
static async getNewToken(oAuth2Client) {
return new Promise((resolve, reject) => {
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: this.SCOPES,
});
console.log(chalk.cyan.bold('Authorize whiskey release radar app to send emails through this account: '), authUrl);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question(chalk.cyan.bold('Enter access token from login page: '), (code) => {
rl.close();
oAuth2Client.getToken(code, (err, token) => {
if (err) {
console.error('Error retrieving access token', err);
reject();
}
oAuth2Client.setCredentials(token);
// Store the token to disk for later program executions
fs.writeFile(this.TOKEN_PATH, JSON.stringify(token), (err) => {
if (err) return console.error(err);
console.log('Token stored to', this.TOKEN_PATH);
});
resolve();
});
});
});
}
static buildEmailRequestBody(to, from, subject, message) {
let stringArray = [
'Content-Type: text/html; charset=\'UTF-8\'\n',
'MIME-Version: 1.0\n',
'Content-Transfer-Encoding: 7bit\n',
'to: ', to, '\n',
'from: ', from, '\n',
'subject: ', subject, '\n\n',
message
].join('');
return Buffer.from(stringArray)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_');
}
static async sendReleaseAlarmEmail(arrivals, shopName) {
const auth = this.oAuth2Client;
const gmail = google.gmail({ version: 'v1', auth });
const from = 'all.my.spamm@gmail.com';
const subject = `New releases for shop ${shopName} available`;
let message =
'<h2> New releases: </h2>' +
'<table><tr><th>Name</th><th>Price</th><th>Link</th></tr>';
arrivals.forEach((product) => {
let tableRow = `<tr><td>${product.title}</td><td>${product.price}</td><td>${product.link}</td></tr>`;
message += tableRow;
});
message += '</table>';
const rawData = this.buildEmailRequestBody(this.outPutEmail, from, subject, message);
return new Promise((resolve, reject) => {
gmail.users.messages.send({
userId: 'me',
resource: {
raw: rawData
}
}, (err, res) => {
if (err) reject(err);
resolve(true);
});
});
}
}