@wirecat/cli-memo 0.29.0 → 0.31.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/README.md +1 -1
- package/dist/actions/command.js +5 -5
- package/dist/actions/command.js.map +1 -1
- package/dist/agents/command.js +1 -1
- package/dist/agents/command.js.map +1 -1
- package/dist/answers/command.d.ts.map +1 -1
- package/dist/answers/command.js +4 -3
- package/dist/answers/command.js.map +1 -1
- package/dist/bin/memo.js +8 -0
- package/dist/bin/memo.js.map +1 -1
- package/dist/config.d.ts +8 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +15 -7
- package/dist/config.js.map +1 -1
- package/dist/context/command.d.ts.map +1 -1
- package/dist/context/command.js +4 -3
- package/dist/context/command.js.map +1 -1
- package/dist/discovery/command.d.ts +1 -1
- package/dist/discovery/command.js +2 -2
- package/dist/discovery/command.js.map +1 -1
- package/dist/doctor/command.d.ts +81 -0
- package/dist/doctor/command.d.ts.map +1 -0
- package/dist/doctor/command.js +150 -0
- package/dist/doctor/command.js.map +1 -0
- package/dist/effects.d.ts.map +1 -1
- package/dist/effects.js +3 -0
- package/dist/effects.js.map +1 -1
- package/dist/examples.d.ts.map +1 -1
- package/dist/examples.js +3 -0
- package/dist/examples.js.map +1 -1
- package/dist/facts/command.js +5 -5
- package/dist/facts/command.js.map +1 -1
- package/dist/json-fields.d.ts +16 -0
- package/dist/json-fields.d.ts.map +1 -0
- package/dist/json-fields.js +53 -0
- package/dist/json-fields.js.map +1 -0
- package/dist/knowledge/command.d.ts.map +1 -1
- package/dist/knowledge/command.js +17 -21
- package/dist/knowledge/command.js.map +1 -1
- package/dist/knowledge/meeting-projects-command.js +1 -1
- package/dist/knowledge/meeting-projects-command.js.map +1 -1
- package/dist/mail/command.d.ts.map +1 -1
- package/dist/mail/command.js +62 -17
- package/dist/mail/command.js.map +1 -1
- package/dist/mail/domain-age.d.ts +21 -0
- package/dist/mail/domain-age.d.ts.map +1 -0
- package/dist/mail/domain-age.js +99 -0
- package/dist/mail/domain-age.js.map +1 -0
- package/dist/mail/gmail.d.ts +12 -3
- package/dist/mail/gmail.d.ts.map +1 -1
- package/dist/mail/gmail.js +29 -18
- package/dist/mail/gmail.js.map +1 -1
- package/dist/mail/headers.d.ts +20 -1
- package/dist/mail/headers.d.ts.map +1 -1
- package/dist/mail/headers.js +49 -3
- package/dist/mail/headers.js.map +1 -1
- package/dist/mail/himalaya.d.ts +5 -0
- package/dist/mail/himalaya.d.ts.map +1 -1
- package/dist/mail/himalaya.js +34 -5
- package/dist/mail/himalaya.js.map +1 -1
- package/dist/mail/import.d.ts +7 -1
- package/dist/mail/import.d.ts.map +1 -1
- package/dist/mail/import.js +120 -3
- package/dist/mail/import.js.map +1 -1
- package/dist/mail/mbox.d.ts.map +1 -1
- package/dist/mail/mbox.js +5 -1
- package/dist/mail/mbox.js.map +1 -1
- package/dist/mail/messages-command.d.ts.map +1 -1
- package/dist/mail/messages-command.js +4 -3
- package/dist/mail/messages-command.js.map +1 -1
- package/dist/mail/probe.d.ts +7 -1
- package/dist/mail/probe.d.ts.map +1 -1
- package/dist/mail/probe.js +12 -1
- package/dist/mail/probe.js.map +1 -1
- package/dist/mail/resume.d.ts +46 -0
- package/dist/mail/resume.d.ts.map +1 -0
- package/dist/mail/resume.js +62 -0
- package/dist/mail/resume.js.map +1 -0
- package/dist/mail/rules.d.ts +2 -2
- package/dist/mail/rules.d.ts.map +1 -1
- package/dist/mail/rules.js +3 -3
- package/dist/mail/rules.js.map +1 -1
- package/dist/mail/score.d.ts +50 -0
- package/dist/mail/score.d.ts.map +1 -0
- package/dist/mail/score.js +118 -0
- package/dist/mail/score.js.map +1 -0
- package/dist/mail/source.d.ts +11 -2
- package/dist/mail/source.d.ts.map +1 -1
- package/dist/mail/source.js +7 -3
- package/dist/mail/source.js.map +1 -1
- package/dist/mail/status.d.ts +26 -0
- package/dist/mail/status.d.ts.map +1 -0
- package/dist/mail/status.js +59 -0
- package/dist/mail/status.js.map +1 -0
- package/dist/memories/command.js +6 -6
- package/dist/memories/command.js.map +1 -1
- package/dist/notes/command.js +6 -6
- package/dist/notes/command.js.map +1 -1
- package/dist/notes/folders-command.d.ts.map +1 -1
- package/dist/notes/folders-command.js +6 -4
- package/dist/notes/folders-command.js.map +1 -1
- package/dist/notes/search.js +1 -1
- package/dist/notes/search.js.map +1 -1
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +1 -1
- package/dist/options.js.map +1 -1
- package/dist/output.d.ts +9 -0
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +35 -3
- package/dist/output.js.map +1 -1
- package/dist/program.d.ts +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +9 -1
- package/dist/program.js.map +1 -1
- package/dist/reasons.d.ts.map +1 -1
- package/dist/reasons.js +6 -0
- package/dist/reasons.js.map +1 -1
- package/dist/records/run.d.ts +1 -1
- package/dist/records/run.d.ts.map +1 -1
- package/dist/records/run.js +3 -3
- package/dist/records/run.js.map +1 -1
- package/dist/run/auto.d.ts +11 -1
- package/dist/run/auto.d.ts.map +1 -1
- package/dist/run/auto.js +40 -8
- package/dist/run/auto.js.map +1 -1
- package/dist/run/import.d.ts.map +1 -1
- package/dist/run/import.js +12 -5
- package/dist/run/import.js.map +1 -1
- package/dist/search/answers.d.ts +61 -0
- package/dist/search/answers.d.ts.map +1 -0
- package/dist/search/answers.js +39 -0
- package/dist/search/answers.js.map +1 -0
- package/dist/search/command.d.ts.map +1 -1
- package/dist/search/command.js +10 -6
- package/dist/search/command.js.map +1 -1
- package/dist/tags/command.d.ts.map +1 -1
- package/dist/tags/command.js +11 -3
- package/dist/tags/command.js.map +1 -1
- package/dist/tasks/command.js +2 -2
- package/dist/tasks/command.js.map +1 -1
- package/dist/tasks/relations-command.js +3 -3
- package/dist/tasks/relations-command.js.map +1 -1
- package/dist/update.d.ts +26 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +67 -0
- package/dist/update.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/vocabulary/command.js +4 -4
- package/dist/vocabulary/command.js.map +1 -1
- package/package.json +5 -3
- package/skills/cli-memo/SKILL.md +12 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages-command.d.ts","sourceRoot":"","sources":["../../src/mail/messages-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAI1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAKxC,eAAO,MAAM,eAAe,YAAa,OAAO,WAAW,OAAO,OAAO,MAAM,CAAC,UAAU,KAAG,
|
|
1
|
+
{"version":3,"file":"messages-command.d.ts","sourceRoot":"","sources":["../../src/mail/messages-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAI1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAKxC,eAAO,MAAM,eAAe,YAAa,OAAO,WAAW,OAAO,OAAO,MAAM,CAAC,UAAU,KAAG,IAuB5F,CAAA"}
|
|
@@ -3,7 +3,7 @@ import { parseLocator } from "@wirecat/cli-core";
|
|
|
3
3
|
import { readMail } from "@wirecat/cli-core/services";
|
|
4
4
|
import { openStore } from "@wirecat/cli-core/store";
|
|
5
5
|
import { whole } from "../options.js";
|
|
6
|
-
import { printAtDetail } from "../output.js";
|
|
6
|
+
import { envelopeOf, printAtDetail } from "../output.js";
|
|
7
7
|
import { found } from "../search/command.js";
|
|
8
8
|
export const messagesCommand = (program, streams, env) => {
|
|
9
9
|
const messages = program.command("messages").description("stored emails; tg and max read messenger messages");
|
|
@@ -13,15 +13,16 @@ export const messagesCommand = (program, streams, env) => {
|
|
|
13
13
|
.argument("<message>", "the email's msg:email/… reference, as search answers give it")
|
|
14
14
|
.option("--before-n <n>", "also this many earlier emails of its thread", whole, 0)
|
|
15
15
|
.option("--after-n <n>", "also this many later emails of its thread", whole, 0)
|
|
16
|
-
.option("--json", "print JSON")
|
|
16
|
+
.option("--json", "print JSON; --json=id,title keeps only those fields")
|
|
17
17
|
.action(async (reference, options) => {
|
|
18
18
|
if (parseLocator(reference).provider !== "email")
|
|
19
19
|
throw new CliError("validation_error", `${reference} is not an email; tg and max show messenger messages`);
|
|
20
|
+
const startedAt = Date.now();
|
|
20
21
|
const store = await openStore({ env });
|
|
21
22
|
try {
|
|
22
23
|
const emails = await readMail(store, reference, { before: options.beforeN, after: options.afterN });
|
|
23
24
|
if (options.json)
|
|
24
|
-
printAtDetail(streams, options.beforeN || options.afterN ?
|
|
25
|
+
printAtDetail(streams, envelopeOf(options.beforeN || options.afterN ? emails : emails[0], startedAt));
|
|
25
26
|
else
|
|
26
27
|
streams.data(`${emails.map((email) => found(email, "full")).join("\n\n")}\n`);
|
|
27
28
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages-command.js","sourceRoot":"","sources":["../../src/mail/messages-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAgB,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAEnD,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"messages-command.js","sourceRoot":"","sources":["../../src/mail/messages-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAgB,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAEnD,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AACrC,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAE5C,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAgB,EAAE,OAAgB,EAAE,GAAsB,EAAQ,EAAE;IAClG,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,mDAAmD,CAAC,CAAA;IAC7G,QAAQ;SACL,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,iEAAiE,CAAC;SAC9E,QAAQ,CAAC,WAAW,EAAE,8DAA8D,CAAC;SACrF,MAAM,CAAC,gBAAgB,EAAE,6CAA6C,EAAE,KAAK,EAAE,CAAC,CAAC;SACjF,MAAM,CAAC,eAAe,EAAE,2CAA2C,EAAE,KAAK,EAAE,CAAC,CAAC;SAC9E,MAAM,CAAC,QAAQ,EAAE,qDAAqD,CAAC;SACvE,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,OAA4D,EAAE,EAAE;QAChG,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC,QAAQ,KAAK,OAAO;YAC9C,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,GAAG,SAAS,sDAAsD,CAAC,CAAA;QAC5G,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC5B,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;QACtC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;YACnG,IAAI,OAAO,CAAC,IAAI;gBACd,aAAa,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAA;;gBAClG,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACpF,CAAC;gBAAS,CAAC;YACT,MAAM,KAAK,CAAC,KAAK,EAAE,CAAA;QACrB,CAAC;IACH,CAAC,CAAC,CAAA;AACN,CAAC,CAAA"}
|
package/dist/mail/probe.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type DomainAge, type Signal } from "./score.js";
|
|
1
2
|
import type { Listed } from "./source.js";
|
|
2
3
|
export declare const SUGGEST_RULE: string;
|
|
3
4
|
export interface ProbeGroup {
|
|
@@ -15,6 +16,9 @@ export interface ProbeGroup {
|
|
|
15
16
|
/** The owner sent mail to one of the group's senders. */
|
|
16
17
|
replied: boolean;
|
|
17
18
|
suggest: "skip" | null;
|
|
19
|
+
/** How much the group looks like spam, a scam or a robot: the sum of its signals' weights (SCORE_RULE). */
|
|
20
|
+
score: number;
|
|
21
|
+
signals: Signal[];
|
|
18
22
|
}
|
|
19
23
|
export interface Probe {
|
|
20
24
|
emails: number;
|
|
@@ -27,5 +31,7 @@ export interface Probe {
|
|
|
27
31
|
items: ProbeGroup[];
|
|
28
32
|
}
|
|
29
33
|
/** Groups mail by List-Id when it has one, else by sender address; largest groups first. */
|
|
30
|
-
export declare const probeMail: (items: Listed[], limit: number) => Probe;
|
|
34
|
+
export declare const probeMail: (items: Listed[], limit: number, ages?: ReadonlyMap<string, DomainAge>) => Probe;
|
|
35
|
+
/** The sender domains of the groups worth asking a registry about: not a big mailbox provider, never replied to. */
|
|
36
|
+
export declare const domainsToAge: (groups: ProbeGroup[], skip: ReadonlySet<string>) => string[];
|
|
31
37
|
//# sourceMappingURL=probe.d.ts.map
|
package/dist/mail/probe.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../../src/mail/probe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,eAAO,MAAM,YAAY,QAEsE,CAAA;AAE/F,MAAM,WAAW,UAAU;IACzB,qDAAqD;IACrD,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,mEAAmE;IACnE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,yDAAyD;IACzD,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../../src/mail/probe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAiB,KAAK,MAAM,EAAc,MAAM,YAAY,CAAA;AACnF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,eAAO,MAAM,YAAY,QAEsE,CAAA;AAE/F,MAAM,WAAW,UAAU;IACzB,qDAAqD;IACrD,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,mEAAmE;IACnE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,yDAAyD;IACzD,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,2GAA2G;IAC3G,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAA;IACZ,2DAA2D;IAC3D,cAAc,EAAE,MAAM,CAAA;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,UAAU,EAAE,CAAA;CACpB;AAMD,4FAA4F;AAC5F,eAAO,MAAM,SAAS,UAAW,MAAM,EAAE,SAAS,MAAM,SAAQ,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,KAAe,KA8C5G,CAAA;AAED,oHAAoH;AACpH,eAAO,MAAM,YAAY,WAAY,UAAU,EAAE,QAAQ,WAAW,CAAC,MAAM,CAAC,KAAG,MAAM,EAQpF,CAAA"}
|
package/dist/mail/probe.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { registrableOf, scoreGroup } from "./score.js";
|
|
1
2
|
export const SUGGEST_RULE = "suggest is skip when a group has at least 20 emails, at least 80% of them list or bulk mail " +
|
|
2
3
|
"(List-Id, List-Unsubscribe or Precedence: bulk) and the owner never sent mail to its sender";
|
|
3
4
|
const share = (part, whole) => Math.round((part / whole) * 100) / 100;
|
|
4
5
|
const isSent = (item) => item.labels?.includes("Sent") || /(^|\/)sent\b/i.test(item.folder ?? "");
|
|
5
6
|
/** Groups mail by List-Id when it has one, else by sender address; largest groups first. */
|
|
6
|
-
export const probeMail = (items, limit) => {
|
|
7
|
+
export const probeMail = (items, limit, ages = new Map()) => {
|
|
7
8
|
const sent = items.filter(isSent);
|
|
8
9
|
const recipients = new Set(sent.flatMap((item) => item.headers?.to ?? []));
|
|
9
10
|
const groups = new Map();
|
|
@@ -40,6 +41,7 @@ export const probeMail = (items, limit) => {
|
|
|
40
41
|
lastYear: years.reduce((a, b) => Math.max(a, b)),
|
|
41
42
|
replied,
|
|
42
43
|
suggest: group.length >= 20 && bulk >= 0.8 && !replied ? "skip" : null,
|
|
44
|
+
...scoreGroup(group, { replied, bulk, ages }),
|
|
43
45
|
};
|
|
44
46
|
});
|
|
45
47
|
all.sort((a, b) => b.emails - a.emails || b.bytes - a.bytes);
|
|
@@ -52,4 +54,13 @@ export const probeMail = (items, limit) => {
|
|
|
52
54
|
items: all.slice(0, limit),
|
|
53
55
|
};
|
|
54
56
|
};
|
|
57
|
+
/** The sender domains of the groups worth asking a registry about: not a big mailbox provider, never replied to. */
|
|
58
|
+
export const domainsToAge = (groups, skip) => [
|
|
59
|
+
...new Set(groups.flatMap((group) => {
|
|
60
|
+
if (group.replied || group.from === null)
|
|
61
|
+
return [];
|
|
62
|
+
const domain = registrableOf(group.from);
|
|
63
|
+
return skip.has(domain) ? [] : [domain];
|
|
64
|
+
})),
|
|
65
|
+
];
|
|
55
66
|
//# sourceMappingURL=probe.js.map
|
package/dist/mail/probe.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"probe.js","sourceRoot":"","sources":["../../src/mail/probe.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"probe.js","sourceRoot":"","sources":["../../src/mail/probe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,aAAa,EAAe,UAAU,EAAE,MAAM,YAAY,CAAA;AAGnF,MAAM,CAAC,MAAM,YAAY,GACvB,8FAA8F;IAC9F,6FAA6F,CAAA;AAiC/F,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,KAAa,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAA;AAErF,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAA;AAEzG,4FAA4F;AAC5F,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAe,EAAE,KAAa,EAAE,IAAI,GAAmC,IAAI,GAAG,EAAE,EAAS,EAAE;IACnH,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACjC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAC1E,MAAM,MAAM,GAAG,IAAI,GAAG,EAAoB,CAAA;IAC1C,IAAI,cAAc,GAAG,CAAC,CAAA;IACtB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,MAAM,CAAC,IAAI,CAAC;YAAE,SAAQ;QAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;QAC5B,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,EAAE,CAAC;YAC1F,cAAc,EAAE,CAAA;YAChB,SAAQ;QACV,CAAC;QACD,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAA;QAC5F,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC7B,IAAI,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;;YACtB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;IAC9B,CAAC;IACD,MAAM,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAc,EAAE;QACzD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;QAC/G,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAA;QAC7D,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,cAAc,EAAE,CAAC,CAAA;QAC7E,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;QACnF,MAAM,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;QACrE,OAAO;YACL,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI;YAC7B,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,IAAI,IAAI;YACzC,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;YAC7D,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI;YAC5F,IAAI;YACJ,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACjD,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAChD,OAAO;YACP,OAAO,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;YACtE,GAAG,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;SAC9C,CAAA;IACH,CAAC,CAAC,CAAA;IACF,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAA;IAC5D,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7D,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,cAAc;QACd,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;KAC3B,CAAA;AACH,CAAC,CAAA;AAED,oHAAoH;AACpH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAoB,EAAE,IAAyB,EAAY,EAAE,CAAC;IACzF,GAAG,IAAI,GAAG,CACR,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QACvB,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,EAAE,CAAA;QACnD,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACxC,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;IACzC,CAAC,CAAC,CACH;CACF,CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { MailRule } from "./rules.js";
|
|
2
|
+
/** Inclusive UID stretches, sorted and apart: a mailbox read newest first in batches stays a few stretches. */
|
|
3
|
+
export type Ranges = [number, number][];
|
|
4
|
+
/** Where a folder's listing stopped, kept in the store beside the mail it describes, so a restored backup agrees. */
|
|
5
|
+
export interface ResumePoint {
|
|
6
|
+
validity: string;
|
|
7
|
+
done: Ranges;
|
|
8
|
+
/** The rules the done mail was decided under; other rules decide it again. */
|
|
9
|
+
rules: string;
|
|
10
|
+
/**
|
|
11
|
+
* The widest recent listing of every message, the only kind that proves deletions and refreshes labels and
|
|
12
|
+
* flags: a later run whose window it covers may list only what is not done.
|
|
13
|
+
*/
|
|
14
|
+
full: {
|
|
15
|
+
since: string;
|
|
16
|
+
at: string;
|
|
17
|
+
};
|
|
18
|
+
/** The widest window searched: its messages, and how many of them are done; a narrower run leaves it. */
|
|
19
|
+
window: {
|
|
20
|
+
since: string;
|
|
21
|
+
total: number;
|
|
22
|
+
done: number;
|
|
23
|
+
};
|
|
24
|
+
updatedAt: string;
|
|
25
|
+
}
|
|
26
|
+
/** A whole listing at least this often, so deletions, labels and read state are never more than a day old. */
|
|
27
|
+
export declare const FULL_PASS_MS = 86400000;
|
|
28
|
+
export declare const resumeKey: (folder: string) => string;
|
|
29
|
+
/** An mbox file has no UIDs: an unchanged file read to the end has nothing new. */
|
|
30
|
+
export declare const MBOX_RESUME = "mail_resume:mbox";
|
|
31
|
+
export interface FileStamp {
|
|
32
|
+
size: number;
|
|
33
|
+
mtimeMs: number;
|
|
34
|
+
}
|
|
35
|
+
export interface MboxPoint extends FileStamp {
|
|
36
|
+
/** Every email of the file was read: a run cut short by --limit reads it again. */
|
|
37
|
+
complete: boolean;
|
|
38
|
+
updatedAt: string;
|
|
39
|
+
}
|
|
40
|
+
export declare const rangesOf: (values: Iterable<number>) => Ranges;
|
|
41
|
+
export declare const mergeRanges: (a: Ranges, b: Ranges) => Ranges;
|
|
42
|
+
export declare const within: (ranges: Ranges, value: number) => boolean;
|
|
43
|
+
/** Only what decides mail: a changed reason or date is the same rule. */
|
|
44
|
+
export declare const rulesKey: (rules: readonly MailRule[]) => string;
|
|
45
|
+
export declare const parsePoint: <T>(value: string | undefined) => T | undefined;
|
|
46
|
+
//# sourceMappingURL=resume.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../src/mail/resume.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE1C,+GAA+G;AAC/G,MAAM,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;AAEvC,qHAAqH;AACrH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;IACnC,yGAAyG;IACzG,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IACtD,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,8GAA8G;AAC9G,eAAO,MAAM,YAAY,WAAa,CAAA;AAEtC,eAAO,MAAM,SAAS,WAAY,MAAM,KAAG,MAAiC,CAAA;AAE5E,mFAAmF;AACnF,eAAO,MAAM,WAAW,qBAAqB,CAAA;AAE7C,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,mFAAmF;IACnF,QAAQ,EAAE,OAAO,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,eAAO,MAAM,QAAQ,WAAY,QAAQ,CAAC,MAAM,CAAC,KAAG,MASnD,CAAA;AAED,eAAO,MAAM,WAAW,MAAO,MAAM,KAAK,MAAM,KAAG,MAQlD,CAAA;AAED,eAAO,MAAM,MAAM,WAAY,MAAM,SAAS,MAAM,KAAG,OAWtD,CAAA;AAED,yEAAyE;AACzE,eAAO,MAAM,QAAQ,UAAW,SAAS,QAAQ,EAAE,KAAG,MAYrC,CAAA;AAEjB,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,MAAM,GAAG,SAAS,KAAG,CAAC,GAAG,SAO7D,CAAA"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
/** A whole listing at least this often, so deletions, labels and read state are never more than a day old. */
|
|
3
|
+
export const FULL_PASS_MS = 86_400_000;
|
|
4
|
+
export const resumeKey = (folder) => `mail_resume:${folder}`;
|
|
5
|
+
/** An mbox file has no UIDs: an unchanged file read to the end has nothing new. */
|
|
6
|
+
export const MBOX_RESUME = "mail_resume:mbox";
|
|
7
|
+
export const rangesOf = (values) => {
|
|
8
|
+
const sorted = [...new Set(values)].sort((a, b) => a - b);
|
|
9
|
+
const ranges = [];
|
|
10
|
+
for (const value of sorted) {
|
|
11
|
+
const last = ranges.at(-1);
|
|
12
|
+
if (last !== undefined && value === last[1] + 1)
|
|
13
|
+
last[1] = value;
|
|
14
|
+
else
|
|
15
|
+
ranges.push([value, value]);
|
|
16
|
+
}
|
|
17
|
+
return ranges;
|
|
18
|
+
};
|
|
19
|
+
export const mergeRanges = (a, b) => {
|
|
20
|
+
const merged = [];
|
|
21
|
+
for (const [from, to] of [...a, ...b].sort(([x], [y]) => x - y)) {
|
|
22
|
+
const last = merged.at(-1);
|
|
23
|
+
if (last !== undefined && from <= last[1] + 1)
|
|
24
|
+
last[1] = Math.max(last[1], to);
|
|
25
|
+
else
|
|
26
|
+
merged.push([from, to]);
|
|
27
|
+
}
|
|
28
|
+
return merged;
|
|
29
|
+
};
|
|
30
|
+
export const within = (ranges, value) => {
|
|
31
|
+
let low = 0;
|
|
32
|
+
let high = ranges.length - 1;
|
|
33
|
+
while (low <= high) {
|
|
34
|
+
const middle = (low + high) >> 1;
|
|
35
|
+
const [from, to] = ranges[middle];
|
|
36
|
+
if (value < from)
|
|
37
|
+
high = middle - 1;
|
|
38
|
+
else if (value > to)
|
|
39
|
+
low = middle + 1;
|
|
40
|
+
else
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
};
|
|
45
|
+
/** Only what decides mail: a changed reason or date is the same rule. */
|
|
46
|
+
export const rulesKey = (rules) => createHash("sha256")
|
|
47
|
+
.update(JSON.stringify(rules
|
|
48
|
+
.map(({ match, action }) => JSON.stringify([action, match.from ?? null, match.domain ?? null, match.list_id ?? null]))
|
|
49
|
+
.sort()))
|
|
50
|
+
.digest("hex")
|
|
51
|
+
.slice(0, 16);
|
|
52
|
+
export const parsePoint = (value) => {
|
|
53
|
+
if (value === undefined)
|
|
54
|
+
return undefined;
|
|
55
|
+
try {
|
|
56
|
+
return JSON.parse(value);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=resume.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume.js","sourceRoot":"","sources":["../../src/mail/resume.ts"],"names":[],"mappings":"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"}
|
package/dist/mail/rules.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { MailHeaders } from "./headers.js";
|
|
|
2
2
|
export interface MailRuleMatch {
|
|
3
3
|
from?: string;
|
|
4
4
|
domain?: string;
|
|
5
|
-
|
|
5
|
+
list_id?: string;
|
|
6
6
|
}
|
|
7
7
|
export type MailAction = "skip" | "envelope" | "keep";
|
|
8
8
|
export interface MailRule {
|
|
@@ -10,7 +10,7 @@ export interface MailRule {
|
|
|
10
10
|
/** skip: never read or stored · envelope: stored without its text, so it can be counted and cleaned later. */
|
|
11
11
|
action: MailAction;
|
|
12
12
|
reason?: string;
|
|
13
|
-
|
|
13
|
+
decided_at: string;
|
|
14
14
|
}
|
|
15
15
|
/** A domain also matches its subdomains: bulk mail often comes from `mail.` or `news.` of the same domain. */
|
|
16
16
|
export declare const matches: (match: MailRuleMatch, headers: MailHeaders) => boolean;
|
package/dist/mail/rules.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/mail/rules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/mail/rules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAA;AAErD,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,aAAa,CAAA;IACpB,8GAA8G;IAC9G,MAAM,EAAE,UAAU,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;CACnB;AAID,8GAA8G;AAC9G,eAAO,MAAM,OAAO,UAAW,aAAa,WAAW,WAAW,KAAG,OAWpE,CAAA;AAID;;;GAGG;AACH,eAAO,MAAM,MAAM,UAAW,SAAS,QAAQ,EAAE,WAAW,WAAW,GAAG,SAAS,KAAG,QAAQ,GAAG,SAGhG,CAAA;AAED,mGAAmG;AACnG,eAAO,MAAM,WAAW,UAAW,aAAa;;;;CAY/C,CAAA;AAED,eAAO,MAAM,QAAQ,aAAa,CAAA;AAElC,eAAO,MAAM,SAAS,MAAO,aAAa,KAAK,aAAa,KAAG,OAGR,CAAA;AAEvD,eAAO,MAAM,aAAa,eAAgB,MAAM;;;;CAG/C,CAAA"}
|
package/dist/mail/rules.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const domainOf = (address) => address.slice(address.lastIndexOf("@") + 1);
|
|
2
2
|
/** A domain also matches its subdomains: bulk mail often comes from `mail.` or `news.` of the same domain. */
|
|
3
3
|
export const matches = (match, headers) => {
|
|
4
|
-
const { from, domain, listId } = match;
|
|
4
|
+
const { from, domain, list_id: listId } = match;
|
|
5
5
|
if (from === undefined && domain === undefined && listId === undefined)
|
|
6
6
|
return false;
|
|
7
7
|
const sender = headers.from;
|
|
@@ -27,7 +27,7 @@ export const envelopeBox = (match) => {
|
|
|
27
27
|
? ["from", match.from]
|
|
28
28
|
: match.domain !== undefined
|
|
29
29
|
? ["domain", match.domain]
|
|
30
|
-
: ["list-id", match.
|
|
30
|
+
: ["list-id", match.list_id ?? ""];
|
|
31
31
|
return {
|
|
32
32
|
externalId: `memo:envelope:${kind}:${value.toLowerCase()}`,
|
|
33
33
|
name: `envelope: ${kind} ${value}`,
|
|
@@ -37,7 +37,7 @@ export const envelopeBox = (match) => {
|
|
|
37
37
|
export const ENVELOPE = "envelope";
|
|
38
38
|
export const sameMatch = (a, b) => a.from?.toLowerCase() === b.from?.toLowerCase() &&
|
|
39
39
|
a.domain?.toLowerCase() === b.domain?.toLowerCase() &&
|
|
40
|
-
a.
|
|
40
|
+
a.list_id?.toLowerCase() === b.list_id?.toLowerCase();
|
|
41
41
|
export const envelopeBoxOf = (externalId) => {
|
|
42
42
|
const [, , kind, ...value] = externalId.split(":");
|
|
43
43
|
return { externalId, name: `envelope: ${kind} ${value.join(":")}`, kind: ENVELOPE };
|
package/dist/mail/rules.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/mail/rules.ts"],"names":[],"mappings":"AAkBA,MAAM,QAAQ,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;AAEzF,8GAA8G;AAC9G,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,KAAoB,EAAE,OAAoB,EAAW,EAAE;IAC7E,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/mail/rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Listed } from "./source.js";
|
|
2
|
+
/**
|
|
3
|
+
* How much each sign of spam, a scam or a robot adds to a sender's score. Gmail filters spam before it reaches
|
|
4
|
+
* All Mail, so these mostly find what got through: spoofed senders, scams and robots no rule covers yet.
|
|
5
|
+
*/
|
|
6
|
+
export declare const WEIGHTS: {
|
|
7
|
+
readonly spam_folder: 4;
|
|
8
|
+
readonly dmarc_fail: 3;
|
|
9
|
+
readonly brand_spoof: 3;
|
|
10
|
+
readonly young_domain: 3;
|
|
11
|
+
readonly reply_to_elsewhere: 2;
|
|
12
|
+
readonly disposable_domain: 2;
|
|
13
|
+
readonly bulk_never_replied: 1;
|
|
14
|
+
readonly replied: -5;
|
|
15
|
+
};
|
|
16
|
+
export type Signal = keyof typeof WEIGHTS;
|
|
17
|
+
export declare const SCORE_RULE: string;
|
|
18
|
+
/** A domain registered too recently to trust: under this many days old when the mail arrived. */
|
|
19
|
+
export declare const YOUNG_DAYS = 180;
|
|
20
|
+
/** What the registry said about a domain; `created` is ISO 8601, `unsupported` when its registry has no RDAP. */
|
|
21
|
+
export interface DomainAge {
|
|
22
|
+
created?: string;
|
|
23
|
+
unsupported?: boolean;
|
|
24
|
+
checkedAt: string;
|
|
25
|
+
}
|
|
26
|
+
/** The part of a host a person registers: `mail.news.example.co.uk` is `example.co.uk`. */
|
|
27
|
+
export declare const registrableOf: (address: string) => string;
|
|
28
|
+
/**
|
|
29
|
+
* The big mailbox providers. Their domains are years old and say nothing about the sender, so they are never
|
|
30
|
+
* looked up; a brand display name sent from one of them is the classic scam.
|
|
31
|
+
*/
|
|
32
|
+
export declare const FREE_MAIL: Set<string>;
|
|
33
|
+
/** The brand a display name claims while the address belongs to someone else, if any. */
|
|
34
|
+
export declare const spoofedBrand: (name: string | undefined, address: string | undefined) => string | undefined;
|
|
35
|
+
/** Under YOUNG_DAYS old at `at`; false when the age is not known. */
|
|
36
|
+
export declare const youngAt: (age: DomainAge | undefined, at: string) => boolean;
|
|
37
|
+
export interface Scored {
|
|
38
|
+
score: number;
|
|
39
|
+
signals: Signal[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A sender group's score from the facts its emails carry. A sign counts when it holds for at least half the group's
|
|
43
|
+
* emails, so one odd email does not mark a sender; a spoofed brand counts on any one.
|
|
44
|
+
*/
|
|
45
|
+
export declare const scoreGroup: (items: Listed[], context: {
|
|
46
|
+
replied: boolean;
|
|
47
|
+
bulk: number;
|
|
48
|
+
ages: ReadonlyMap<string, DomainAge>;
|
|
49
|
+
}) => Scored;
|
|
50
|
+
//# sourceMappingURL=score.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"score.d.ts","sourceRoot":"","sources":["../../src/mail/score.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC;;;GAGG;AACH,eAAO,MAAM,OAAO;aAClB,WAAW,EAAE,CAAC;aACd,UAAU,EAAE,CAAC;aACb,WAAW,EAAE,CAAC;aACd,YAAY,EAAE,CAAC;aACf,kBAAkB,EAAE,CAAC;aACrB,iBAAiB,EAAE,CAAC;aACpB,kBAAkB,EAAE,CAAC;aACrB,OAAO,EAAE,CAAC,CAAC;CACH,CAAA;AAEV,MAAM,MAAM,MAAM,GAAG,MAAM,OAAO,OAAO,CAAA;AAEzC,eAAO,MAAM,UAAU,QAG6E,CAAA;AAEpG,iGAAiG;AACjG,eAAO,MAAM,UAAU,MAAM,CAAA;AAE7B,iHAAiH;AACjH,MAAM,WAAW,SAAS;IACxB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,2FAA2F;AAC3F,eAAO,MAAM,aAAa,YAAa,MAAM,KAAG,MAG/C,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,aAwBpB,CAAA;AAuBF,yFAAyF;AACzF,eAAO,MAAM,YAAY,SAAU,MAAM,GAAG,SAAS,WAAW,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAM7F,CAAA;AAID,qEAAqE;AACrE,eAAO,MAAM,OAAO,QAAS,SAAS,GAAG,SAAS,MAAM,MAAM,KAAG,OAC6B,CAAA;AAE9F,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAKD;;;GAGG;AACH,eAAO,MAAM,UAAU,UACd,MAAM,EAAE,WACN;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;CAAE,KAChF,MAsBF,CAAA"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { isDisposableEmailDomain } from "disposable-email-domains-js";
|
|
2
|
+
import { getDomain } from "tldts";
|
|
3
|
+
/**
|
|
4
|
+
* How much each sign of spam, a scam or a robot adds to a sender's score. Gmail filters spam before it reaches
|
|
5
|
+
* All Mail, so these mostly find what got through: spoofed senders, scams and robots no rule covers yet.
|
|
6
|
+
*/
|
|
7
|
+
export const WEIGHTS = {
|
|
8
|
+
spam_folder: 4,
|
|
9
|
+
dmarc_fail: 3,
|
|
10
|
+
brand_spoof: 3,
|
|
11
|
+
young_domain: 3,
|
|
12
|
+
reply_to_elsewhere: 2,
|
|
13
|
+
disposable_domain: 2,
|
|
14
|
+
bulk_never_replied: 1,
|
|
15
|
+
replied: -5,
|
|
16
|
+
};
|
|
17
|
+
export const SCORE_RULE = "score adds: in Gmail's Spam +4, Gmail's DMARC check failed +3, a brand in the display name sent from another " +
|
|
18
|
+
"domain +3, the domain under 180 days old when the mail came +3 (only with looked-up ages), Reply-To on another " +
|
|
19
|
+
"domain +2, a throwaway-mail domain +2, bulk mail never replied to +1, replied to by the owner -5";
|
|
20
|
+
/** A domain registered too recently to trust: under this many days old when the mail arrived. */
|
|
21
|
+
export const YOUNG_DAYS = 180;
|
|
22
|
+
/** The part of a host a person registers: `mail.news.example.co.uk` is `example.co.uk`. */
|
|
23
|
+
export const registrableOf = (address) => {
|
|
24
|
+
const host = address.slice(address.lastIndexOf("@") + 1).toLowerCase();
|
|
25
|
+
return getDomain(host) ?? host;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* The big mailbox providers. Their domains are years old and say nothing about the sender, so they are never
|
|
29
|
+
* looked up; a brand display name sent from one of them is the classic scam.
|
|
30
|
+
*/
|
|
31
|
+
export const FREE_MAIL = new Set([
|
|
32
|
+
"gmail.com",
|
|
33
|
+
"googlemail.com",
|
|
34
|
+
"yahoo.com",
|
|
35
|
+
"outlook.com",
|
|
36
|
+
"hotmail.com",
|
|
37
|
+
"live.com",
|
|
38
|
+
"msn.com",
|
|
39
|
+
"icloud.com",
|
|
40
|
+
"me.com",
|
|
41
|
+
"aol.com",
|
|
42
|
+
"proton.me",
|
|
43
|
+
"protonmail.com",
|
|
44
|
+
"gmx.com",
|
|
45
|
+
"gmx.de",
|
|
46
|
+
"mail.com",
|
|
47
|
+
"yandex.ru",
|
|
48
|
+
"ya.ru",
|
|
49
|
+
"mail.ru",
|
|
50
|
+
"bk.ru",
|
|
51
|
+
"inbox.ru",
|
|
52
|
+
"list.ru",
|
|
53
|
+
"rambler.ru",
|
|
54
|
+
"zoho.com",
|
|
55
|
+
]);
|
|
56
|
+
/** A brand and the first labels of the domains it really sends from. */
|
|
57
|
+
const BRANDS = {
|
|
58
|
+
paypal: ["paypal"],
|
|
59
|
+
apple: ["apple", "icloud"],
|
|
60
|
+
microsoft: ["microsoft", "outlook", "office", "office365", "live", "hotmail", "azure"],
|
|
61
|
+
google: ["google", "gmail", "youtube", "googlemail"],
|
|
62
|
+
amazon: ["amazon", "amazonaws", "aws"],
|
|
63
|
+
netflix: ["netflix"],
|
|
64
|
+
facebook: ["facebook", "facebookmail", "meta", "fb"],
|
|
65
|
+
instagram: ["instagram", "facebookmail"],
|
|
66
|
+
whatsapp: ["whatsapp"],
|
|
67
|
+
linkedin: ["linkedin"],
|
|
68
|
+
dhl: ["dhl"],
|
|
69
|
+
fedex: ["fedex"],
|
|
70
|
+
docusign: ["docusign"],
|
|
71
|
+
dropbox: ["dropbox"],
|
|
72
|
+
binance: ["binance"],
|
|
73
|
+
coinbase: ["coinbase"],
|
|
74
|
+
revolut: ["revolut"],
|
|
75
|
+
};
|
|
76
|
+
/** The brand a display name claims while the address belongs to someone else, if any. */
|
|
77
|
+
export const spoofedBrand = (name, address) => {
|
|
78
|
+
if (name === undefined || address === undefined)
|
|
79
|
+
return undefined;
|
|
80
|
+
const label = registrableOf(address).split(".")[0] ?? "";
|
|
81
|
+
return Object.entries(BRANDS).find(([brand, owned]) => new RegExp(`\\b${brand}\\b`, "i").test(name) && !owned.includes(label))?.[0];
|
|
82
|
+
};
|
|
83
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
84
|
+
/** Under YOUNG_DAYS old at `at`; false when the age is not known. */
|
|
85
|
+
export const youngAt = (age, at) => age?.created !== undefined && Date.parse(at) - Date.parse(age.created) < YOUNG_DAYS * DAY_MS;
|
|
86
|
+
const most = (items, test) => items.filter((item) => test(item)).length * 2 >= items.length;
|
|
87
|
+
/**
|
|
88
|
+
* A sender group's score from the facts its emails carry. A sign counts when it holds for at least half the group's
|
|
89
|
+
* emails, so one odd email does not mark a sender; a spoofed brand counts on any one.
|
|
90
|
+
*/
|
|
91
|
+
export const scoreGroup = (items, context) => {
|
|
92
|
+
const signals = [];
|
|
93
|
+
const judged = items.filter((item) => item.headers?.auth?.dmarc !== undefined);
|
|
94
|
+
if (most(items, (item) => item.labels?.includes("Spam")))
|
|
95
|
+
signals.push("spam_folder");
|
|
96
|
+
if (judged.length && most(judged, (item) => item.headers?.auth?.dmarc === "fail"))
|
|
97
|
+
signals.push("dmarc_fail");
|
|
98
|
+
if (items.some((item) => spoofedBrand(item.headers?.fromName, item.headers?.from) !== undefined))
|
|
99
|
+
signals.push("brand_spoof");
|
|
100
|
+
const sender = items.find((item) => item.headers?.from !== undefined)?.headers?.from;
|
|
101
|
+
const domain = sender === undefined ? undefined : registrableOf(sender);
|
|
102
|
+
const first = items.reduce((a, b) => (a.receivedAt < b.receivedAt ? a : b));
|
|
103
|
+
if (domain !== undefined && youngAt(context.ages.get(domain), first.receivedAt))
|
|
104
|
+
signals.push("young_domain");
|
|
105
|
+
if (most(items, (item) => {
|
|
106
|
+
const { from, replyTo } = item.headers ?? {};
|
|
107
|
+
return from !== undefined && replyTo !== undefined && registrableOf(replyTo) !== registrableOf(from);
|
|
108
|
+
}))
|
|
109
|
+
signals.push("reply_to_elsewhere");
|
|
110
|
+
if (domain !== undefined && isDisposableEmailDomain(domain))
|
|
111
|
+
signals.push("disposable_domain");
|
|
112
|
+
if (context.bulk >= 0.8 && !context.replied)
|
|
113
|
+
signals.push("bulk_never_replied");
|
|
114
|
+
if (context.replied)
|
|
115
|
+
signals.push("replied");
|
|
116
|
+
return { score: signals.reduce((sum, signal) => sum + WEIGHTS[signal], 0), signals };
|
|
117
|
+
};
|
|
118
|
+
//# sourceMappingURL=score.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"score.js","sourceRoot":"","sources":["../../src/mail/score.ts"],"names":[],"mappings":"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"}
|
package/dist/mail/source.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { type Listed } from "./gmail.js";
|
|
1
|
+
import { type Listed, type Searched } from "./gmail.js";
|
|
2
2
|
import type { Himalaya } from "./himalaya.js";
|
|
3
|
-
|
|
3
|
+
import type { FileStamp } from "./resume.js";
|
|
4
|
+
export type { Listed, Searched };
|
|
4
5
|
/** Everything the import asks of a mail client, so himalaya can be replaced without touching the import. */
|
|
5
6
|
export interface MailSource {
|
|
6
7
|
/**
|
|
@@ -9,7 +10,15 @@ export interface MailSource {
|
|
|
9
10
|
*/
|
|
10
11
|
list(since: Date, folder: string, options?: {
|
|
11
12
|
headers?: boolean;
|
|
13
|
+
searched?: Searched;
|
|
12
14
|
}): Promise<Listed[]>;
|
|
15
|
+
/**
|
|
16
|
+
* The folder's UIDs in the window and its UIDVALIDITY, without reading a message; `list` given them reads only
|
|
17
|
+
* those. Absent for a file, which has no UIDs.
|
|
18
|
+
*/
|
|
19
|
+
search?(since: Date, folder: string): Promise<Searched>;
|
|
20
|
+
/** A file's size and modification time, so an unchanged file read to the end is not read again. */
|
|
21
|
+
stamp?(): Promise<FileStamp>;
|
|
13
22
|
/** Each item's raw RFC 5322 bytes, in order; one that could not be read is an Error, not a failed call. */
|
|
14
23
|
fetchRaw(items: Listed[]): Promise<(Uint8Array | Error)[]>;
|
|
15
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/mail/source.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAA6B,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/mail/source.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAA6B,KAAK,QAAQ,EAAc,MAAM,YAAY,CAAA;AAC9F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE5C,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;AAEhC,4GAA4G;AAC5G,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAC1G;;;OAGG;IACH,MAAM,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IACvD,mGAAmG;IACnG,KAAK,CAAC,IAAI,OAAO,CAAC,SAAS,CAAC,CAAA;IAC5B,2GAA2G;IAC3G,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,UAAU,GAAG,KAAK,CAAC,EAAE,CAAC,CAAA;CAC3D;AAiCD,eAAO,MAAM,cAAc,QACpB,QAAQ,WACJ;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;CAAE,KAC1D,UAmEF,CAAA"}
|
package/dist/mail/source.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CliError } from "@wirecat/cli-base";
|
|
2
|
-
import { listAllMail, listImapMail } from "./gmail.js";
|
|
2
|
+
import { listAllMail, listImapMail, searchMail } from "./gmail.js";
|
|
3
3
|
const BATCH_COUNT = 50;
|
|
4
4
|
const BATCH_BYTES = 20 * 1024 * 1024;
|
|
5
5
|
const MIN_BUFFER = 64 * 1024 * 1024;
|
|
@@ -65,8 +65,12 @@ export const himalayaSource = (run, account) => {
|
|
|
65
65
|
};
|
|
66
66
|
return {
|
|
67
67
|
list: async (since, folder, options) => account.mode === "imap"
|
|
68
|
-
? listImapMail(run, account.name, since, folder)
|
|
69
|
-
: (await listAllMail(run, account.name, since, folder, options?.headers)).map((item) => ({
|
|
68
|
+
? listImapMail(run, account.name, since, folder, options?.searched)
|
|
69
|
+
: (await listAllMail(run, account.name, since, folder, options?.headers, options?.searched)).map((item) => ({
|
|
70
|
+
...item,
|
|
71
|
+
folder,
|
|
72
|
+
})),
|
|
73
|
+
search: (since, folder) => searchMail(run, account.name, since, folder),
|
|
70
74
|
fetchRaw: async (items) => {
|
|
71
75
|
const read = new Map();
|
|
72
76
|
const settle = async (batch) => {
|
package/dist/mail/source.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/mail/source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAe,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/mail/source.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type Progress } from "@wirecat/cli-core/background";
|
|
2
|
+
import type { MessageStore } from "@wirecat/cli-core/store";
|
|
3
|
+
import type { MailAccount } from "./import.js";
|
|
4
|
+
import { type MboxPoint } from "./resume.js";
|
|
5
|
+
export interface MailStatus {
|
|
6
|
+
account: string;
|
|
7
|
+
/** Emails stored with their text. */
|
|
8
|
+
stored: number;
|
|
9
|
+
/** Emails a rule recorded without their text. */
|
|
10
|
+
envelopes: number;
|
|
11
|
+
/** Mail whose outcome is final, of the mail in the widest window searched. */
|
|
12
|
+
progress: Progress;
|
|
13
|
+
folders: {
|
|
14
|
+
folder: string;
|
|
15
|
+
done: number;
|
|
16
|
+
total: number;
|
|
17
|
+
fullAt: string;
|
|
18
|
+
updatedAt: string;
|
|
19
|
+
}[];
|
|
20
|
+
/** An mbox account: the file read last, and whether it was read to the end. */
|
|
21
|
+
file?: MboxPoint;
|
|
22
|
+
}
|
|
23
|
+
/** Read from the store only; the mailbox is not asked, so this answers while a sync runs. */
|
|
24
|
+
export declare const mailStatus: (store: MessageStore, account: MailAccount, now?: Date) => Promise<MailStatus>;
|
|
25
|
+
export declare const statusText: (status: MailStatus) => string;
|
|
26
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/mail/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAA4B,MAAM,8BAA8B,CAAA;AACtF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAe,KAAK,SAAS,EAA2C,MAAM,aAAa,CAAA;AAGlG,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAA;IACjB,8EAA8E;IAC9E,QAAQ,EAAE,QAAQ,CAAA;IAClB,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC7F,+EAA+E;IAC/E,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED,6FAA6F;AAC7F,eAAO,MAAM,UAAU,UAAiB,YAAY,WAAW,WAAW,iBAAqB,OAAO,CAAC,UAAU,CA4ChH,CAAA;AAED,eAAO,MAAM,UAAU,WAAY,UAAU,KAAG,MAWlC,CAAA"}
|