@guayaba/workflow-piece-gmail 0.12.3
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.
- package/.babelrc +3 -0
- package/.eslintrc.json +37 -0
- package/README.md +5 -0
- package/assets/logo.png +0 -0
- package/package.json +31 -0
- package/src/i18n/ca.json +63 -0
- package/src/i18n/de.json +129 -0
- package/src/i18n/es.json +129 -0
- package/src/i18n/fr.json +129 -0
- package/src/i18n/hi.json +63 -0
- package/src/i18n/id.json +63 -0
- package/src/i18n/ja.json +129 -0
- package/src/i18n/nl.json +129 -0
- package/src/i18n/pt.json +129 -0
- package/src/i18n/ru.json +63 -0
- package/src/i18n/translation.json +129 -0
- package/src/i18n/vi.json +63 -0
- package/src/i18n/zh.json +129 -0
- package/src/index.ts +69 -0
- package/src/lib/actions/create-draft-reply-action.ts +306 -0
- package/src/lib/actions/get-mail-action.ts +44 -0
- package/src/lib/actions/get-thread-action.ts +39 -0
- package/src/lib/actions/reply-to-email-action.ts +220 -0
- package/src/lib/actions/request-approval-in-email.ts +194 -0
- package/src/lib/actions/search-email-action.ts +211 -0
- package/src/lib/actions/send-email-action.ts +205 -0
- package/src/lib/auth.ts +116 -0
- package/src/lib/common/data.ts +268 -0
- package/src/lib/common/models.ts +91 -0
- package/src/lib/common/props.ts +256 -0
- package/src/lib/triggers/new-attachment.ts +198 -0
- package/src/lib/triggers/new-conversation.ts +413 -0
- package/src/lib/triggers/new-email.ts +167 -0
- package/src/lib/triggers/new-label.ts +77 -0
- package/src/lib/triggers/new-labeled-email.ts +192 -0
- package/tsconfig.json +16 -0
- package/tsconfig.lib.json +15 -0
package/src/lib/auth.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AppConnectionValueForAuthProperty,
|
|
3
|
+
PieceAuth,
|
|
4
|
+
Property,
|
|
5
|
+
} from '@guayaba/workflows-framework';
|
|
6
|
+
import { AppConnectionType } from '@guayaba/workflows-shared';
|
|
7
|
+
import { google } from 'googleapis';
|
|
8
|
+
import { OAuth2Client } from 'googleapis-common';
|
|
9
|
+
|
|
10
|
+
const gmailServiceAccountScopes = [
|
|
11
|
+
'https://www.googleapis.com/auth/gmail.send',
|
|
12
|
+
'https://www.googleapis.com/auth/gmail.readonly',
|
|
13
|
+
'https://www.googleapis.com/auth/gmail.compose',
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
export const gmailScopes = [...gmailServiceAccountScopes, 'email'];
|
|
17
|
+
|
|
18
|
+
export const gmailAuth = [
|
|
19
|
+
PieceAuth.OAuth2({
|
|
20
|
+
description: '',
|
|
21
|
+
authUrl: 'https://accounts.google.com/o/oauth2/auth',
|
|
22
|
+
tokenUrl: 'https://oauth2.googleapis.com/token',
|
|
23
|
+
required: true,
|
|
24
|
+
scope: gmailScopes,
|
|
25
|
+
}),
|
|
26
|
+
PieceAuth.CustomAuth({
|
|
27
|
+
displayName: 'Service Account (Advanced)',
|
|
28
|
+
description:
|
|
29
|
+
'Authenticate via service account from https://console.cloud.google.com/ > IAM & Admin > Service Accounts > Create Service Account > Keys > Add key. <br> <br> You can optionally use domain-wide delegation (https://support.google.com/a/answer/162106?hl=en#zippy=%2Cset-up-domain-wide-delegation-for-a-client) to access Gmail without adding the service account to each mailbox. <br> <br> **Note:** A user email with domain-wide delegation is required for Gmail service account access.',
|
|
30
|
+
required: true,
|
|
31
|
+
props: {
|
|
32
|
+
serviceAccount: Property.LongText({
|
|
33
|
+
displayName: 'Service Account JSON Key',
|
|
34
|
+
required: true,
|
|
35
|
+
}),
|
|
36
|
+
userEmail: Property.ShortText({
|
|
37
|
+
displayName: 'User Email',
|
|
38
|
+
required: true,
|
|
39
|
+
description:
|
|
40
|
+
'Email address of the user to impersonate. Required for Gmail service account access via domain-wide delegation.',
|
|
41
|
+
}),
|
|
42
|
+
},
|
|
43
|
+
validate: async ({ auth }) => {
|
|
44
|
+
try {
|
|
45
|
+
await getAccessToken({
|
|
46
|
+
type: AppConnectionType.CUSTOM_AUTH,
|
|
47
|
+
props: { ...auth },
|
|
48
|
+
});
|
|
49
|
+
} catch (e) {
|
|
50
|
+
return {
|
|
51
|
+
valid: false,
|
|
52
|
+
error: (e as Error).message,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
valid: true,
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
}),
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
export type GmailAuthValue = AppConnectionValueForAuthProperty<
|
|
63
|
+
typeof gmailAuth
|
|
64
|
+
>;
|
|
65
|
+
|
|
66
|
+
export async function createGoogleClient(
|
|
67
|
+
auth: GmailAuthValue
|
|
68
|
+
): Promise<OAuth2Client> {
|
|
69
|
+
if (auth.type === AppConnectionType.CUSTOM_AUTH) {
|
|
70
|
+
let serviceAccount;
|
|
71
|
+
try {
|
|
72
|
+
serviceAccount = JSON.parse(auth.props.serviceAccount);
|
|
73
|
+
} catch {
|
|
74
|
+
throw new Error(
|
|
75
|
+
'Invalid Service Account JSON Key. Please provide a valid JSON string.'
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
return new google.auth.JWT({
|
|
79
|
+
email: serviceAccount.client_email,
|
|
80
|
+
key: serviceAccount.private_key,
|
|
81
|
+
scopes: gmailServiceAccountScopes,
|
|
82
|
+
subject: auth.props.userEmail?.trim() || undefined,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
const authClient = new OAuth2Client();
|
|
86
|
+
authClient.setCredentials(auth);
|
|
87
|
+
return authClient;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export const getAccessToken = async (auth: GmailAuthValue): Promise<string> => {
|
|
91
|
+
if (auth.type === AppConnectionType.CUSTOM_AUTH) {
|
|
92
|
+
const googleClient = await createGoogleClient(auth);
|
|
93
|
+
const response = await googleClient.getAccessToken();
|
|
94
|
+
if (response.token) {
|
|
95
|
+
return response.token;
|
|
96
|
+
} else {
|
|
97
|
+
throw new Error(
|
|
98
|
+
'Could not retrieve access token from service account json'
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return auth.access_token;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export async function getUserEmail(
|
|
106
|
+
auth: GmailAuthValue,
|
|
107
|
+
authClient: OAuth2Client
|
|
108
|
+
): Promise<string | undefined> {
|
|
109
|
+
if (auth.type === AppConnectionType.CUSTOM_AUTH) {
|
|
110
|
+
return auth.props.userEmail?.trim();
|
|
111
|
+
}
|
|
112
|
+
return (
|
|
113
|
+
(await google.oauth2({ version: 'v2', auth: authClient }).userinfo.get())
|
|
114
|
+
.data.email ?? undefined
|
|
115
|
+
);
|
|
116
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { FilesService } from '@guayaba/workflows-framework';
|
|
2
|
+
import {
|
|
3
|
+
GmailLabel,
|
|
4
|
+
GmailMessage,
|
|
5
|
+
GmailThread,
|
|
6
|
+
GmailMessageFormat,
|
|
7
|
+
GmailMessageResponse as GmailMessageList,
|
|
8
|
+
} from './models';
|
|
9
|
+
import {
|
|
10
|
+
AuthenticationType,
|
|
11
|
+
httpClient,
|
|
12
|
+
HttpMethod,
|
|
13
|
+
} from '@guayaba/workflows-common';
|
|
14
|
+
import { Attachment, ParsedMail, simpleParser } from 'mailparser';
|
|
15
|
+
import { GmailAuthValue, getAccessToken } from '../auth';
|
|
16
|
+
|
|
17
|
+
interface SearchMailProps {
|
|
18
|
+
access_token: string;
|
|
19
|
+
from: string;
|
|
20
|
+
to: string;
|
|
21
|
+
subject?: string;
|
|
22
|
+
label: GmailLabel;
|
|
23
|
+
category: string;
|
|
24
|
+
after?: number;
|
|
25
|
+
before?: number;
|
|
26
|
+
max_results?: number;
|
|
27
|
+
page_token?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface GetMailProps {
|
|
31
|
+
access_token: string;
|
|
32
|
+
message_id?: string;
|
|
33
|
+
thread_id?: string;
|
|
34
|
+
format: GmailMessageFormat;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const GmailRequests = {
|
|
38
|
+
getMail: async ({ access_token, format, message_id }: GetMailProps) => {
|
|
39
|
+
const response = await httpClient.sendRequest<GmailMessage>({
|
|
40
|
+
method: HttpMethod.GET,
|
|
41
|
+
url: `https://gmail.googleapis.com/gmail/v1/users/me/messages/${message_id}`,
|
|
42
|
+
authentication: {
|
|
43
|
+
type: AuthenticationType.BEARER_TOKEN,
|
|
44
|
+
token: access_token,
|
|
45
|
+
},
|
|
46
|
+
queryParams: {
|
|
47
|
+
format,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
let bodyHtml = '';
|
|
51
|
+
let bodyPlain = '';
|
|
52
|
+
const payload = response.body.payload;
|
|
53
|
+
let bodyParts = payload.parts || [];
|
|
54
|
+
const headers = payload.headers.reduce(
|
|
55
|
+
(obj: { [key: string]: string }, header) => {
|
|
56
|
+
obj[header.name.toLowerCase()] = header.value;
|
|
57
|
+
return obj;
|
|
58
|
+
},
|
|
59
|
+
{}
|
|
60
|
+
);
|
|
61
|
+
const alternateBodyPart = bodyParts.find((part) =>
|
|
62
|
+
part.mimeType.startsWith('multipart/alternative')
|
|
63
|
+
);
|
|
64
|
+
if (alternateBodyPart && alternateBodyPart?.parts) {
|
|
65
|
+
bodyParts = alternateBodyPart.parts;
|
|
66
|
+
}
|
|
67
|
+
const subject = headers['subject'] || '';
|
|
68
|
+
// Determine the content type of the message body
|
|
69
|
+
const contentType = headers['content-type'] || 'text/plain';
|
|
70
|
+
const isMultipart = contentType.startsWith('multipart/');
|
|
71
|
+
|
|
72
|
+
if (isMultipart) {
|
|
73
|
+
// If the message is multipart, extract the plain text and HTML parts
|
|
74
|
+
const textPart = bodyParts.find((part) => part.mimeType === 'text/plain');
|
|
75
|
+
const htmlPart = bodyParts.find((part) => part.mimeType === 'text/html');
|
|
76
|
+
|
|
77
|
+
// If the message is an "alternative" multipart, use the plain text part if it exists
|
|
78
|
+
const preferredPart = textPart || htmlPart;
|
|
79
|
+
bodyHtml = htmlPart ? decodeBase64(htmlPart.body.data) : '';
|
|
80
|
+
bodyPlain = preferredPart ? decodeBase64(preferredPart.body.data) : '';
|
|
81
|
+
} else {
|
|
82
|
+
// If the message is not multipart, use the body as-is
|
|
83
|
+
bodyPlain = decodeBase64(payload.body.data);
|
|
84
|
+
bodyHtml = '';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
subject: subject,
|
|
89
|
+
body_html: bodyHtml,
|
|
90
|
+
body_plain: bodyPlain,
|
|
91
|
+
...response.body,
|
|
92
|
+
};
|
|
93
|
+
},
|
|
94
|
+
getThread: async ({ access_token, format, thread_id }: GetMailProps) => {
|
|
95
|
+
const response = await httpClient.sendRequest<GmailThread>({
|
|
96
|
+
method: HttpMethod.GET,
|
|
97
|
+
url: `https://gmail.googleapis.com/gmail/v1/users/me/threads/${thread_id}`,
|
|
98
|
+
authentication: {
|
|
99
|
+
type: AuthenticationType.BEARER_TOKEN,
|
|
100
|
+
token: access_token,
|
|
101
|
+
},
|
|
102
|
+
queryParams: {
|
|
103
|
+
format,
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
return response.body;
|
|
108
|
+
},
|
|
109
|
+
getLabels: async (authentication: GmailAuthValue) => {
|
|
110
|
+
return await httpClient.sendRequest<{ labels: GmailLabel[] }>({
|
|
111
|
+
method: HttpMethod.GET,
|
|
112
|
+
url: `https://gmail.googleapis.com/gmail/v1/users/me/labels`,
|
|
113
|
+
authentication: {
|
|
114
|
+
type: AuthenticationType.BEARER_TOKEN,
|
|
115
|
+
token: await getAccessToken(authentication),
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
},
|
|
119
|
+
searchMail: async ({
|
|
120
|
+
access_token,
|
|
121
|
+
max_results = 1,
|
|
122
|
+
page_token: pageToken,
|
|
123
|
+
...mail
|
|
124
|
+
}: SearchMailProps) => {
|
|
125
|
+
const query = [];
|
|
126
|
+
|
|
127
|
+
if (mail.from) query.push(`from:(${mail.from})`);
|
|
128
|
+
if (mail.to) query.push(`to:(${mail.to})`);
|
|
129
|
+
if (mail.subject) query.push(`subject:(${mail.subject})`);
|
|
130
|
+
if (mail.label) query.push(`label:${mail.label.name}`);
|
|
131
|
+
if (mail.category) query.push(`category:${mail.category}`);
|
|
132
|
+
if (mail.after != null && mail.after > 0) query.push(`after:${mail.after}`);
|
|
133
|
+
if (mail.before != null) query.push(`before:${mail.before}`);
|
|
134
|
+
|
|
135
|
+
const response = await httpClient.sendRequest<GmailMessageList>({
|
|
136
|
+
method: HttpMethod.GET,
|
|
137
|
+
url: `https://www.googleapis.com/gmail/v1/users/me/messages`,
|
|
138
|
+
authentication: {
|
|
139
|
+
type: AuthenticationType.BEARER_TOKEN,
|
|
140
|
+
token: access_token,
|
|
141
|
+
},
|
|
142
|
+
queryParams: {
|
|
143
|
+
q: query.join(' '),
|
|
144
|
+
maxResults: `${max_results}`,
|
|
145
|
+
...(pageToken ? { pageToken } : {}),
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
if (response.body.messages) {
|
|
150
|
+
const messages = await Promise.all(
|
|
151
|
+
response.body.messages.map(
|
|
152
|
+
async (message: { id: string; threadId: string }) => {
|
|
153
|
+
const mail = await GmailRequests.getMail({
|
|
154
|
+
access_token,
|
|
155
|
+
message_id: message.id,
|
|
156
|
+
format: GmailMessageFormat.FULL,
|
|
157
|
+
});
|
|
158
|
+
const thread = await GmailRequests.getThread({
|
|
159
|
+
access_token,
|
|
160
|
+
thread_id: message.threadId,
|
|
161
|
+
format: GmailMessageFormat.FULL,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
message: mail,
|
|
166
|
+
thread,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
messages,
|
|
174
|
+
resultSizeEstimate: response.body.resultSizeEstimate,
|
|
175
|
+
...(response?.body.nextPageToken
|
|
176
|
+
? { nextPageToken: response.body.nextPageToken }
|
|
177
|
+
: {}),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return response.body;
|
|
182
|
+
},
|
|
183
|
+
getRecentMessages: async (
|
|
184
|
+
authentication: GmailAuthValue,
|
|
185
|
+
maxResults = 20
|
|
186
|
+
) => {
|
|
187
|
+
return await httpClient.sendRequest<GmailMessageList>({
|
|
188
|
+
method: HttpMethod.GET,
|
|
189
|
+
url: 'https://gmail.googleapis.com/gmail/v1/users/me/messages',
|
|
190
|
+
authentication: {
|
|
191
|
+
type: AuthenticationType.BEARER_TOKEN,
|
|
192
|
+
token: await getAccessToken(authentication),
|
|
193
|
+
},
|
|
194
|
+
queryParams: {
|
|
195
|
+
maxResults: maxResults.toString(),
|
|
196
|
+
q: 'in:inbox OR in:sent', // Get recent messages from inbox and sent
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
},
|
|
200
|
+
getRecentThreads: async (authentication: GmailAuthValue, maxResults = 15) => {
|
|
201
|
+
return await httpClient.sendRequest<{
|
|
202
|
+
threads: { id: string; snippet?: string }[];
|
|
203
|
+
}>({
|
|
204
|
+
method: HttpMethod.GET,
|
|
205
|
+
url: 'https://gmail.googleapis.com/gmail/v1/users/me/threads',
|
|
206
|
+
authentication: {
|
|
207
|
+
type: AuthenticationType.BEARER_TOKEN,
|
|
208
|
+
token: await getAccessToken(authentication),
|
|
209
|
+
},
|
|
210
|
+
queryParams: {
|
|
211
|
+
maxResults: maxResults.toString(),
|
|
212
|
+
q: 'in:inbox OR in:sent', // Get recent threads from inbox and sent
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
function decodeBase64(data: any) {
|
|
219
|
+
return Buffer.from(data, 'base64').toString();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export async function parseStream(stream: any) {
|
|
223
|
+
return new Promise<ParsedMail>((resolve, reject) => {
|
|
224
|
+
simpleParser(stream, (err, parsed) => {
|
|
225
|
+
if (err) {
|
|
226
|
+
reject(err);
|
|
227
|
+
} else {
|
|
228
|
+
resolve(parsed);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export async function convertAttachment(
|
|
235
|
+
attachments: Attachment[],
|
|
236
|
+
files: FilesService
|
|
237
|
+
) {
|
|
238
|
+
const promises = attachments.map(async (attachment) => {
|
|
239
|
+
try {
|
|
240
|
+
const fileName = attachment.filename ?? `attachment-${Date.now()}`;
|
|
241
|
+
return {
|
|
242
|
+
fileName,
|
|
243
|
+
mimeType: attachment.contentType,
|
|
244
|
+
size: attachment.size,
|
|
245
|
+
data: await files.write({
|
|
246
|
+
fileName: fileName,
|
|
247
|
+
data: attachment.content,
|
|
248
|
+
}),
|
|
249
|
+
};
|
|
250
|
+
} catch (error) {
|
|
251
|
+
console.error(
|
|
252
|
+
`Failed to process attachment: ${attachment.filename}`,
|
|
253
|
+
error
|
|
254
|
+
);
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
const results = await Promise.all(promises);
|
|
259
|
+
return results.filter((result) => result !== null);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function getFirstFiveOrAll(array: unknown[]) {
|
|
263
|
+
if (array.length <= 5) {
|
|
264
|
+
return array;
|
|
265
|
+
} else {
|
|
266
|
+
return array.slice(0, 5);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export interface GmailLabel {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
messageListVisibility: GmailMessageListVisibility;
|
|
5
|
+
labelListVisibility: GmailLabelListVisibility;
|
|
6
|
+
type: GmailLabelType;
|
|
7
|
+
messagesTotal: number;
|
|
8
|
+
messagesUnread: number;
|
|
9
|
+
threadsTotal: number;
|
|
10
|
+
threadsUnread: number;
|
|
11
|
+
color: {
|
|
12
|
+
textColor: string;
|
|
13
|
+
backgroundColor: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface GmailMessage {
|
|
18
|
+
id: string;
|
|
19
|
+
threadId: string;
|
|
20
|
+
labelIds: [string];
|
|
21
|
+
snippet: string;
|
|
22
|
+
historyId: string;
|
|
23
|
+
internalDate: number;
|
|
24
|
+
payload: {
|
|
25
|
+
partId: string;
|
|
26
|
+
mimeType: string;
|
|
27
|
+
filename: string;
|
|
28
|
+
headers: {
|
|
29
|
+
name: string;
|
|
30
|
+
value: string;
|
|
31
|
+
}[];
|
|
32
|
+
body: {
|
|
33
|
+
data: any;
|
|
34
|
+
size: number;
|
|
35
|
+
};
|
|
36
|
+
parts: {
|
|
37
|
+
parts: any[];
|
|
38
|
+
partId: string;
|
|
39
|
+
mimeType: string;
|
|
40
|
+
filename: string;
|
|
41
|
+
headers: {
|
|
42
|
+
name: string;
|
|
43
|
+
value: string;
|
|
44
|
+
}[];
|
|
45
|
+
body: {
|
|
46
|
+
size: number;
|
|
47
|
+
data: string;
|
|
48
|
+
};
|
|
49
|
+
}[];
|
|
50
|
+
};
|
|
51
|
+
sizeEstimate: number;
|
|
52
|
+
raw: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface GmailThread {
|
|
56
|
+
id: string;
|
|
57
|
+
snippet: string;
|
|
58
|
+
historyId: string;
|
|
59
|
+
messages: GmailMessage[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface GmailMessageResponse {
|
|
63
|
+
messages: {
|
|
64
|
+
id: string;
|
|
65
|
+
threadId: string;
|
|
66
|
+
}[];
|
|
67
|
+
nextPageToken?: string;
|
|
68
|
+
resultSizeEstimate: number;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
enum GmailMessageListVisibility {
|
|
72
|
+
SHOW = 'show',
|
|
73
|
+
HIDE = 'hide',
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
enum GmailLabelListVisibility {
|
|
77
|
+
SHOW = 'show',
|
|
78
|
+
HIDE = 'hide',
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
enum GmailLabelType {
|
|
82
|
+
SYSTEM = 'system',
|
|
83
|
+
USER = 'user',
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export enum GmailMessageFormat {
|
|
87
|
+
MINIMAL = 'minimal',
|
|
88
|
+
FULL = 'full',
|
|
89
|
+
RAW = 'raw',
|
|
90
|
+
METADATA = 'metadata',
|
|
91
|
+
}
|