emailengine-app 2.68.1 → 2.70.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.
- package/.github/workflows/deploy.yml +8 -3
- package/.github/workflows/release.yaml +6 -0
- package/CHANGELOG.md +59 -0
- package/Gruntfile.js +3 -1
- package/config/default.toml +2 -0
- package/data/google-crawlers.json +7 -1
- package/getswagger.sh +40 -4
- package/gettext-extract.js +163 -0
- package/lib/account.js +135 -72
- package/lib/api-routes/account-routes.js +684 -106
- package/lib/api-routes/blocklist-routes.js +344 -0
- package/lib/api-routes/chat-routes.js +32 -14
- package/lib/api-routes/delivery-test-routes.js +346 -0
- package/lib/api-routes/export-routes.js +28 -14
- package/lib/api-routes/gateway-routes.js +427 -0
- package/lib/api-routes/license-routes.js +156 -0
- package/lib/api-routes/mailbox-routes.js +344 -0
- package/lib/api-routes/message-routes.js +221 -187
- package/lib/api-routes/oauth2-app-routes.js +697 -0
- package/lib/api-routes/outbox-routes.js +185 -0
- package/lib/api-routes/pubsub-routes.js +102 -0
- package/lib/api-routes/route-helpers.js +58 -0
- package/lib/api-routes/settings-routes.js +357 -0
- package/lib/api-routes/stats-routes.js +111 -0
- package/lib/api-routes/submit-routes.js +461 -0
- package/lib/api-routes/template-routes.js +60 -75
- package/lib/api-routes/token-routes.js +297 -0
- package/lib/api-routes/webhook-route-routes.js +181 -0
- package/lib/autodetect-imap-settings.js +0 -2
- package/lib/consts.js +5 -0
- package/lib/email-client/base-client.js +28 -6
- package/lib/email-client/gmail-client.js +133 -112
- package/lib/email-client/imap/mailbox.js +34 -11
- package/lib/email-client/imap/subconnection.js +20 -13
- package/lib/email-client/imap/sync-operations.js +131 -3
- package/lib/email-client/imap-client.js +152 -75
- package/lib/email-client/notification-handler.js +1 -4
- package/lib/email-client/outlook-client.js +134 -75
- package/lib/export.js +97 -20
- package/lib/feature-flags.js +2 -2
- package/lib/gateway.js +4 -9
- package/lib/get-raw-email.js +5 -5
- package/lib/imapproxy/imap-core/lib/commands/starttls.js +18 -0
- package/lib/imapproxy/imap-core/lib/imap-command.js +6 -1
- package/lib/imapproxy/imap-core/lib/imap-connection.js +106 -24
- package/lib/imapproxy/imap-core/lib/imap-server.js +24 -0
- package/lib/imapproxy/imap-core/lib/imap-stream.js +26 -0
- package/lib/logger.js +24 -21
- package/lib/message-port-stream.js +113 -16
- package/lib/metrics-collector.js +0 -2
- package/lib/oauth2-apps.js +13 -4
- package/lib/outbox.js +24 -40
- package/lib/redis-operations.js +1 -1
- package/lib/reject-worker-calls.js +42 -0
- package/lib/routes-ui.js +37 -8778
- package/lib/schemas.js +429 -84
- package/lib/sentry.js +139 -0
- package/lib/settings.js +9 -3
- package/lib/stream-encrypt.js +1 -1
- package/lib/templates.js +1 -1
- package/lib/tokens.js +5 -3
- package/lib/tools.js +70 -4
- package/lib/ui-routes/account-routes.js +45 -212
- package/lib/ui-routes/admin-config-routes.js +928 -489
- package/lib/ui-routes/admin-entities-routes.js +1 -0
- package/lib/ui-routes/auth-routes.js +1339 -0
- package/lib/ui-routes/dashboard-routes.js +188 -0
- package/lib/ui-routes/document-store-routes.js +800 -0
- package/lib/ui-routes/export-routes.js +217 -0
- package/lib/ui-routes/internals-routes.js +354 -0
- package/lib/ui-routes/network-config-routes.js +759 -0
- package/lib/ui-routes/{oauth-routes.js → oauth-config-routes.js} +369 -91
- package/lib/ui-routes/route-helpers.js +314 -0
- package/lib/ui-routes/smtp-test-routes.js +236 -0
- package/lib/ui-routes/unsubscribe-routes.js +232 -0
- package/lib/webhook-request.js +36 -0
- package/lib/webhooks.js +8 -4
- package/package.json +13 -12
- package/sbom.json +1 -1
- package/server.js +222 -39
- package/static/licenses.html +160 -300
- package/translations/messages.pot +112 -132
- package/update-info.sh +19 -1
- package/views/config/logging.hbs +48 -0
- package/views/dashboard.hbs +7 -26
- package/views/internals/index.hbs +15 -0
- package/views/tokens/index.hbs +9 -0
- package/workers/api.js +200 -4424
- package/workers/documents.js +2 -22
- package/workers/export.js +103 -104
- package/workers/imap-proxy.js +3 -23
- package/workers/imap.js +32 -36
- package/workers/smtp.js +2 -22
- package/workers/submit.js +26 -35
- package/workers/webhooks.js +9 -43
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Boom = require('@hapi/boom');
|
|
4
|
+
const Joi = require('joi');
|
|
5
|
+
const { redis } = require('../db');
|
|
6
|
+
const { Account } = require('../account');
|
|
7
|
+
const getSecret = require('../get-secret');
|
|
8
|
+
const { lists } = require('../lists');
|
|
9
|
+
const { failAction } = require('../tools');
|
|
10
|
+
const { handleError } = require('./route-helpers');
|
|
11
|
+
const { accountIdSchema, errorResponses } = require('../schemas');
|
|
12
|
+
const { REDIS_PREFIX } = require('../consts');
|
|
13
|
+
|
|
14
|
+
async function init(args) {
|
|
15
|
+
const { server, call, CORS_CONFIG } = args;
|
|
16
|
+
|
|
17
|
+
server.route({
|
|
18
|
+
method: 'GET',
|
|
19
|
+
path: '/v1/blocklists',
|
|
20
|
+
|
|
21
|
+
async handler(request) {
|
|
22
|
+
try {
|
|
23
|
+
return await lists.list(request.query.page, request.query.pageSize);
|
|
24
|
+
} catch (err) {
|
|
25
|
+
handleError(request, err);
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
options: {
|
|
30
|
+
description: 'List blocklists',
|
|
31
|
+
notes: 'List blocklists with blocked addresses',
|
|
32
|
+
tags: ['api', 'Blocklists'],
|
|
33
|
+
|
|
34
|
+
plugins: {
|
|
35
|
+
'hapi-swagger': {
|
|
36
|
+
responses: errorResponses(400, 401, 403, 429, 500)
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
auth: {
|
|
41
|
+
strategy: 'api-token',
|
|
42
|
+
mode: 'required'
|
|
43
|
+
},
|
|
44
|
+
cors: CORS_CONFIG,
|
|
45
|
+
|
|
46
|
+
validate: {
|
|
47
|
+
options: {
|
|
48
|
+
stripUnknown: false,
|
|
49
|
+
abortEarly: false,
|
|
50
|
+
convert: true
|
|
51
|
+
},
|
|
52
|
+
failAction,
|
|
53
|
+
|
|
54
|
+
query: Joi.object({
|
|
55
|
+
page: Joi.number()
|
|
56
|
+
.integer()
|
|
57
|
+
.min(0)
|
|
58
|
+
.max(1024 * 1024)
|
|
59
|
+
.default(0)
|
|
60
|
+
.example(0)
|
|
61
|
+
.description('Page number (zero indexed, so use 0 for first page)')
|
|
62
|
+
.label('PageNumber'),
|
|
63
|
+
pageSize: Joi.number().integer().min(1).max(1000).default(20).example(20).description('How many entries per page').label('PageSize')
|
|
64
|
+
}).label('PageListsRequest')
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
response: {
|
|
68
|
+
schema: Joi.object({
|
|
69
|
+
total: Joi.number().integer().example(120).description('How many matching entries').label('TotalNumber'),
|
|
70
|
+
page: Joi.number().integer().example(0).description('Current page (0-based index)').label('PageNumber'),
|
|
71
|
+
pages: Joi.number().integer().example(24).description('Total page count').label('PagesNumber'),
|
|
72
|
+
|
|
73
|
+
blocklists: Joi.array()
|
|
74
|
+
.items(
|
|
75
|
+
Joi.object({
|
|
76
|
+
listId: Joi.string().max(256).required().example('example').description('List ID'),
|
|
77
|
+
count: Joi.number().integer().example(12).description('Count of blocked addresses in this list')
|
|
78
|
+
}).label('BlocklistsResponseItem')
|
|
79
|
+
)
|
|
80
|
+
.label('BlocklistsEntries')
|
|
81
|
+
}).label('BlocklistsResponse'),
|
|
82
|
+
failAction: 'log'
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
server.route({
|
|
88
|
+
method: 'GET',
|
|
89
|
+
path: '/v1/blocklist/{listId}',
|
|
90
|
+
|
|
91
|
+
async handler(request) {
|
|
92
|
+
try {
|
|
93
|
+
return await lists.listContent(request.params.listId, request.query.page, request.query.pageSize);
|
|
94
|
+
} catch (err) {
|
|
95
|
+
handleError(request, err);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
options: {
|
|
100
|
+
description: 'List blocklist entries',
|
|
101
|
+
notes: 'List blocked addresses for a list',
|
|
102
|
+
tags: ['api', 'Blocklists'],
|
|
103
|
+
|
|
104
|
+
plugins: {
|
|
105
|
+
'hapi-swagger': {
|
|
106
|
+
responses: errorResponses(400, 401, 403, 404, 429, 500)
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
auth: {
|
|
111
|
+
strategy: 'api-token',
|
|
112
|
+
mode: 'required'
|
|
113
|
+
},
|
|
114
|
+
cors: CORS_CONFIG,
|
|
115
|
+
|
|
116
|
+
validate: {
|
|
117
|
+
options: {
|
|
118
|
+
stripUnknown: false,
|
|
119
|
+
abortEarly: false,
|
|
120
|
+
convert: true
|
|
121
|
+
},
|
|
122
|
+
failAction,
|
|
123
|
+
|
|
124
|
+
params: Joi.object({
|
|
125
|
+
listId: Joi.string()
|
|
126
|
+
.hostname()
|
|
127
|
+
.example('test-list')
|
|
128
|
+
.description('List ID. Must use a subdomain name format. Lists are registered ad-hoc, so a new identifier defines a new list.')
|
|
129
|
+
.label('ListID')
|
|
130
|
+
.required()
|
|
131
|
+
}).label('BlocklistListRequest'),
|
|
132
|
+
|
|
133
|
+
query: Joi.object({
|
|
134
|
+
page: Joi.number()
|
|
135
|
+
.integer()
|
|
136
|
+
.min(0)
|
|
137
|
+
.max(1024 * 1024)
|
|
138
|
+
.default(0)
|
|
139
|
+
.example(0)
|
|
140
|
+
.description('Page number (zero indexed, so use 0 for first page)')
|
|
141
|
+
.label('PageNumber'),
|
|
142
|
+
pageSize: Joi.number().integer().min(1).max(1000).default(20).example(20).description('How many entries per page').label('PageSize')
|
|
143
|
+
}).label('PageListsRequest')
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
response: {
|
|
147
|
+
schema: Joi.object({
|
|
148
|
+
listId: Joi.string().max(256).required().example('example').description('List ID'),
|
|
149
|
+
total: Joi.number().integer().example(120).description('How many matching entries').label('TotalNumber'),
|
|
150
|
+
page: Joi.number().integer().example(0).description('Current page (0-based index)').label('PageNumber'),
|
|
151
|
+
pages: Joi.number().integer().example(24).description('Total page count').label('PagesNumber'),
|
|
152
|
+
addresses: Joi.array()
|
|
153
|
+
.items(
|
|
154
|
+
Joi.object({
|
|
155
|
+
recipient: Joi.string().email().example('user@example.com').description('Listed email address').required(),
|
|
156
|
+
account: accountIdSchema.required(),
|
|
157
|
+
messageId: Joi.string().example('<test123@example.com>').description('Message ID'),
|
|
158
|
+
source: Joi.string().example('api').description('Which mechanism was used to add the entry'),
|
|
159
|
+
reason: Joi.string().example('block').description('Why this entry was added'),
|
|
160
|
+
remoteAddress: Joi.string()
|
|
161
|
+
.ip({
|
|
162
|
+
version: ['ipv4', 'ipv6'],
|
|
163
|
+
cidr: 'optional'
|
|
164
|
+
})
|
|
165
|
+
.description('Which IP address triggered the entry'),
|
|
166
|
+
userAgent: Joi.string().example('Mozilla/5.0 (Macintosh)').description('Which user agent triggered the entry'),
|
|
167
|
+
created: Joi.date().iso().example('2021-02-17T13:43:18.860Z').description('The time this entry was added or updated').required()
|
|
168
|
+
}).label('BlocklistListResponseItem')
|
|
169
|
+
)
|
|
170
|
+
.label('BlocklistListEntries')
|
|
171
|
+
}).label('BlocklistListResponse'),
|
|
172
|
+
failAction: 'log'
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
server.route({
|
|
178
|
+
method: 'POST',
|
|
179
|
+
path: '/v1/blocklist/{listId}',
|
|
180
|
+
async handler(request) {
|
|
181
|
+
let accountObject = new Account({
|
|
182
|
+
redis,
|
|
183
|
+
account: request.payload.account,
|
|
184
|
+
call,
|
|
185
|
+
secret: await getSecret(),
|
|
186
|
+
timeout: request.headers['x-ee-timeout']
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
// throws if account does not exist
|
|
191
|
+
await accountObject.loadAccountData();
|
|
192
|
+
|
|
193
|
+
let added = await redis.eeListAdd(
|
|
194
|
+
`${REDIS_PREFIX}lists:unsub:lists`,
|
|
195
|
+
`${REDIS_PREFIX}lists:unsub:entries:${request.params.listId}`,
|
|
196
|
+
request.params.listId,
|
|
197
|
+
request.payload.recipient.toLowerCase().trim(),
|
|
198
|
+
JSON.stringify({
|
|
199
|
+
recipient: request.payload.recipient,
|
|
200
|
+
account: request.payload.account,
|
|
201
|
+
source: 'api',
|
|
202
|
+
reason: request.payload.reason,
|
|
203
|
+
remoteAddress: request.app.ip,
|
|
204
|
+
userAgent: request.headers['user-agent'],
|
|
205
|
+
created: new Date().toISOString()
|
|
206
|
+
})
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
success: true,
|
|
211
|
+
added: !!added
|
|
212
|
+
};
|
|
213
|
+
} catch (err) {
|
|
214
|
+
handleError(request, err);
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
options: {
|
|
218
|
+
description: 'Add to blocklist',
|
|
219
|
+
notes: 'Add an email address to a blocklist',
|
|
220
|
+
tags: ['api', 'Blocklists'],
|
|
221
|
+
|
|
222
|
+
plugins: {
|
|
223
|
+
'hapi-swagger': {
|
|
224
|
+
responses: errorResponses(400, 401, 403, 404, 429, 500)
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
auth: {
|
|
229
|
+
strategy: 'api-token',
|
|
230
|
+
mode: 'required'
|
|
231
|
+
},
|
|
232
|
+
cors: CORS_CONFIG,
|
|
233
|
+
|
|
234
|
+
validate: {
|
|
235
|
+
options: {
|
|
236
|
+
stripUnknown: false,
|
|
237
|
+
abortEarly: false,
|
|
238
|
+
convert: true
|
|
239
|
+
},
|
|
240
|
+
failAction,
|
|
241
|
+
|
|
242
|
+
params: Joi.object({
|
|
243
|
+
listId: Joi.string()
|
|
244
|
+
.hostname()
|
|
245
|
+
.example('test-list')
|
|
246
|
+
.description('List ID. Must use a subdomain name format. Lists are registered ad-hoc, so a new identifier defines a new list.')
|
|
247
|
+
.label('ListID')
|
|
248
|
+
.required()
|
|
249
|
+
}).label('BlocklistListRequest'),
|
|
250
|
+
|
|
251
|
+
payload: Joi.object({
|
|
252
|
+
account: accountIdSchema.required(),
|
|
253
|
+
recipient: Joi.string().empty('').email().example('user@example.com').description('Email address to add to the list').required(),
|
|
254
|
+
reason: Joi.string().empty('').default('block').description('Identifier for the blocking reason')
|
|
255
|
+
}).label('BlocklistListAddPayload')
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
response: {
|
|
259
|
+
schema: Joi.object({
|
|
260
|
+
success: Joi.boolean().example(true).description('Was the request successful').label('BlocklistListAddSuccess'),
|
|
261
|
+
added: Joi.boolean().example(true).description('Was the address added to the list')
|
|
262
|
+
}).label('BlocklistListAddResponse'),
|
|
263
|
+
failAction: 'log'
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
server.route({
|
|
269
|
+
method: 'DELETE',
|
|
270
|
+
path: '/v1/blocklist/{listId}',
|
|
271
|
+
|
|
272
|
+
async handler(request) {
|
|
273
|
+
try {
|
|
274
|
+
let exists = await redis.hexists(`${REDIS_PREFIX}lists:unsub:lists`, request.params.listId);
|
|
275
|
+
if (!exists) {
|
|
276
|
+
let message = 'Requested blocklist was not found';
|
|
277
|
+
let error = Boom.boomify(new Error(message), { statusCode: 404 });
|
|
278
|
+
throw error;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
let deleted = await redis.eeListRemove(
|
|
282
|
+
`${REDIS_PREFIX}lists:unsub:lists`,
|
|
283
|
+
`${REDIS_PREFIX}lists:unsub:entries:${request.params.listId}`,
|
|
284
|
+
request.params.listId,
|
|
285
|
+
request.query.recipient.toLowerCase().trim()
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
deleted: !!deleted
|
|
290
|
+
};
|
|
291
|
+
} catch (err) {
|
|
292
|
+
handleError(request, err);
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
options: {
|
|
296
|
+
description: 'Remove from blocklist',
|
|
297
|
+
notes: 'Delete a blocked email address from a list',
|
|
298
|
+
tags: ['api', 'Blocklists'],
|
|
299
|
+
|
|
300
|
+
plugins: {
|
|
301
|
+
'hapi-swagger': {
|
|
302
|
+
responses: errorResponses(400, 401, 403, 404, 429, 500)
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
|
|
306
|
+
auth: {
|
|
307
|
+
strategy: 'api-token',
|
|
308
|
+
mode: 'required'
|
|
309
|
+
},
|
|
310
|
+
cors: CORS_CONFIG,
|
|
311
|
+
|
|
312
|
+
validate: {
|
|
313
|
+
options: {
|
|
314
|
+
stripUnknown: false,
|
|
315
|
+
abortEarly: false,
|
|
316
|
+
convert: true
|
|
317
|
+
},
|
|
318
|
+
failAction,
|
|
319
|
+
|
|
320
|
+
params: Joi.object({
|
|
321
|
+
listId: Joi.string()
|
|
322
|
+
.hostname()
|
|
323
|
+
.example('test-list')
|
|
324
|
+
.description('List ID. Must use a subdomain name format. Lists are registered ad-hoc, so a new identifier defines a new list.')
|
|
325
|
+
.label('ListID')
|
|
326
|
+
.required()
|
|
327
|
+
}).label('BlocklistListRequest'),
|
|
328
|
+
|
|
329
|
+
query: Joi.object({
|
|
330
|
+
recipient: Joi.string().empty('').email().example('user@example.com').description('Email address to remove from the list').required()
|
|
331
|
+
}).label('RecipientQuery')
|
|
332
|
+
},
|
|
333
|
+
|
|
334
|
+
response: {
|
|
335
|
+
schema: Joi.object({
|
|
336
|
+
deleted: Joi.boolean().truthy('Y', 'true', '1').falsy('N', 'false', 0).default(true).description('Was the address removed from the list')
|
|
337
|
+
}).label('DeleteBlocklistResponse'),
|
|
338
|
+
failAction: 'log'
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
module.exports = init;
|
|
@@ -11,7 +11,7 @@ const util = require('util');
|
|
|
11
11
|
|
|
12
12
|
const LOG_VERBOSE = getBoolean(process.env.EE_OPENAPI_VERBOSE);
|
|
13
13
|
|
|
14
|
-
const { accountIdSchema,
|
|
14
|
+
const { accountIdSchema, messageSpecialUseSchema, responseAddressSchema, responseFromAddressSchema, errorResponses } = require('../schemas');
|
|
15
15
|
|
|
16
16
|
function getDateValue(str) {
|
|
17
17
|
try {
|
|
@@ -97,7 +97,7 @@ async function init(args) {
|
|
|
97
97
|
startTime: sortingResponse?.start_time,
|
|
98
98
|
endTime: sortingResponse?.end_time,
|
|
99
99
|
model: sortingResponse?.model,
|
|
100
|
-
tokens: sortingResponse
|
|
100
|
+
tokens: sortingResponse?.tokens
|
|
101
101
|
});
|
|
102
102
|
|
|
103
103
|
// Step 2. Embeddings for the request
|
|
@@ -195,7 +195,7 @@ async function init(args) {
|
|
|
195
195
|
filter: vectorsFilter?.bool?.must
|
|
196
196
|
});
|
|
197
197
|
return {
|
|
198
|
-
success:
|
|
198
|
+
success: false,
|
|
199
199
|
answer: null,
|
|
200
200
|
processPipeline
|
|
201
201
|
};
|
|
@@ -281,7 +281,7 @@ async function init(args) {
|
|
|
281
281
|
message: 'Retrieved the answer',
|
|
282
282
|
messages: queryResponse?.messageId?.length || 0,
|
|
283
283
|
model: queryResponse?.model,
|
|
284
|
-
tokens: queryResponse
|
|
284
|
+
tokens: queryResponse?.tokens
|
|
285
285
|
});
|
|
286
286
|
|
|
287
287
|
if (queryResponse?.answer) {
|
|
@@ -360,7 +360,7 @@ async function init(args) {
|
|
|
360
360
|
}
|
|
361
361
|
|
|
362
362
|
return {
|
|
363
|
-
success: !!
|
|
363
|
+
success: !!responseData.answer,
|
|
364
364
|
...responseData,
|
|
365
365
|
processPipeline
|
|
366
366
|
};
|
|
@@ -399,9 +399,13 @@ async function init(args) {
|
|
|
399
399
|
options: {
|
|
400
400
|
description: 'Chat with emails',
|
|
401
401
|
notes: 'Use OpenAI API and embeddings stored in the Document Store to "chat" with account emails. Requires Document Store indexing and the "Chat with emails" feature to be enabled.',
|
|
402
|
-
tags: ['Deprecated endpoints (Document Store)'],
|
|
402
|
+
tags: ['api', 'Deprecated endpoints (Document Store)'],
|
|
403
403
|
|
|
404
|
-
plugins: {
|
|
404
|
+
plugins: {
|
|
405
|
+
'hapi-swagger': {
|
|
406
|
+
responses: errorResponses(400, 401, 403, 404, 429, 500)
|
|
407
|
+
}
|
|
408
|
+
},
|
|
405
409
|
|
|
406
410
|
auth: {
|
|
407
411
|
strategy: 'api-token',
|
|
@@ -434,30 +438,44 @@ async function init(args) {
|
|
|
434
438
|
|
|
435
439
|
response: {
|
|
436
440
|
schema: Joi.object({
|
|
437
|
-
success: Joi.boolean()
|
|
438
|
-
|
|
441
|
+
success: Joi.boolean()
|
|
442
|
+
.example(true)
|
|
443
|
+
.description('Whether the LLM produced an answer. Can be false on a 200 response when no answer was found')
|
|
444
|
+
.label('ReturnChatResponseSuccess'),
|
|
445
|
+
answer: Joi.string()
|
|
446
|
+
.trim()
|
|
447
|
+
.allow(null)
|
|
448
|
+
.example('Last tuesday')
|
|
449
|
+
.description('Chat response. Not present (or null) when no answer was produced')
|
|
450
|
+
.label('ChatResponse'),
|
|
439
451
|
messages: Joi.array()
|
|
440
452
|
.items(
|
|
441
453
|
Joi.object({
|
|
442
454
|
id: Joi.string().example('AAAAAgAACrI').description('Unique identifier for the message').label('ChatMessageId'),
|
|
443
455
|
path: Joi.string().example('INBOX').description('Folder this message was found from').label('ChatMessagePath'),
|
|
444
456
|
date: Joi.date().iso().example('2023-09-29T10:03:49.000Z').description('Date of the email'),
|
|
445
|
-
from:
|
|
457
|
+
from: responseFromAddressSchema,
|
|
446
458
|
|
|
447
459
|
to: Joi.array()
|
|
448
|
-
.items(
|
|
460
|
+
.items(responseAddressSchema)
|
|
449
461
|
.single()
|
|
450
462
|
.description('List of addresses')
|
|
451
463
|
.example([{ address: 'recipient@example.com' }])
|
|
452
|
-
.label('
|
|
453
|
-
|
|
464
|
+
.label('ChatToAddressList'),
|
|
465
|
+
cc: Joi.array().items(responseAddressSchema).single().description('List of CC addresses').label('ChatCcAddressList'),
|
|
466
|
+
bcc: Joi.array().items(responseAddressSchema).single().description('List of BCC addresses').label('ChatBccAddressList'),
|
|
467
|
+
subject: Joi.string().example('What a wonderful message').description('Message subject'),
|
|
454
468
|
messageSpecialUse: messageSpecialUseSchema
|
|
455
469
|
})
|
|
456
470
|
.description('Email that best matched the question')
|
|
457
471
|
.label('ChatResponseMessage')
|
|
458
472
|
)
|
|
459
473
|
.description('Emails that best matched the question')
|
|
460
|
-
.label('ChatResponseMessages')
|
|
474
|
+
.label('ChatResponseMessages'),
|
|
475
|
+
processPipeline: Joi.array()
|
|
476
|
+
.items(Joi.object().unknown().label('ChatProcessPipelineStep'))
|
|
477
|
+
.description('Diagnostic information about the chat processing steps, including timings and token usage')
|
|
478
|
+
.label('ChatProcessPipeline')
|
|
461
479
|
}).label('ReturnChatResponse'),
|
|
462
480
|
failAction: 'log'
|
|
463
481
|
}
|