From 7646db23e96fb8afc56ed81f51f32649ffbeda5a Mon Sep 17 00:00:00 2001 From: Andris Reinman Date: Tue, 16 Apr 2024 16:57:48 +0300 Subject: [PATCH] Gmail API support update --- lib/api-client/gmail-client.js | 92 +++++++++++++++++----------------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/lib/api-client/gmail-client.js b/lib/api-client/gmail-client.js index e3cf0676..ca9b0b5a 100644 --- a/lib/api-client/gmail-client.js +++ b/lib/api-client/gmail-client.js @@ -41,7 +41,7 @@ const SYSTEM_NAMES = { ✅ listMessages ❌ paging - not implemented - ❌ search - not implemented + - search - partially implemented, missing emailId, threadId ✅ getText ✅ getMessage case 'updateMessage': @@ -186,9 +186,19 @@ class GmailClient extends BaseClient { if (!label) { return false; } - requestQuery.labelIds = label.id; + requestQuery.labelIds = [label.id]; } + if (query.search) { + // NB! Might throw if using unsupported search terms + const preparedQuery = this.prepareQuery(query.search); + if (preparedQuery) { + requestQuery.q = this.prepareQuery(query.search); + } + } + + console.log('REQUEST QUERY', requestQuery); + let messageList = []; let listingResult = await this.oAuth2Client.request(accessToken, `${GMAIL_API_BASE}/gmail/v1/users/me/messages`, 'get', requestQuery); @@ -716,75 +726,67 @@ class GmailClient extends BaseClient { } // convert IMAP SEARCH query object to a Gmail API search query - prepareQuery(path, query) { - let queryParts = []; + prepareQuery(search) { + search = search || {}; + + const queryParts = []; // FIXME: emailId, threadId + // not supported search terms for (let disabledKey of ['seq', 'uid', 'paths', 'answered', 'deleted', 'draft']) { - let error = new Error(`Unsupported search term "${disabledKey}"`); - error.code = 'UnsupportedSearchTerm'; - throw error; - } - - if (path) { - let key; - let label; - for (let sysPath of Object.keys(SYSTEM_NAMES)) { - if (SYSTEM_NAMES[sysPath].toLowerCase().trim() === path.toLowerCase().trim()) { - // found match - if (/^CATEGORY_/.test(sysPath)) { - key = 'category'; - label = sysPath.split('_').pop().toLowerCase().trim(); - } else { - key = 'in'; - label = sysPath.toLowerCase(); - } - break; - } + if (disabledKey in search) { + let error = new Error(`Unsupported search term "${disabledKey}"`); + error.code = 'UnsupportedSearchTerm'; + throw error; } - if (!key) { - key = 'label'; - label = path.toLowerCase().trim(); - } - queryParts.push(`${key}:${this.formatSearchTerm(label)}`); } - if (typeof query.search.unseen === 'boolean') { - queryParts.push(`${!query.search.flagged ? '-' : ''}is:starred`); + // flagged + if (typeof search.flagged === 'boolean') { + queryParts.push(`${!search.flagged ? '-' : ''}is:starred`); } - if (typeof query.search.unseen === 'boolean') { - queryParts.push(`is:${query.search.unseen ? 'unread' : 'read'}`); + // unseen + if (typeof search.unseen === 'boolean') { + queryParts.push(`is:${search.unseen ? 'unread' : 'read'}`); } - if (typeof query.search.seen === 'boolean') { - queryParts.push(`is:${query.search.unseen ? 'read' : 'unread'}`); + // seen + if (typeof search.seen === 'boolean') { + queryParts.push(`is:${search.unseen ? 'read' : 'unread'}`); } for (let key of ['from', 'to', 'cc', 'bcc', 'subject']) { - if (query.search[key]) { - queryParts.push(`${key}:${this.formatSearchTerm(query.search[key])}`); + if (search[key]) { + queryParts.push(`${key}:${this.formatSearchTerm(search[key])}`); } } - for (let headerKey of Object.keys(query.search.header || {})) { + for (let headerKey of Object.keys(search.header || {})) { switch (headerKey.toLowerCase().trim()) { case 'message-id': - queryParts.push(`rfc822msgid:${this.formatSearchTerm(query.search.header[headerKey])}`); + queryParts.push(`rfc822msgid:${this.formatSearchTerm(search.header[headerKey])}`); break; + default: { + let error = new Error(`Unsupported search header "${headerKey}"`); + error.code = 'UnsupportedSearchTerm'; + throw error; + } } } - if (query.search.gmailRaw && typeof query.search.gmailRaw === 'string') { - queryParts.push(query.search.gmailRaw); + // whatever is used in the raw search, just prepend + if (search.gmailRaw && typeof search.gmailRaw === 'string') { + queryParts.push(search.gmailRaw); } - if (query.search.body && typeof query.search.body === 'string') { - queryParts.push(`${this.formatSearchTerm(query.search.body)}`); + // body search + if (search.body && typeof search.body === 'string') { + queryParts.push(`${this.formatSearchTerm(search.body)}`); } - return queryParts.join(' '); + return queryParts.join(' ').trim(); } } @@ -801,7 +803,7 @@ if (/gmail-client\.js$/.test(process.argv[1])) { let mailboxes = await gmailClient.listMailboxes(); console.log(mailboxes); - let messages = await gmailClient.listMessages({ path: 'INBOX' }); + let messages = await gmailClient.listMessages({ path: 'INBOX', search: { from: 'notify@chartmogul.com' } }); console.log(JSON.stringify(messages, false, 2)); let deleted = false;