proton-mail-bridge-client 1.11.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/LICENSE +21 -0
- package/README.md +445 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1627 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3173 -0
- package/dist/index.js.map +1 -0
- package/dist/scripts/bridge-smoke.d.ts +2 -0
- package/dist/scripts/bridge-smoke.d.ts.map +1 -0
- package/dist/scripts/bridge-smoke.js +415 -0
- package/dist/scripts/bridge-smoke.js.map +1 -0
- package/dist/scripts/check-claude-desktop.d.ts +17 -0
- package/dist/scripts/check-claude-desktop.d.ts.map +1 -0
- package/dist/scripts/check-claude-desktop.js +138 -0
- package/dist/scripts/check-claude-desktop.js.map +1 -0
- package/dist/scripts/install-claude-desktop.d.ts +39 -0
- package/dist/scripts/install-claude-desktop.d.ts.map +1 -0
- package/dist/scripts/install-claude-desktop.js +257 -0
- package/dist/scripts/install-claude-desktop.js.map +1 -0
- package/dist/scripts/setup-claude-desktop.d.ts +15 -0
- package/dist/scripts/setup-claude-desktop.d.ts.map +1 -0
- package/dist/scripts/setup-claude-desktop.js +187 -0
- package/dist/scripts/setup-claude-desktop.js.map +1 -0
- package/dist/services/analytics-service.d.ts +45 -0
- package/dist/services/analytics-service.d.ts.map +1 -0
- package/dist/services/analytics-service.js +189 -0
- package/dist/services/analytics-service.js.map +1 -0
- package/dist/services/audit-service.d.ts +13 -0
- package/dist/services/audit-service.d.ts.map +1 -0
- package/dist/services/audit-service.js +67 -0
- package/dist/services/audit-service.js.map +1 -0
- package/dist/services/background-sync-service.d.ts +28 -0
- package/dist/services/background-sync-service.d.ts.map +1 -0
- package/dist/services/background-sync-service.js +216 -0
- package/dist/services/background-sync-service.js.map +1 -0
- package/dist/services/draft-store-service.d.ts +59 -0
- package/dist/services/draft-store-service.d.ts.map +1 -0
- package/dist/services/draft-store-service.js +251 -0
- package/dist/services/draft-store-service.js.map +1 -0
- package/dist/services/local-index-service.d.ts +90 -0
- package/dist/services/local-index-service.d.ts.map +1 -0
- package/dist/services/local-index-service.js +1462 -0
- package/dist/services/local-index-service.js.map +1 -0
- package/dist/services/simple-imap-service.d.ts +209 -0
- package/dist/services/simple-imap-service.d.ts.map +1 -0
- package/dist/services/simple-imap-service.js +1100 -0
- package/dist/services/simple-imap-service.js.map +1 -0
- package/dist/services/smtp-service.d.ts +15 -0
- package/dist/services/smtp-service.d.ts.map +1 -0
- package/dist/services/smtp-service.js +100 -0
- package/dist/services/smtp-service.js.map +1 -0
- package/dist/types/index.d.ts +355 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/helpers.d.ts +45 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +393 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/utils/logger.d.ts +22 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +91 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/runtime-policy.d.ts +12 -0
- package/dist/utils/runtime-policy.d.ts.map +1 -0
- package/dist/utils/runtime-policy.js +62 -0
- package/dist/utils/runtime-policy.js.map +1 -0
- package/glama.json +6 -0
- package/package.json +91 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { dedupeEmails, extractDomain, lowerCaseAddress } from "../utils/helpers.js";
|
|
2
|
+
function extractAddresses(email) {
|
|
3
|
+
return [...email.from, ...email.to, ...email.cc, ...email.bcc, ...email.replyTo];
|
|
4
|
+
}
|
|
5
|
+
function toDayKey(value) {
|
|
6
|
+
if (!value) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
const date = new Date(value);
|
|
10
|
+
if (Number.isNaN(date.getTime())) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
return date.toISOString().slice(0, 10);
|
|
14
|
+
}
|
|
15
|
+
export class AnalyticsService {
|
|
16
|
+
clearCache() {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
getEmailStats(emails, folders, ownerEmail) {
|
|
20
|
+
const deduped = dedupeEmails(emails);
|
|
21
|
+
const totalMessages = folders.reduce((sum, folder) => sum + (folder.messages ?? 0), 0);
|
|
22
|
+
const unreadMessages = folders.reduce((sum, folder) => sum + (folder.unseen ?? 0), 0);
|
|
23
|
+
const contacts = this.getContacts(deduped, Number.MAX_SAFE_INTEGER, ownerEmail);
|
|
24
|
+
return {
|
|
25
|
+
generatedAt: new Date().toISOString(),
|
|
26
|
+
mailbox: {
|
|
27
|
+
folderCount: folders.length,
|
|
28
|
+
totalMessages,
|
|
29
|
+
unreadMessages,
|
|
30
|
+
},
|
|
31
|
+
sample: {
|
|
32
|
+
size: deduped.length,
|
|
33
|
+
starredMessages: deduped.filter((email) => email.isStarred).length,
|
|
34
|
+
messagesWithAttachments: deduped.filter((email) => email.hasAttachments).length,
|
|
35
|
+
uniqueContacts: contacts.length,
|
|
36
|
+
},
|
|
37
|
+
folders: folders.map((folder) => ({
|
|
38
|
+
path: folder.path,
|
|
39
|
+
messages: folder.messages ?? 0,
|
|
40
|
+
unseen: folder.unseen ?? 0,
|
|
41
|
+
specialUse: folder.specialUse,
|
|
42
|
+
})),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
getEmailAnalytics(emails, ownerEmail) {
|
|
46
|
+
const deduped = dedupeEmails(emails);
|
|
47
|
+
const hourCounts = new Map();
|
|
48
|
+
const senderCounts = new Map();
|
|
49
|
+
const domainCounts = new Map();
|
|
50
|
+
for (const email of deduped) {
|
|
51
|
+
const date = new Date(email.internalDate || email.date || 0);
|
|
52
|
+
if (!Number.isNaN(date.getTime())) {
|
|
53
|
+
hourCounts.set(date.getUTCHours(), (hourCounts.get(date.getUTCHours()) ?? 0) + 1);
|
|
54
|
+
}
|
|
55
|
+
for (const sender of email.from) {
|
|
56
|
+
const address = lowerCaseAddress(sender.address);
|
|
57
|
+
if (!address || address === lowerCaseAddress(ownerEmail)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
senderCounts.set(address, (senderCounts.get(address) ?? 0) + 1);
|
|
61
|
+
const domain = extractDomain(address);
|
|
62
|
+
if (domain) {
|
|
63
|
+
domainCounts.set(domain, (domainCounts.get(domain) ?? 0) + 1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const busiestHours = [...hourCounts.entries()]
|
|
68
|
+
.sort((left, right) => right[1] - left[1])
|
|
69
|
+
.slice(0, 5)
|
|
70
|
+
.map(([hour, count]) => ({
|
|
71
|
+
hour: `${String(hour).padStart(2, "0")}:00Z`,
|
|
72
|
+
count,
|
|
73
|
+
}));
|
|
74
|
+
const topSenders = [...senderCounts.entries()]
|
|
75
|
+
.sort((left, right) => right[1] - left[1])
|
|
76
|
+
.slice(0, 10)
|
|
77
|
+
.map(([address, count]) => ({ address, count }));
|
|
78
|
+
const topDomains = [...domainCounts.entries()]
|
|
79
|
+
.sort((left, right) => right[1] - left[1])
|
|
80
|
+
.slice(0, 10)
|
|
81
|
+
.map(([domain, count]) => ({ domain, count }));
|
|
82
|
+
const trends = this.getVolumeTrends(deduped, 30);
|
|
83
|
+
const busiestDay = [...trends].sort((left, right) => right.count - left.count)[0];
|
|
84
|
+
return {
|
|
85
|
+
generatedAt: new Date().toISOString(),
|
|
86
|
+
sampleSize: deduped.length,
|
|
87
|
+
busiestHours,
|
|
88
|
+
topSenders,
|
|
89
|
+
topDomains,
|
|
90
|
+
busiestDay,
|
|
91
|
+
insights: [
|
|
92
|
+
busiestHours[0]
|
|
93
|
+
? `Peak sampled activity occurs around ${busiestHours[0].hour}.`
|
|
94
|
+
: "No recent activity was available for hourly analysis.",
|
|
95
|
+
topSenders[0]
|
|
96
|
+
? `Top sender in the sampled window: ${topSenders[0].address}.`
|
|
97
|
+
: "No sender data was available in the sampled window.",
|
|
98
|
+
busiestDay
|
|
99
|
+
? `Busiest sampled day was ${busiestDay.date} with ${busiestDay.count} messages.`
|
|
100
|
+
: "No day-level trend data was available.",
|
|
101
|
+
],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
getContacts(emails, limit = 100, ownerEmail) {
|
|
105
|
+
const owner = lowerCaseAddress(ownerEmail);
|
|
106
|
+
const contacts = new Map();
|
|
107
|
+
for (const email of dedupeEmails(emails)) {
|
|
108
|
+
const fromAddresses = email.from
|
|
109
|
+
.map((value) => ({ ...value, address: lowerCaseAddress(value.address) }))
|
|
110
|
+
.filter((value) => Boolean(value.address));
|
|
111
|
+
const toAddresses = [...email.to, ...email.cc, ...email.bcc]
|
|
112
|
+
.map((value) => ({ ...value, address: lowerCaseAddress(value.address) }))
|
|
113
|
+
.filter((value) => Boolean(value.address));
|
|
114
|
+
const emailTimestamp = email.internalDate || email.date;
|
|
115
|
+
const emailFromOwner = fromAddresses.some((value) => value.address === owner);
|
|
116
|
+
for (const address of extractAddresses(email)) {
|
|
117
|
+
const normalizedAddress = lowerCaseAddress(address.address);
|
|
118
|
+
if (!normalizedAddress || normalizedAddress === owner) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const contact = contacts.get(normalizedAddress) ?? {
|
|
122
|
+
address: normalizedAddress,
|
|
123
|
+
name: address.name,
|
|
124
|
+
incoming: 0,
|
|
125
|
+
outgoing: 0,
|
|
126
|
+
totalMessages: 0,
|
|
127
|
+
lastContactAt: undefined,
|
|
128
|
+
};
|
|
129
|
+
contact.totalMessages += 1;
|
|
130
|
+
if (emailFromOwner) {
|
|
131
|
+
if (toAddresses.some((value) => value.address === normalizedAddress)) {
|
|
132
|
+
contact.outgoing += 1;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else if (fromAddresses.some((value) => value.address === normalizedAddress)) {
|
|
136
|
+
contact.incoming += 1;
|
|
137
|
+
}
|
|
138
|
+
if (emailTimestamp &&
|
|
139
|
+
(!contact.lastContactAt ||
|
|
140
|
+
new Date(emailTimestamp).getTime() > new Date(contact.lastContactAt).getTime())) {
|
|
141
|
+
contact.lastContactAt = new Date(emailTimestamp).toISOString();
|
|
142
|
+
}
|
|
143
|
+
contacts.set(normalizedAddress, contact);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return [...contacts.values()]
|
|
147
|
+
.sort((left, right) => {
|
|
148
|
+
if (right.totalMessages !== left.totalMessages) {
|
|
149
|
+
return right.totalMessages - left.totalMessages;
|
|
150
|
+
}
|
|
151
|
+
return (right.lastContactAt ?? "").localeCompare(left.lastContactAt ?? "");
|
|
152
|
+
})
|
|
153
|
+
.slice(0, limit);
|
|
154
|
+
}
|
|
155
|
+
getVolumeTrends(emails, days = 30) {
|
|
156
|
+
const trendMap = new Map();
|
|
157
|
+
const now = new Date();
|
|
158
|
+
for (let index = days - 1; index >= 0; index -= 1) {
|
|
159
|
+
const current = new Date(now.getTime() - index * 24 * 60 * 60 * 1000);
|
|
160
|
+
const key = current.toISOString().slice(0, 10);
|
|
161
|
+
trendMap.set(key, {
|
|
162
|
+
date: key,
|
|
163
|
+
count: 0,
|
|
164
|
+
unreadCount: 0,
|
|
165
|
+
starredCount: 0,
|
|
166
|
+
attachmentCount: 0,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
for (const email of dedupeEmails(emails)) {
|
|
170
|
+
const key = toDayKey(email.internalDate || email.date);
|
|
171
|
+
if (!key || !trendMap.has(key)) {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
const point = trendMap.get(key);
|
|
175
|
+
point.count += 1;
|
|
176
|
+
if (!email.isRead) {
|
|
177
|
+
point.unreadCount += 1;
|
|
178
|
+
}
|
|
179
|
+
if (email.isStarred) {
|
|
180
|
+
point.starredCount += 1;
|
|
181
|
+
}
|
|
182
|
+
if (email.hasAttachments) {
|
|
183
|
+
point.attachmentCount += 1;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return [...trendMap.values()];
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=analytics-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics-service.js","sourceRoot":"","sources":["../../src/services/analytics-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AuditEntry, ProtonMailConfig } from "../types/index.js";
|
|
2
|
+
export declare class AuditService {
|
|
3
|
+
private readonly config;
|
|
4
|
+
private readonly auditPath;
|
|
5
|
+
private readonly archivePath;
|
|
6
|
+
constructor(config: ProtonMailConfig);
|
|
7
|
+
getPath(): string;
|
|
8
|
+
record(entry: AuditEntry): Promise<void>;
|
|
9
|
+
list(limit?: number): Promise<AuditEntry[]>;
|
|
10
|
+
private rotateIfNeeded;
|
|
11
|
+
private readEntries;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=audit-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-service.d.ts","sourceRoot":"","sources":["../../src/services/audit-service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAItE,qBAAa,YAAY;IAIX,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAER,MAAM,EAAE,gBAAgB;IAKrD,OAAO,IAAI,MAAM;IAIX,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxC,IAAI,CAAC,KAAK,SAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;YAKhC,cAAc;YAgBd,WAAW;CAyB1B"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { appendFile, mkdir, readFile, rename, rm, stat } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
const MAX_AUDIT_BYTES = 5 * 1024 * 1024;
|
|
4
|
+
export class AuditService {
|
|
5
|
+
config;
|
|
6
|
+
auditPath;
|
|
7
|
+
archivePath;
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.config = config;
|
|
10
|
+
this.auditPath = join(this.config.dataDir, "audit.log");
|
|
11
|
+
this.archivePath = `${this.auditPath}.1`;
|
|
12
|
+
}
|
|
13
|
+
getPath() {
|
|
14
|
+
return this.auditPath;
|
|
15
|
+
}
|
|
16
|
+
async record(entry) {
|
|
17
|
+
await mkdir(dirname(this.auditPath), { recursive: true });
|
|
18
|
+
await this.rotateIfNeeded();
|
|
19
|
+
await appendFile(this.auditPath, `${JSON.stringify(entry)}\n`, "utf8");
|
|
20
|
+
}
|
|
21
|
+
async list(limit = 100) {
|
|
22
|
+
const entries = [...(await this.readEntries(this.archivePath)), ...(await this.readEntries(this.auditPath))];
|
|
23
|
+
return entries.slice(-limit);
|
|
24
|
+
}
|
|
25
|
+
async rotateIfNeeded() {
|
|
26
|
+
try {
|
|
27
|
+
const info = await stat(this.auditPath);
|
|
28
|
+
if (info.size < MAX_AUDIT_BYTES) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
await rm(this.archivePath, { force: true });
|
|
32
|
+
await rename(this.auditPath, this.archivePath);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async readEntries(path) {
|
|
42
|
+
try {
|
|
43
|
+
const raw = await readFile(path, "utf8");
|
|
44
|
+
return raw
|
|
45
|
+
.split(/\r?\n/)
|
|
46
|
+
.filter(Boolean)
|
|
47
|
+
.flatMap((line) => {
|
|
48
|
+
try {
|
|
49
|
+
return [JSON.parse(line)];
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (error &&
|
|
58
|
+
typeof error === "object" &&
|
|
59
|
+
"code" in error &&
|
|
60
|
+
error.code === "ENOENT") {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=audit-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-service.js","sourceRoot":"","sources":["../../src/services/audit-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { BackgroundSyncStatus, ProtonMailConfig } from "../types/index.js";
|
|
2
|
+
import { type Logger } from "../utils/logger.js";
|
|
3
|
+
import { LocalIndexService } from "./local-index-service.js";
|
|
4
|
+
import { SimpleIMAPService } from "./simple-imap-service.js";
|
|
5
|
+
export declare class BackgroundSyncService {
|
|
6
|
+
private readonly config;
|
|
7
|
+
private readonly imapService;
|
|
8
|
+
private readonly localIndexService;
|
|
9
|
+
private readonly log;
|
|
10
|
+
private readonly status;
|
|
11
|
+
private timer?;
|
|
12
|
+
private activeRun?;
|
|
13
|
+
private idleLoop?;
|
|
14
|
+
private started;
|
|
15
|
+
private authFailureCount;
|
|
16
|
+
private transientFailureCount;
|
|
17
|
+
constructor(config: ProtonMailConfig, imapService: SimpleIMAPService, localIndexService: LocalIndexService, log?: Logger);
|
|
18
|
+
start(): void;
|
|
19
|
+
stop(): void;
|
|
20
|
+
getStatus(): BackgroundSyncStatus;
|
|
21
|
+
runNow(reason?: string): Promise<BackgroundSyncStatus>;
|
|
22
|
+
private scheduleNextRun;
|
|
23
|
+
private scheduleFailureRetry;
|
|
24
|
+
private scheduleTimer;
|
|
25
|
+
private startIdleLoop;
|
|
26
|
+
private waitForRetry;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=background-sync-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-sync-service.d.ts","sourceRoot":"","sources":["../../src/services/background-sync-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAA+B,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAO1F,qBAAa,qBAAqB;IAU9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,GAAG;IAZtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,KAAK,CAAC,CAAiB;IAC/B,OAAO,CAAC,SAAS,CAAC,CAAgB;IAClC,OAAO,CAAC,QAAQ,CAAC,CAAgB;IACjC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,qBAAqB,CAAK;gBAGf,MAAM,EAAE,gBAAgB,EACxB,WAAW,EAAE,iBAAiB,EAC9B,iBAAiB,EAAE,iBAAiB,EACpC,GAAG,GAAE,MAAe;IAgBvC,KAAK,IAAI,IAAI;IAeb,IAAI,IAAI,IAAI;IAWZ,SAAS,IAAI,oBAAoB;IAI3B,MAAM,CAAC,MAAM,SAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;IA2E9D,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,oBAAoB;IAe5B,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,aAAa;YA0CP,YAAY;CAM3B"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { logger } from "../utils/logger.js";
|
|
2
|
+
import { isLikelyAuthenticationError } from "./simple-imap-service.js";
|
|
3
|
+
const AUTH_BACKOFF_MIN_MS = 5 * 60_000;
|
|
4
|
+
const AUTH_BACKOFF_MAX_MS = 30 * 60_000;
|
|
5
|
+
const TRANSIENT_BACKOFF_MIN_MS = 15_000;
|
|
6
|
+
const TRANSIENT_BACKOFF_MAX_MS = 2 * 60_000;
|
|
7
|
+
export class BackgroundSyncService {
|
|
8
|
+
config;
|
|
9
|
+
imapService;
|
|
10
|
+
localIndexService;
|
|
11
|
+
log;
|
|
12
|
+
status;
|
|
13
|
+
timer;
|
|
14
|
+
activeRun;
|
|
15
|
+
idleLoop;
|
|
16
|
+
started = false;
|
|
17
|
+
authFailureCount = 0;
|
|
18
|
+
transientFailureCount = 0;
|
|
19
|
+
constructor(config, imapService, localIndexService, log = logger) {
|
|
20
|
+
this.config = config;
|
|
21
|
+
this.imapService = imapService;
|
|
22
|
+
this.localIndexService = localIndexService;
|
|
23
|
+
this.log = log;
|
|
24
|
+
this.status = {
|
|
25
|
+
enabled: this.config.autoSync,
|
|
26
|
+
running: false,
|
|
27
|
+
intervalMinutes: this.config.syncInterval,
|
|
28
|
+
folder: this.config.runtime.autoSyncFolder,
|
|
29
|
+
full: this.config.runtime.autoSyncFull,
|
|
30
|
+
limitPerFolder: this.config.runtime.autoSyncLimitPerFolder,
|
|
31
|
+
startupSync: this.config.runtime.startupSync,
|
|
32
|
+
idleEnabled: this.config.runtime.idleWatchEnabled,
|
|
33
|
+
idleWatching: false,
|
|
34
|
+
idleMaxSeconds: this.config.runtime.idleMaxSeconds,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
start() {
|
|
38
|
+
if (this.started || !this.status.enabled) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
this.started = true;
|
|
42
|
+
if (this.status.startupSync) {
|
|
43
|
+
void this.runNow("startup");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
this.startIdleLoop();
|
|
47
|
+
this.scheduleNextRun();
|
|
48
|
+
}
|
|
49
|
+
stop() {
|
|
50
|
+
this.started = false;
|
|
51
|
+
if (this.timer) {
|
|
52
|
+
clearTimeout(this.timer);
|
|
53
|
+
this.timer = undefined;
|
|
54
|
+
}
|
|
55
|
+
this.status.nextRunAt = undefined;
|
|
56
|
+
this.status.backoffUntil = undefined;
|
|
57
|
+
this.status.idleWatching = false;
|
|
58
|
+
}
|
|
59
|
+
getStatus() {
|
|
60
|
+
return { ...this.status };
|
|
61
|
+
}
|
|
62
|
+
async runNow(reason = "manual") {
|
|
63
|
+
if (!this.status.enabled) {
|
|
64
|
+
return this.getStatus();
|
|
65
|
+
}
|
|
66
|
+
if (this.activeRun) {
|
|
67
|
+
await this.activeRun;
|
|
68
|
+
return this.getStatus();
|
|
69
|
+
}
|
|
70
|
+
if (this.timer) {
|
|
71
|
+
clearTimeout(this.timer);
|
|
72
|
+
this.timer = undefined;
|
|
73
|
+
}
|
|
74
|
+
this.status.nextRunAt = undefined;
|
|
75
|
+
this.activeRun = (async () => {
|
|
76
|
+
const startedAt = new Date().toISOString();
|
|
77
|
+
let failureKind;
|
|
78
|
+
this.status.running = true;
|
|
79
|
+
this.status.lastRunAt = startedAt;
|
|
80
|
+
this.log.info("Starting background mailbox sync", "BackgroundSyncService", {
|
|
81
|
+
reason,
|
|
82
|
+
folder: this.status.folder,
|
|
83
|
+
full: this.status.full,
|
|
84
|
+
limitPerFolder: this.status.limitPerFolder,
|
|
85
|
+
});
|
|
86
|
+
try {
|
|
87
|
+
const snapshot = await this.imapService.collectEmailsForIndex({
|
|
88
|
+
folder: this.status.folder,
|
|
89
|
+
full: this.status.full,
|
|
90
|
+
limitPerFolder: this.status.limitPerFolder,
|
|
91
|
+
checkpoints: await this.localIndexService.getSyncCheckpointMap(),
|
|
92
|
+
});
|
|
93
|
+
await this.localIndexService.recordSnapshot({
|
|
94
|
+
folders: snapshot.folders,
|
|
95
|
+
emails: snapshot.emails,
|
|
96
|
+
syncedAt: snapshot.syncedAt,
|
|
97
|
+
folderStats: snapshot.folderStats,
|
|
98
|
+
});
|
|
99
|
+
this.status.lastSuccessAt = snapshot.syncedAt;
|
|
100
|
+
this.status.lastError = undefined;
|
|
101
|
+
this.status.lastFailureKind = undefined;
|
|
102
|
+
this.authFailureCount = 0;
|
|
103
|
+
this.transientFailureCount = 0;
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
failureKind = isLikelyAuthenticationError(error) ? "auth" : "transient";
|
|
107
|
+
this.status.lastError = error instanceof Error ? error.message : String(error);
|
|
108
|
+
this.status.lastFailureKind = failureKind;
|
|
109
|
+
this.log.warn("Background mailbox sync failed", "BackgroundSyncService", {
|
|
110
|
+
reason,
|
|
111
|
+
failureKind,
|
|
112
|
+
error,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
this.status.running = false;
|
|
117
|
+
this.activeRun = undefined;
|
|
118
|
+
if (this.started) {
|
|
119
|
+
if (!failureKind) {
|
|
120
|
+
this.startIdleLoop();
|
|
121
|
+
this.scheduleNextRun();
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
this.scheduleFailureRetry(failureKind);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
})();
|
|
129
|
+
await this.activeRun;
|
|
130
|
+
return this.getStatus();
|
|
131
|
+
}
|
|
132
|
+
scheduleNextRun() {
|
|
133
|
+
if (!this.started || !this.status.enabled) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (this.timer) {
|
|
137
|
+
clearTimeout(this.timer);
|
|
138
|
+
this.timer = undefined;
|
|
139
|
+
}
|
|
140
|
+
const delayMs = Math.max(1, this.status.intervalMinutes) * 60_000;
|
|
141
|
+
this.scheduleTimer(delayMs, "interval");
|
|
142
|
+
}
|
|
143
|
+
scheduleFailureRetry(kind) {
|
|
144
|
+
const count = kind === "auth" ? ++this.authFailureCount : ++this.transientFailureCount;
|
|
145
|
+
if (kind === "auth") {
|
|
146
|
+
this.transientFailureCount = 0;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
this.authFailureCount = 0;
|
|
150
|
+
}
|
|
151
|
+
const minDelay = kind === "auth" ? AUTH_BACKOFF_MIN_MS : TRANSIENT_BACKOFF_MIN_MS;
|
|
152
|
+
const maxDelay = kind === "auth" ? AUTH_BACKOFF_MAX_MS : TRANSIENT_BACKOFF_MAX_MS;
|
|
153
|
+
const delayMs = Math.min(maxDelay, minDelay * 2 ** Math.max(0, count - 1));
|
|
154
|
+
this.status.backoffUntil = new Date(Date.now() + delayMs).toISOString();
|
|
155
|
+
this.scheduleTimer(delayMs, `${kind}-retry`);
|
|
156
|
+
}
|
|
157
|
+
scheduleTimer(delayMs, reason) {
|
|
158
|
+
if (this.timer) {
|
|
159
|
+
clearTimeout(this.timer);
|
|
160
|
+
}
|
|
161
|
+
const nextRunAt = new Date(Date.now() + delayMs).toISOString();
|
|
162
|
+
this.status.nextRunAt = nextRunAt;
|
|
163
|
+
this.timer = setTimeout(() => {
|
|
164
|
+
void this.runNow(reason);
|
|
165
|
+
}, delayMs);
|
|
166
|
+
this.timer.unref?.();
|
|
167
|
+
}
|
|
168
|
+
startIdleLoop() {
|
|
169
|
+
if (this.idleLoop || !this.status.idleEnabled || !this.status.folder) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
this.idleLoop = (async () => {
|
|
173
|
+
while (this.started && this.status.enabled && this.status.idleEnabled && this.status.folder) {
|
|
174
|
+
this.status.idleWatching = true;
|
|
175
|
+
try {
|
|
176
|
+
const result = await this.imapService.waitForMailboxChanges({
|
|
177
|
+
folder: this.status.folder,
|
|
178
|
+
timeoutMs: this.status.idleMaxSeconds * 1000,
|
|
179
|
+
});
|
|
180
|
+
this.status.lastIdleAt = result.checkedAt;
|
|
181
|
+
this.status.lastIdleError = undefined;
|
|
182
|
+
if (result.changed) {
|
|
183
|
+
this.status.lastIdleChangeAt = result.checkedAt;
|
|
184
|
+
this.status.lastIdleEventCount = result.events.length;
|
|
185
|
+
await this.runNow("idle");
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
this.status.lastIdleError = error instanceof Error ? error.message : String(error);
|
|
190
|
+
const failureKind = isLikelyAuthenticationError(error) ? "auth" : "transient";
|
|
191
|
+
this.log.warn("Mailbox IDLE watch failed", "BackgroundSyncService", {
|
|
192
|
+
folder: this.status.folder,
|
|
193
|
+
failureKind,
|
|
194
|
+
error,
|
|
195
|
+
});
|
|
196
|
+
if (failureKind === "auth") {
|
|
197
|
+
this.status.lastFailureKind = "auth";
|
|
198
|
+
this.status.lastError = this.status.lastIdleError;
|
|
199
|
+
this.scheduleFailureRetry("auth");
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
await this.waitForRetry(TRANSIENT_BACKOFF_MIN_MS);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
this.status.idleWatching = false;
|
|
206
|
+
this.idleLoop = undefined;
|
|
207
|
+
})();
|
|
208
|
+
}
|
|
209
|
+
async waitForRetry(delayMs) {
|
|
210
|
+
await new Promise((resolve) => {
|
|
211
|
+
const timer = setTimeout(resolve, delayMs);
|
|
212
|
+
timer.unref?.();
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=background-sync-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-sync-service.js","sourceRoot":"","sources":["../../src/services/background-sync-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { DraftMode, DraftRecord, RemoteDraftRef, DraftSendResult, ProtonMailConfig } from "../types/index.js";
|
|
2
|
+
import { type Logger } from "../utils/logger.js";
|
|
3
|
+
export declare class DraftStoreService {
|
|
4
|
+
private readonly config;
|
|
5
|
+
private readonly log;
|
|
6
|
+
private readonly draftPath;
|
|
7
|
+
private loadedStore?;
|
|
8
|
+
constructor(config: ProtonMailConfig, log?: Logger);
|
|
9
|
+
listDrafts(includeSent?: boolean): Promise<DraftRecord[]>;
|
|
10
|
+
getDraft(id: string): Promise<DraftRecord>;
|
|
11
|
+
createDraft(input: {
|
|
12
|
+
mode?: DraftMode;
|
|
13
|
+
to?: string[];
|
|
14
|
+
cc?: string[];
|
|
15
|
+
bcc?: string[];
|
|
16
|
+
subject: string;
|
|
17
|
+
body: string;
|
|
18
|
+
isHtml?: boolean;
|
|
19
|
+
priority?: "high" | "normal" | "low";
|
|
20
|
+
replyTo?: string;
|
|
21
|
+
inReplyTo?: string;
|
|
22
|
+
references?: string[];
|
|
23
|
+
attachments?: DraftRecord["attachments"];
|
|
24
|
+
sourceEmailId?: string;
|
|
25
|
+
sourceMessageId?: string;
|
|
26
|
+
notes?: string;
|
|
27
|
+
}): Promise<DraftRecord>;
|
|
28
|
+
updateDraft(id: string, patch: {
|
|
29
|
+
to?: string[];
|
|
30
|
+
cc?: string[];
|
|
31
|
+
bcc?: string[];
|
|
32
|
+
subject?: string;
|
|
33
|
+
body?: string;
|
|
34
|
+
isHtml?: boolean;
|
|
35
|
+
priority?: "high" | "normal" | "low";
|
|
36
|
+
replyTo?: string;
|
|
37
|
+
inReplyTo?: string;
|
|
38
|
+
references?: string[];
|
|
39
|
+
attachments?: DraftRecord["attachments"];
|
|
40
|
+
notes?: string;
|
|
41
|
+
}): Promise<DraftRecord>;
|
|
42
|
+
markSent(id: string, result: DraftSendResult): Promise<DraftRecord>;
|
|
43
|
+
markRemoteSynced(id: string, remoteDraft: RemoteDraftRef): Promise<DraftRecord>;
|
|
44
|
+
markRemoteSyncError(id: string, message: string): Promise<DraftRecord>;
|
|
45
|
+
clearRemoteSync(id: string): Promise<DraftRecord>;
|
|
46
|
+
deleteDraft(id: string): Promise<{
|
|
47
|
+
id: string;
|
|
48
|
+
removed: boolean;
|
|
49
|
+
}>;
|
|
50
|
+
clear(): Promise<{
|
|
51
|
+
path: string;
|
|
52
|
+
removed: boolean;
|
|
53
|
+
}>;
|
|
54
|
+
private load;
|
|
55
|
+
private save;
|
|
56
|
+
private normalizeDraft;
|
|
57
|
+
private createDraftMessageId;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=draft-store-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draft-store-service.d.ts","sourceRoot":"","sources":["../../src/services/draft-store-service.ts"],"names":[],"mappings":"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"}
|