mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-09-20 07:16:05 +08:00
feat(api-search): Allow searching for messages by uid (#587)
This commit is contained in:
parent
299cc37f2f
commit
a4ae3d7113
|
@ -1945,6 +1945,11 @@ paths:
|
|||
description: ID of the Mailbox
|
||||
schema:
|
||||
type: string
|
||||
- name: id
|
||||
in: query
|
||||
description: Message ID values, only applies when used in combination with `mailbox`. Either comma separated numbers (1,2,3) or colon separated range (3:15), or a range from UID to end (3:*)
|
||||
schema:
|
||||
type: string
|
||||
- name: thread
|
||||
in: query
|
||||
description: Thread ID
|
||||
|
@ -2091,6 +2096,9 @@ paths:
|
|||
mailbox:
|
||||
description: ID of the Mailbox
|
||||
type: string
|
||||
id:
|
||||
description: Message ID values, only applies when used in combination with `mailbox`. Either comma separated numbers (1,2,3) or colon separated range (3:15), or a range from UID to end (3:*)
|
||||
type: string
|
||||
thread:
|
||||
description: Thread ID
|
||||
type: string
|
||||
|
|
|
@ -20,7 +20,7 @@ const roles = require('../roles');
|
|||
const { nextPageCursorSchema, previousPageCursorSchema, pageNrSchema, sessSchema, sessIPSchema, booleanSchema, metaDataSchema } = require('../schemas');
|
||||
const { preprocessAttachments } = require('../data-url');
|
||||
const TaskHandler = require('../task-handler');
|
||||
const prepareSearchFilter = require('../prepare-search-filter');
|
||||
const { prepareSearchFilter, uidRangeStringToQuery } = require('../prepare-search-filter');
|
||||
const { getMongoDBQuery /*, getElasticSearchQuery*/ } = require('../search-query');
|
||||
//const { getClient } = require('../elasticsearch');
|
||||
|
||||
|
@ -226,41 +226,9 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti
|
|||
let moveTo = result.value.moveTo ? new ObjectId(result.value.moveTo) : false;
|
||||
let message = result.value.message;
|
||||
|
||||
let messageQuery;
|
||||
let messageQuery = uidRangeStringToQuery(message);
|
||||
|
||||
if (/^\d+$/.test(message)) {
|
||||
messageQuery = Number(message);
|
||||
} else if (/^\d+(,\d+)*$/.test(message)) {
|
||||
messageQuery = {
|
||||
$in: message
|
||||
.split(',')
|
||||
.map(uid => Number(uid))
|
||||
.sort((a, b) => a - b)
|
||||
};
|
||||
} else if (/^\d+:(\d+|\*)$/.test(message)) {
|
||||
let parts = message
|
||||
.split(':')
|
||||
.map(uid => Number(uid))
|
||||
.sort((a, b) => {
|
||||
if (a === '*') {
|
||||
return 1;
|
||||
}
|
||||
if (b === '*') {
|
||||
return -1;
|
||||
}
|
||||
return a - b;
|
||||
});
|
||||
if (parts[0] === parts[1]) {
|
||||
messageQuery = parts[0];
|
||||
} else {
|
||||
messageQuery = {
|
||||
$gte: parts[0]
|
||||
};
|
||||
if (!isNaN(parts[1])) {
|
||||
messageQuery.$lte = parts[1];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!messageQuery) {
|
||||
res.status(404);
|
||||
return res.json({
|
||||
error: 'Invalid message identifier',
|
||||
|
@ -626,6 +594,13 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti
|
|||
q: Joi.string().trim().empty('').max(1024).optional().description('Additional query string'),
|
||||
|
||||
mailbox: Joi.string().hex().length(24).empty('').description('ID of the Mailbox'),
|
||||
id: Joi.string()
|
||||
.trim()
|
||||
.empty('')
|
||||
.regex(/^\d+(,\d+)*$|^\d+:(\d+|\*)$/i)
|
||||
.description(
|
||||
'Message ID values, only applies when used in combination with `mailbox`. Either comma separated numbers (1,2,3) or colon separated range (3:15), or a range from UID to end (3:*)'
|
||||
),
|
||||
thread: Joi.string().hex().length(24).empty('').description('Thread ID'),
|
||||
|
||||
or: Joi.object({
|
||||
|
|
|
@ -3,8 +3,52 @@
|
|||
const ObjectId = require('mongodb').ObjectId;
|
||||
const { escapeRegexStr } = require('./tools');
|
||||
|
||||
const uidRangeStringToQuery = uidRange => {
|
||||
if (!uidRange) {
|
||||
return;
|
||||
}
|
||||
|
||||
let query;
|
||||
|
||||
if (/^\d+$/.test(uidRange)) {
|
||||
query = Number(uidRange);
|
||||
} else if (/^\d+(,\d+)*$/.test(uidRange)) {
|
||||
query = {
|
||||
$in: uidRange
|
||||
.split(',')
|
||||
.map(uid => Number(uid))
|
||||
.sort((a, b) => a - b)
|
||||
};
|
||||
} else if (/^\d+:(\d+|\*)$/.test(uidRange)) {
|
||||
let parts = uidRange
|
||||
.split(':')
|
||||
.map(uid => Number(uid))
|
||||
.sort((a, b) => {
|
||||
if (a === '*') {
|
||||
return 1;
|
||||
}
|
||||
if (b === '*') {
|
||||
return -1;
|
||||
}
|
||||
return a - b;
|
||||
});
|
||||
if (parts[0] === parts[1]) {
|
||||
query = parts[0];
|
||||
} else {
|
||||
query = {
|
||||
$gte: parts[0]
|
||||
};
|
||||
if (!isNaN(parts[1])) {
|
||||
query.$lte = parts[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return query;
|
||||
};
|
||||
|
||||
const prepareSearchFilter = async (db, user, payload) => {
|
||||
let mailbox = payload.mailbox ? new ObjectId(payload.mailbox) : false;
|
||||
let idQuery = uidRangeStringToQuery(payload.id);
|
||||
let thread = payload.thread ? new ObjectId(payload.thread) : false;
|
||||
|
||||
let orTerms = payload.or || {};
|
||||
|
@ -87,6 +131,10 @@ const prepareSearchFilter = async (db, user, payload) => {
|
|||
filter.mailbox = { $nin: mailboxes.map(m => m._id) };
|
||||
}
|
||||
|
||||
if (filter.mailbox && idQuery) {
|
||||
filter.uid = idQuery;
|
||||
}
|
||||
|
||||
if (thread) {
|
||||
filter.thread = thread;
|
||||
}
|
||||
|
@ -267,4 +315,4 @@ const prepareSearchFilter = async (db, user, payload) => {
|
|||
return { filter, query };
|
||||
};
|
||||
|
||||
module.exports = prepareSearchFilter;
|
||||
module.exports = { uidRangeStringToQuery, prepareSearchFilter };
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
const log = require('npmlog');
|
||||
const db = require('../db');
|
||||
const util = require('util');
|
||||
const prepareSearchFilter = require('../prepare-search-filter');
|
||||
const { prepareSearchFilter } = require('../prepare-search-filter');
|
||||
const { getMongoDBQuery } = require('../search-query');
|
||||
const ObjectId = require('mongodb').ObjectId;
|
||||
|
||||
|
|
Loading…
Reference in a new issue