@remit/mailbox-service 0.0.109 → 0.0.110
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/package.json +1 -1
- package/src/filters/match.test.ts +36 -0
- package/src/filters/match.ts +17 -3
package/package.json
CHANGED
|
@@ -65,6 +65,42 @@ describe("clauseMatches", () => {
|
|
|
65
65
|
);
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
+
it("matches HasWords on the sender display name alone, as search does", () => {
|
|
69
|
+
const msg = message({
|
|
70
|
+
from: "booking@mail.example",
|
|
71
|
+
fromName: "Austrian Airlines Booking",
|
|
72
|
+
subject: "Your trip to Vienna",
|
|
73
|
+
text: "Check in opens 24 hours before departure.",
|
|
74
|
+
});
|
|
75
|
+
assert.equal(
|
|
76
|
+
clauseMatches(
|
|
77
|
+
clause(FilterClauseField.HasWords, "Austrian airlines"),
|
|
78
|
+
msg,
|
|
79
|
+
),
|
|
80
|
+
true,
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("matches HasWords regardless of word order and case", () => {
|
|
85
|
+
assert.equal(
|
|
86
|
+
clauseMatches(
|
|
87
|
+
clause(FilterClauseField.HasWords, "ALICE invoice"),
|
|
88
|
+
message(),
|
|
89
|
+
),
|
|
90
|
+
true,
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("does not match HasWords when one word is missing", () => {
|
|
95
|
+
assert.equal(
|
|
96
|
+
clauseMatches(
|
|
97
|
+
clause(FilterClauseField.HasWords, "invoice receipt"),
|
|
98
|
+
message(),
|
|
99
|
+
),
|
|
100
|
+
false,
|
|
101
|
+
);
|
|
102
|
+
});
|
|
103
|
+
|
|
68
104
|
it("never matches an empty clause value", () => {
|
|
69
105
|
assert.equal(
|
|
70
106
|
clauseMatches(clause(FilterClauseField.HasWords, " "), message()),
|
package/src/filters/match.ts
CHANGED
|
@@ -49,6 +49,20 @@ export interface FilterMessage {
|
|
|
49
49
|
const includesFold = (haystack: string, needle: string): boolean =>
|
|
50
50
|
haystack.toLowerCase().includes(needle.toLowerCase());
|
|
51
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Whether every whitespace-separated word of `value` appears somewhere in the
|
|
54
|
+
* sender address, sender name, subject or body — the shape free-text search
|
|
55
|
+
* matches with (`buildSearchConditions`), so a filter made from a search keeps
|
|
56
|
+
* the mail that search showed.
|
|
57
|
+
*/
|
|
58
|
+
const hasEveryWord = (value: string, msg: FilterMessage): boolean => {
|
|
59
|
+
const fields = [msg.from, msg.fromName, msg.subject, msg.text];
|
|
60
|
+
return value
|
|
61
|
+
.split(/\s+/)
|
|
62
|
+
.filter(Boolean)
|
|
63
|
+
.every((word) => fields.some((field) => includesFold(field, word)));
|
|
64
|
+
};
|
|
65
|
+
|
|
52
66
|
const hostOf = (address: string): string => {
|
|
53
67
|
const at = address.lastIndexOf("@");
|
|
54
68
|
return at >= 0 ? address.slice(at + 1) : address;
|
|
@@ -65,8 +79,8 @@ const registrableDomain = (addressOrHost: string): string | null =>
|
|
|
65
79
|
|
|
66
80
|
/**
|
|
67
81
|
* Whether one literal clause matches the message. From matches against the
|
|
68
|
-
* sender address and display name; Subject against the subject; HasWords
|
|
69
|
-
* subject or body; ListId against the exact normalized `List-Id`; FromDomain
|
|
82
|
+
* sender address and display name; Subject against the subject; HasWords
|
|
83
|
+
* requires every word somewhere in sender, subject or body; ListId against the exact normalized `List-Id`; FromDomain
|
|
70
84
|
* against the sender's registrable domain. An empty clause value never matches.
|
|
71
85
|
*/
|
|
72
86
|
export const clauseMatches = (
|
|
@@ -81,7 +95,7 @@ export const clauseMatches = (
|
|
|
81
95
|
case FilterClauseField.Subject:
|
|
82
96
|
return includesFold(msg.subject, value);
|
|
83
97
|
case FilterClauseField.HasWords:
|
|
84
|
-
return
|
|
98
|
+
return hasEveryWord(value, msg);
|
|
85
99
|
case FilterClauseField.ListId: {
|
|
86
100
|
const target = normalizeListId(value);
|
|
87
101
|
return target !== "" && normalizeListId(msg.listId) === target;
|