list-id filtering

This commit is contained in:
Andris Reinman 2018-11-02 10:18:24 +02:00
parent b4e7387d8b
commit d72198c1bd
4 changed files with 46 additions and 18 deletions

View file

@ -216,6 +216,7 @@ module.exports = (db, server) => {
* @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.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 {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
@ -501,6 +502,7 @@ module.exports = (db, server) => {
* @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.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 {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
@ -574,6 +576,10 @@ module.exports = (db, server) => {
.trim()
.max(255)
.empty(''),
listId: Joi.string()
.trim()
.max(255)
.empty(''),
text: Joi.string()
.trim()
.max(255)
@ -669,7 +675,7 @@ module.exports = (db, server) => {
filterData.name = result.value.name;
}
['from', 'to', 'subject'].forEach(key => {
['from', 'to', 'subject', 'listId'].forEach(key => {
if (result.value.query[key]) {
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.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.listId] Partial match for the List-ID: header (case insensitive)
* @apiParam {String} [query.text] Fulltext search against message text
* @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
@ -896,6 +903,10 @@ module.exports = (db, server) => {
.trim()
.max(255)
.empty(''),
listId: Joi.string()
.trim()
.max(255)
.empty(''),
text: Joi.string()
.trim()
.max(255)
@ -993,7 +1004,7 @@ module.exports = (db, server) => {
hasChanges = true;
}
['from', 'to', 'subject'].forEach(key => {
['from', 'to', 'subject', 'listId'].forEach(key => {
if (result.value.query[key]) {
$set['query.headers.' + key] = result.value.query[key].replace(/\s+/g, ' ');
hasChanges = true;

View file

@ -602,12 +602,21 @@ function checkFilter(filter, prepared, maildata) {
let headerFilters = new Map();
if (query.headers) {
Object.keys(query.headers).forEach(key => {
let header = key.replace(/[A-Z]+/g, c => '-' + c.toLowerCase());
let value = query.headers[key];
if (!value || !value.isRegex) {
value = (query.headers[key] || '').toString().toLowerCase();
}
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)) {
let check = headerFilters.get(key);
let value = (header.value || '').toString();
if (check.isRegex) {
if (check.test(header.value)) {
if (check.test(value)) {
headerMatches.add(key);
}
} else if (header.value === check || header.value.indexOf(check) >= 0) {
} else if (value === check || value.indexOf(check) >= 0) {
headerMatches.add(key);
}
}

View file

@ -1036,7 +1036,10 @@ class MessageHandler {
} catch (E) {
// ignore
}
subject = this.normalizeSubject(subject);
subject = this.normalizeSubject(subject, {
removePrefix: false
});
let flags = [].concat(options.flags || []);
@ -1133,18 +1136,21 @@ class MessageHandler {
);
}
normalizeSubject(subject) {
subject = subject.replace(/\s+/g, ' ');
normalizeSubject(subject, options) {
options = options || {};
subject = subject.replace(/\s+/g, ' ').trim();
let match = true;
while (match) {
match = false;
subject = subject
.replace(/^(re|fwd?)\s*:|\s*\(fwd\)\s*$/gi, () => {
match = true;
return '';
})
.trim();
if (options.removePrefix) {
let match = true;
while (match) {
match = false;
subject = subject
.replace(/^(re|fwd?)\s*:|\s*\(fwd\)\s*$/gi, () => {
match = true;
return '';
})
.trim();
}
}
return subject;

View file

@ -50,7 +50,7 @@
"ioredfour": "1.0.2-ioredis-02",
"ioredis": "4.2.0",
"isemail": "3.2.0",
"joi": "14.0.2",
"joi": "14.0.3",
"js-yaml": "3.12.0",
"key-fingerprint": "1.1.0",
"libbase64": "1.0.3",