1 | const oauth2Client = require('./auth')
|
2 | const google = require('googleapis')
|
3 | const gmail = google.gmail({ version: 'v1' })
|
4 | const btoa = require('btoa')
|
5 | const chalk = require('chalk')
|
6 | const db = require('./db')
|
7 | const base64url = require('base64-url')
|
8 | const createFetch = require('./create-fetch')
|
9 |
|
10 | async function getMessagesList ({
|
11 | filter,
|
12 | next,
|
13 | accessToken
|
14 | }) {
|
15 | const params = {
|
16 | maxResults: 10
|
17 | }
|
18 | if (filter) {
|
19 | params.q = filter
|
20 | }
|
21 | if (next) {
|
22 | params.pageToken = next
|
23 | }
|
24 | const { messages, nextPageToken } = await createFetch({
|
25 | accessToken,
|
26 | endpoint: '/gmail/v1/users/me/messages',
|
27 | base: 'https://www.googleapis.com',
|
28 | params
|
29 | })
|
30 | return { messages, nextPageToken }
|
31 | }
|
32 |
|
33 | async function getEmail (params) {
|
34 | const { accessToken, id, format = 'metadata' } = params
|
35 | const endpoint = `/gmail/v1/users/me/messages/${id}`
|
36 | return createFetch({ accessToken, endpoint, params: { format } })
|
37 | }
|
38 |
|
39 | async function getEmails ({ accessToken, messages, format }) {
|
40 | if (!format) format = 'metadata'
|
41 |
|
42 | return Promise.all(messages.map((message) => {
|
43 | const endpoint = `/gmail/v1/users/me/messages/${message.id}`
|
44 | return createFetch({ accessToken, endpoint, params: { format } })
|
45 | }))
|
46 | }
|
47 |
|
48 | class Client {
|
49 | constructor (oauth2Client, account) {
|
50 | oauth2Client.setCredentials(account.tokens)
|
51 | this.oauth2Client = oauth2Client
|
52 | this.accessToken = account.tokens.access_token
|
53 | this.account = account
|
54 | }
|
55 |
|
56 | static async create (account) {
|
57 | let auth = await oauth2Client()
|
58 | return new Client(auth, account)
|
59 | }
|
60 |
|
61 | send ({ text, sender, recipient, subject }) {
|
62 | const base64Encoded = btoa([
|
63 | 'Content-Type: text/plain; charset=\"UTF-8\"',
|
64 | 'MIME-Version: 1.0',
|
65 | `Subject: ${subject}`,
|
66 | `From: ${sender}`,
|
67 | `To: ${recipient}\n`,
|
68 | `${text}`
|
69 | ].join('\n')).replace(/\+/g, '-').replace(/\//g, '_')
|
70 | gmail.users.messages.send({
|
71 | auth: this.oauth2Client,
|
72 | userId: 'me',
|
73 | resource: { raw: base64Encoded }
|
74 | })
|
75 | }
|
76 |
|
77 | reply ({
|
78 | text,
|
79 | sender,
|
80 | recipient,
|
81 | subject,
|
82 | threadId
|
83 | }) {
|
84 | const arr = [
|
85 | 'Content-Type: text/plain; charset=\"UTF-8\"',
|
86 | 'MIME-Version: 1.0',
|
87 | `Subject: ${subject}`,
|
88 | `From: ${sender}`,
|
89 | `To: ${recipient}\n`,
|
90 | `${text}`
|
91 | ]
|
92 | console.log(chalk.cyan(arr.join('\n')))
|
93 | const base64EncodedEmail = btoa(arr.join('\n'))
|
94 | .replace(/\+/g, '-')
|
95 | .replace(/\//g, '_')
|
96 |
|
97 | gmail.users.messages.send({
|
98 | auth: this.oauth2Client,
|
99 | userId: 'me',
|
100 | resource: {
|
101 | raw: base64EncodedEmail,
|
102 | threadId
|
103 | }
|
104 | })
|
105 | }
|
106 |
|
107 | async fetchMessages (page, filter) {
|
108 | const store = db.get('messages')
|
109 | const next = db.get(`pages.${page}`, undefined).value()
|
110 | const resp = await getMessagesList({
|
111 | accessToken: this.accessToken,
|
112 | next,
|
113 | filter
|
114 | })
|
115 | db.set(`pages.${page + 1}`, resp.nextPageToken).write()
|
116 |
|
117 | let _messages = resp.messages.filter(message =>
|
118 | !store.find({id: message.id}).value()
|
119 | )
|
120 |
|
121 | if (_messages && _messages.length) {
|
122 | const messages = await getEmails({
|
123 | accessToken: this.accessToken,
|
124 | messages: _messages,
|
125 | format: 'full'
|
126 | })
|
127 | db.set(
|
128 | 'messages',
|
129 | messages.concat(store.value()).sort((a, b) =>
|
130 | parseInt(b.internalDate) - parseInt(a.internalDate)
|
131 | )
|
132 | ).write()
|
133 | }
|
134 | }
|
135 |
|
136 | async getMessage (id) {
|
137 | let message = db.get('messages').find(message => message.id === id)
|
138 | let accessToken = this.account.tokens.access_token
|
139 | let raw = await getEmail({ accessToken, id, format: 'raw' })
|
140 | let source = base64url.decode(raw.raw)
|
141 | return {
|
142 | source,
|
143 | message,
|
144 | raw
|
145 | }
|
146 | }
|
147 |
|
148 | deleteMessage (messageId) {
|
149 | gmail.users.messages.trash({
|
150 | auth: this.oauth2Client,
|
151 | userId: 'me',
|
152 | id: messageId
|
153 | })
|
154 | db.get('messages').remove({id: messageId}).write()
|
155 | }
|
156 | }
|
157 |
|
158 | module.exports = Client
|