n8n-nodes-gmail-custom 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
const crypto = require('crypto');
|
|
2
2
|
|
|
3
|
+
let jwtLib;
|
|
4
|
+
try { jwtLib = require('jsonwebtoken'); } catch (e) {}
|
|
5
|
+
|
|
3
6
|
const TOKEN_CACHE = {};
|
|
4
7
|
|
|
5
8
|
function formatPrivateKey(privateKey) {
|
|
@@ -158,6 +161,58 @@ async function buildMimeMessage(options) {
|
|
|
158
161
|
.replace(/=+$/, '');
|
|
159
162
|
}
|
|
160
163
|
|
|
164
|
+
async function getOrRefreshAccessToken(ctx, credentials, fromEmail) {
|
|
165
|
+
const cacheKey = `${credentials.email}:${fromEmail}`;
|
|
166
|
+
let token = TOKEN_CACHE[cacheKey];
|
|
167
|
+
if (token && token.expiresAt > Date.now()) {
|
|
168
|
+
return token.accessToken;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const privateKey = formatPrivateKey(credentials.privateKey);
|
|
172
|
+
const now = Math.floor(Date.now() / 1000);
|
|
173
|
+
|
|
174
|
+
let jwt;
|
|
175
|
+
const payload = {
|
|
176
|
+
iss: credentials.email,
|
|
177
|
+
scope: 'https://mail.google.com/',
|
|
178
|
+
aud: 'https://oauth2.googleapis.com/token',
|
|
179
|
+
exp: now + 3600,
|
|
180
|
+
iat: now,
|
|
181
|
+
sub: fromEmail,
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
if (jwtLib) {
|
|
185
|
+
jwt = jwtLib.sign(payload, privateKey, {
|
|
186
|
+
algorithm: 'RS256',
|
|
187
|
+
header: { kid: privateKey, typ: 'JWT', alg: 'RS256' },
|
|
188
|
+
});
|
|
189
|
+
} else {
|
|
190
|
+
const header = { alg: 'RS256', typ: 'JWT', kid: privateKey };
|
|
191
|
+
const signatureInput = base64UrlEncode(JSON.stringify(header)) + '.' + base64UrlEncode(JSON.stringify(payload));
|
|
192
|
+
const signer = crypto.createSign('RSA-SHA256');
|
|
193
|
+
signer.update(signatureInput);
|
|
194
|
+
const sig = signer.sign(privateKey);
|
|
195
|
+
jwt = signatureInput + '.' + base64urlEscape(sig.toString('base64'));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const response = await ctx.helpers.httpRequest({
|
|
199
|
+
method: 'POST',
|
|
200
|
+
url: 'https://oauth2.googleapis.com/token',
|
|
201
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
202
|
+
body: new URLSearchParams({
|
|
203
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
|
|
204
|
+
assertion: jwt,
|
|
205
|
+
}).toString(),
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
TOKEN_CACHE[cacheKey] = {
|
|
209
|
+
accessToken: response.access_token,
|
|
210
|
+
expiresAt: Date.now() + 3500 * 1000,
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
return response.access_token;
|
|
214
|
+
}
|
|
215
|
+
|
|
161
216
|
class GmailCustom {
|
|
162
217
|
|
|
163
218
|
constructor() {
|
|
@@ -303,10 +358,15 @@ class GmailCustom {
|
|
|
303
358
|
|
|
304
359
|
async execute() {
|
|
305
360
|
const items = this.getInputData();
|
|
361
|
+
if (!items || items.length === 0) {
|
|
362
|
+
return [[]];
|
|
363
|
+
}
|
|
364
|
+
|
|
306
365
|
const returnData = [];
|
|
307
366
|
|
|
308
367
|
for (let i = 0; i < items.length; i++) {
|
|
309
368
|
try {
|
|
369
|
+
const item = items[i];
|
|
310
370
|
const fromEmail = this.getNodeParameter('fromEmail', i, '');
|
|
311
371
|
const sendTo = this.getNodeParameter('sendTo', i, '');
|
|
312
372
|
const subject = this.getNodeParameter('subject', i, '');
|
|
@@ -336,59 +396,15 @@ class GmailCustom {
|
|
|
336
396
|
}
|
|
337
397
|
|
|
338
398
|
if (appendAttribution) {
|
|
339
|
-
const attributionText = '\n\n---\nThis email was sent automatically with n8n';
|
|
340
399
|
if (emailType === 'html') {
|
|
341
400
|
bodyHtml += '<br><br>---<br><em>This email was sent automatically with n8n</em>';
|
|
342
401
|
} else {
|
|
343
|
-
bodyText +=
|
|
402
|
+
bodyText += '\n\n---\nThis email was sent automatically with n8n';
|
|
344
403
|
}
|
|
345
404
|
}
|
|
346
405
|
|
|
347
406
|
const credentials = await this.getCredentials('googleApi');
|
|
348
|
-
const
|
|
349
|
-
let accessToken;
|
|
350
|
-
let expiresAt = 0;
|
|
351
|
-
|
|
352
|
-
if (TOKEN_CACHE[cacheKey]) {
|
|
353
|
-
expiresAt = TOKEN_CACHE[cacheKey].expiresAt;
|
|
354
|
-
accessToken = TOKEN_CACHE[cacheKey].accessToken;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
if (!accessToken || Date.now() >= expiresAt) {
|
|
358
|
-
const privateKey = formatPrivateKey(credentials.privateKey);
|
|
359
|
-
const now = Math.floor(Date.now() / 1000);
|
|
360
|
-
const header = { alg: 'RS256', typ: 'JWT', kid: privateKey };
|
|
361
|
-
const payload = {
|
|
362
|
-
iss: credentials.email,
|
|
363
|
-
scope: 'https://mail.google.com/',
|
|
364
|
-
aud: 'https://oauth2.googleapis.com/token',
|
|
365
|
-
exp: now + 3600,
|
|
366
|
-
iat: now,
|
|
367
|
-
sub: fromEmail,
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
const signatureInput = base64UrlEncode(JSON.stringify(header)) + '.' + base64UrlEncode(JSON.stringify(payload));
|
|
371
|
-
const signer = crypto.createSign('RSA-SHA256');
|
|
372
|
-
signer.update(signatureInput);
|
|
373
|
-
const sig = signer.sign(privateKey);
|
|
374
|
-
const jwt = signatureInput + '.' + base64urlEscape(sig.toString('base64'));
|
|
375
|
-
|
|
376
|
-
const response = await this.helpers.httpRequest({
|
|
377
|
-
method: 'POST',
|
|
378
|
-
url: 'https://oauth2.googleapis.com/token',
|
|
379
|
-
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
380
|
-
body: new URLSearchParams({
|
|
381
|
-
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
|
|
382
|
-
assertion: jwt,
|
|
383
|
-
}).toString(),
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
accessToken = response.access_token;
|
|
387
|
-
TOKEN_CACHE[cacheKey] = {
|
|
388
|
-
accessToken,
|
|
389
|
-
expiresAt: Date.now() + 3500 * 1000,
|
|
390
|
-
};
|
|
391
|
-
}
|
|
407
|
+
const accessToken = await getOrRefreshAccessToken(this, credentials, fromEmail);
|
|
392
408
|
|
|
393
409
|
let attachments = [];
|
|
394
410
|
if (options.attachmentsUi && options.attachmentsUi.attachmentsBinary) {
|
|
@@ -461,10 +477,11 @@ class GmailCustom {
|
|
|
461
477
|
if (lastError) throw lastError;
|
|
462
478
|
|
|
463
479
|
} catch (error) {
|
|
464
|
-
|
|
480
|
+
let continueOnFail = false;
|
|
481
|
+
try { continueOnFail = this.continueOnFail(); } catch (e) {}
|
|
465
482
|
if (continueOnFail) {
|
|
466
483
|
returnData.push({
|
|
467
|
-
json: { error: error.message },
|
|
484
|
+
json: { error: error.message || 'Unknown error' },
|
|
468
485
|
pairedItem: { item: i },
|
|
469
486
|
});
|
|
470
487
|
continue;
|