Skip to content

Commit

Permalink
Added gmail api support for getAttachment
Browse files Browse the repository at this point in the history
  • Loading branch information
andris9 committed Jan 16, 2024
1 parent 75534ca commit 99c854b
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 11 deletions.
97 changes: 87 additions & 10 deletions lib/api-client/gmail-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const logger = require('../logger');
const util = require('util');
const addressparser = require('nodemailer/lib/addressparser');
const libmime = require('libmime');
const he = require('he');

const fs = require('fs');

Expand Down Expand Up @@ -37,6 +38,31 @@ const SYSTEM_NAMES = {
CATEGORY_PROMOTIONS: 'Promotions'
};

/*
✅ listMessages
✅ getText
✅ getMessage
case 'updateMessage':
case 'updateMessages':
✅ listMailboxes
case 'moveMessage':
case 'moveMessages':
case 'deleteMessage':
case 'deleteMessages':
case 'getRawMessage':
case 'getQuota':
case 'createMailbox':
case 'renameMailbox':
case 'deleteMailbox':
✅ getAttachment
case 'submitMessage':
case 'queueMessage':
case 'uploadMessage':
case 'subconnections':
*/

class GmailClient {
constructor(account, options) {
this.account = account;
Expand Down Expand Up @@ -75,7 +101,7 @@ class GmailClient {
await this.getClient();
}

async listMailboxes(query) {
async listMailboxes(options) {
await this.prepare();

const accessToken = await this.getToken();
Expand All @@ -85,7 +111,7 @@ class GmailClient {
let labels = labelsResult.labels.filter(label => !SKIP_LABELS.includes(label.id));

let resultLabels;
if (query && query.counters) {
if (options && options.counters) {
resultLabels = [];
for (let label of labels) {
let labelResult = await this.oAuth2Client.request(accessToken, `${GMAIL_API_BASE}/gmail/v1/users/me/labels/${label.id}`);
Expand Down Expand Up @@ -212,9 +238,11 @@ class GmailClient {

if (!/^multipart\//.test(node.mimeType)) {
if (node.body.attachmentId) {
let attachment = {
const attachmentIdProps = [messageData.id, node.mimeType || null, disposition?.value || null, node.filename || null];

const attachment = {
// append body part nr to message id
id: `${messageData.id}_${node.body.attachmentId}`,
id: `${msgpack.encode(attachmentIdProps).toString('base64url')}.${node.body.attachmentId}`,
contentType: node.mimeType,
encodedSize: node.body.size,

Expand Down Expand Up @@ -474,11 +502,11 @@ class GmailClient {
}

async getAttachmentContent(attachmentId) {
let sepPos = attachmentId.indexOf('_');
let sepPos = attachmentId.indexOf('.');
if (sepPos < 0) {
return null;
}
const messageId = attachmentId.substring(0, sepPos);
const [messageId, contentType, disposition, filename] = msgpack.decode(Buffer.from(attachmentId.substring(0, sepPos), 'base64url'));
const id = attachmentId.substring(sepPos + 1);

await this.prepare();
Expand All @@ -493,9 +521,45 @@ class GmailClient {
requestQuery
);

console.log(result);
return {
content: result?.data ? Buffer.from(result?.data, 'base64url') : null,
contentType,
disposition,
filename
};
}

async getAttachment(attachmentId) {
let attachmentData = await this.getAttachmentContent(attachmentId);

if (!attachmentData || !attachmentData.content) {
return false;
}

return result?.data ? Buffer.from(result?.data, 'base64url') : null;
let filenameParam = '';
if (attachmentData.filename) {
let isCleartextFilename = attachmentData.filename && /^[a-z0-9 _\-()^[\]~=,+*$]$/i.test(attachmentData.filename);
if (isCleartextFilename) {
filenameParam = `; filename=${JSON.stringify(attachmentData.filename)}`;
} else {
filenameParam = `; filename=${JSON.stringify(he.encode(attachmentData.filename))}; filename*=utf-8''${encodeURIComponent(
attachmentData.filename
)}`;
}
}

const content = {
headers: {
'content-type': attachmentData.mimeType || 'application/octet-stream',
'content-disposition': 'attachment' + filenameParam
},
contentType: attachmentData.contentType,
filename: attachmentData.filename,
disposition: attachmentData.disposition,
data: attachmentData.content
};

return content;
}

async getMessage(messageId, options) {
Expand Down Expand Up @@ -605,8 +669,21 @@ let main = async () => {
let raw = await gmailClient.getRawMessage(msg.id);
await fs.promises.writeFile(`/Users/andris/Desktop/${msg.id}.eml`, raw);
for (let a of msg.attachments) {
let attachment = await gmailClient.getAttachmentContent(a.id);
await fs.promises.writeFile(`/Users/andris/Desktop/${a.filename}`, attachment);
let attachment = await gmailClient.getAttachment(a.id);
console.log(attachment);
let s = fs.createWriteStream(`/Users/andris/Desktop/${a.filename}`);

console.log('PIPING TO STREAM');
await new Promise((r, e) => {
s.once('finish', r);
s.once('error', e);

s.write(attachment.data);
s.end();
});
console.log('DONE');

//await fs.promises.writeFile(`/Users/andris/Desktop/${a.filename}`, attachment);
process.exit();
}
}
Expand Down
6 changes: 5 additions & 1 deletion workers/imap.js
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,11 @@ class ConnectionHandler {
}

setImmediate(() => {
source.pipe(stream);
if (Buffer.isBuffer(source.data)) {
stream.end(source.data);
} else {
source.pipe(stream);
}
});

return {
Expand Down

0 comments on commit 99c854b

Please sign in to comment.