mirror of
https://github.com/nodemailer/wildduck.git
synced 2025-11-10 08:21:05 +08:00
list-id filtering
This commit is contained in:
parent
b4e7387d8b
commit
d72198c1bd
4 changed files with 46 additions and 18 deletions
|
|
@ -216,6 +216,7 @@ module.exports = (db, server) => {
|
||||||
* @apiSuccess {String} query.from Partial match for the From: header (case insensitive)
|
* @apiSuccess {String} query.from Partial match for the From: header (case insensitive)
|
||||||
* @apiSuccess {String} query.to Partial match for the To:/Cc: headers (case insensitive)
|
* @apiSuccess {String} query.to Partial match for the To:/Cc: headers (case insensitive)
|
||||||
* @apiSuccess {String} query.subject Partial match for the Subject: header (case insensitive)
|
* @apiSuccess {String} query.subject Partial match for the Subject: header (case insensitive)
|
||||||
|
* @apiSuccess {String} query.listId Partial match for the List-ID: header (case insensitive)
|
||||||
* @apiSuccess {String} query.text Fulltext search against message text
|
* @apiSuccess {String} query.text Fulltext search against message text
|
||||||
* @apiSuccess {Boolean} query.ha Does a message have to have an attachment or not
|
* @apiSuccess {Boolean} query.ha Does a message have to have an attachment or not
|
||||||
* @apiSuccess {Number} query.size Message size in bytes. If the value is a positive number then message needs to be larger, if negative then message needs to be smaller than abs(size) value
|
* @apiSuccess {Number} query.size Message size in bytes. If the value is a positive number then message needs to be larger, if negative then message needs to be smaller than abs(size) value
|
||||||
|
|
@ -501,6 +502,7 @@ module.exports = (db, server) => {
|
||||||
* @apiParam {String} [query.from] Partial match for the From: header (case insensitive)
|
* @apiParam {String} [query.from] Partial match for the From: header (case insensitive)
|
||||||
* @apiParam {String} [query.to] Partial match for the To:/Cc: headers (case insensitive)
|
* @apiParam {String} [query.to] Partial match for the To:/Cc: headers (case insensitive)
|
||||||
* @apiParam {String} [query.subject] Partial match for the Subject: header (case insensitive)
|
* @apiParam {String} [query.subject] Partial match for the Subject: header (case insensitive)
|
||||||
|
* @apiParam {String} [query.listId] Partial match for the List-ID: header (case insensitive)
|
||||||
* @apiParam {String} [query.text] Fulltext search against message text
|
* @apiParam {String} [query.text] Fulltext search against message text
|
||||||
* @apiParam {Boolean} [query.ha] Does a message have to have an attachment or not
|
* @apiParam {Boolean} [query.ha] Does a message have to have an attachment or not
|
||||||
* @apiParam {Number} [query.size] Message size in bytes. If the value is a positive number then message needs to be larger, if negative then message needs to be smaller than abs(size) value
|
* @apiParam {Number} [query.size] Message size in bytes. If the value is a positive number then message needs to be larger, if negative then message needs to be smaller than abs(size) value
|
||||||
|
|
@ -574,6 +576,10 @@ module.exports = (db, server) => {
|
||||||
.trim()
|
.trim()
|
||||||
.max(255)
|
.max(255)
|
||||||
.empty(''),
|
.empty(''),
|
||||||
|
listId: Joi.string()
|
||||||
|
.trim()
|
||||||
|
.max(255)
|
||||||
|
.empty(''),
|
||||||
text: Joi.string()
|
text: Joi.string()
|
||||||
.trim()
|
.trim()
|
||||||
.max(255)
|
.max(255)
|
||||||
|
|
@ -669,7 +675,7 @@ module.exports = (db, server) => {
|
||||||
filterData.name = result.value.name;
|
filterData.name = result.value.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
['from', 'to', 'subject'].forEach(key => {
|
['from', 'to', 'subject', 'listId'].forEach(key => {
|
||||||
if (result.value.query[key]) {
|
if (result.value.query[key]) {
|
||||||
filterData.query.headers[key] = result.value.query[key].replace(/\s+/g, ' ');
|
filterData.query.headers[key] = result.value.query[key].replace(/\s+/g, ' ');
|
||||||
}
|
}
|
||||||
|
|
@ -821,6 +827,7 @@ module.exports = (db, server) => {
|
||||||
* @apiParam {String} [query.from] Partial match for the From: header (case insensitive)
|
* @apiParam {String} [query.from] Partial match for the From: header (case insensitive)
|
||||||
* @apiParam {String} [query.to] Partial match for the To:/Cc: headers (case insensitive)
|
* @apiParam {String} [query.to] Partial match for the To:/Cc: headers (case insensitive)
|
||||||
* @apiParam {String} [query.subject] Partial match for the Subject: header (case insensitive)
|
* @apiParam {String} [query.subject] Partial match for the Subject: header (case insensitive)
|
||||||
|
* @apiParam {String} [query.listId] Partial match for the List-ID: header (case insensitive)
|
||||||
* @apiParam {String} [query.text] Fulltext search against message text
|
* @apiParam {String} [query.text] Fulltext search against message text
|
||||||
* @apiParam {Boolean} [query.ha] Does a message have to have an attachment or not
|
* @apiParam {Boolean} [query.ha] Does a message have to have an attachment or not
|
||||||
* @apiParam {Number} [query.size] Message size in bytes. If the value is a positive number then message needs to be larger, if negative then message needs to be smaller than abs(size) value
|
* @apiParam {Number} [query.size] Message size in bytes. If the value is a positive number then message needs to be larger, if negative then message needs to be smaller than abs(size) value
|
||||||
|
|
@ -896,6 +903,10 @@ module.exports = (db, server) => {
|
||||||
.trim()
|
.trim()
|
||||||
.max(255)
|
.max(255)
|
||||||
.empty(''),
|
.empty(''),
|
||||||
|
listId: Joi.string()
|
||||||
|
.trim()
|
||||||
|
.max(255)
|
||||||
|
.empty(''),
|
||||||
text: Joi.string()
|
text: Joi.string()
|
||||||
.trim()
|
.trim()
|
||||||
.max(255)
|
.max(255)
|
||||||
|
|
@ -993,7 +1004,7 @@ module.exports = (db, server) => {
|
||||||
hasChanges = true;
|
hasChanges = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
['from', 'to', 'subject'].forEach(key => {
|
['from', 'to', 'subject', 'listId'].forEach(key => {
|
||||||
if (result.value.query[key]) {
|
if (result.value.query[key]) {
|
||||||
$set['query.headers.' + key] = result.value.query[key].replace(/\s+/g, ' ');
|
$set['query.headers.' + key] = result.value.query[key].replace(/\s+/g, ' ');
|
||||||
hasChanges = true;
|
hasChanges = true;
|
||||||
|
|
|
||||||
|
|
@ -602,12 +602,21 @@ function checkFilter(filter, prepared, maildata) {
|
||||||
let headerFilters = new Map();
|
let headerFilters = new Map();
|
||||||
if (query.headers) {
|
if (query.headers) {
|
||||||
Object.keys(query.headers).forEach(key => {
|
Object.keys(query.headers).forEach(key => {
|
||||||
|
let header = key.replace(/[A-Z]+/g, c => '-' + c.toLowerCase());
|
||||||
let value = query.headers[key];
|
let value = query.headers[key];
|
||||||
if (!value || !value.isRegex) {
|
if (!value || !value.isRegex) {
|
||||||
value = (query.headers[key] || '').toString().toLowerCase();
|
value = (query.headers[key] || '').toString().toLowerCase();
|
||||||
}
|
}
|
||||||
if (value) {
|
if (value) {
|
||||||
headerFilters.set(key, value);
|
if (header === 'list-id' && typeof value === 'string' && value.indexOf('<') >= 0) {
|
||||||
|
// only check actual ID part of the List-ID header
|
||||||
|
let m = value.match(/<([^>]+)/);
|
||||||
|
if (m && m[1] && m[1].trim()) {
|
||||||
|
value = m[1].trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
headerFilters.set(header, value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -628,11 +637,13 @@ function checkFilter(filter, prepared, maildata) {
|
||||||
}
|
}
|
||||||
if (headerFilters.has(key)) {
|
if (headerFilters.has(key)) {
|
||||||
let check = headerFilters.get(key);
|
let check = headerFilters.get(key);
|
||||||
|
let value = (header.value || '').toString();
|
||||||
|
|
||||||
if (check.isRegex) {
|
if (check.isRegex) {
|
||||||
if (check.test(header.value)) {
|
if (check.test(value)) {
|
||||||
headerMatches.add(key);
|
headerMatches.add(key);
|
||||||
}
|
}
|
||||||
} else if (header.value === check || header.value.indexOf(check) >= 0) {
|
} else if (value === check || value.indexOf(check) >= 0) {
|
||||||
headerMatches.add(key);
|
headerMatches.add(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1036,7 +1036,10 @@ class MessageHandler {
|
||||||
} catch (E) {
|
} catch (E) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
subject = this.normalizeSubject(subject);
|
|
||||||
|
subject = this.normalizeSubject(subject, {
|
||||||
|
removePrefix: false
|
||||||
|
});
|
||||||
|
|
||||||
let flags = [].concat(options.flags || []);
|
let flags = [].concat(options.flags || []);
|
||||||
|
|
||||||
|
|
@ -1133,9 +1136,11 @@ class MessageHandler {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
normalizeSubject(subject) {
|
normalizeSubject(subject, options) {
|
||||||
subject = subject.replace(/\s+/g, ' ');
|
options = options || {};
|
||||||
|
subject = subject.replace(/\s+/g, ' ').trim();
|
||||||
|
|
||||||
|
if (options.removePrefix) {
|
||||||
let match = true;
|
let match = true;
|
||||||
while (match) {
|
while (match) {
|
||||||
match = false;
|
match = false;
|
||||||
|
|
@ -1146,6 +1151,7 @@ class MessageHandler {
|
||||||
})
|
})
|
||||||
.trim();
|
.trim();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return subject;
|
return subject;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
"ioredfour": "1.0.2-ioredis-02",
|
"ioredfour": "1.0.2-ioredis-02",
|
||||||
"ioredis": "4.2.0",
|
"ioredis": "4.2.0",
|
||||||
"isemail": "3.2.0",
|
"isemail": "3.2.0",
|
||||||
"joi": "14.0.2",
|
"joi": "14.0.3",
|
||||||
"js-yaml": "3.12.0",
|
"js-yaml": "3.12.0",
|
||||||
"key-fingerprint": "1.1.0",
|
"key-fingerprint": "1.1.0",
|
||||||
"libbase64": "1.0.3",
|
"libbase64": "1.0.3",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue