@bobfrankston/mailx 1.0.165 → 1.0.166
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 +2 -2
- package/packages/mailx-imap/index.js +23 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/mailx",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.166",
|
|
4
4
|
"description": "Local-first email client with IMAP sync and standalone native app",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bin/mailx.js",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@bobfrankston/iflow-node": "^0.1.1",
|
|
25
25
|
"@bobfrankston/miscinfo": "^1.0.7",
|
|
26
26
|
"@bobfrankston/oauthsupport": "^1.0.20",
|
|
27
|
-
"@bobfrankston/msger": "^0.1.
|
|
27
|
+
"@bobfrankston/msger": "^0.1.216",
|
|
28
28
|
"@capacitor/android": "^8.3.0",
|
|
29
29
|
"@capacitor/cli": "^8.3.0",
|
|
30
30
|
"@capacitor/core": "^8.3.0",
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Syncs messages to local store, emits events for new mail.
|
|
5
5
|
*/
|
|
6
6
|
import { createAutoImapConfig, CompatImapClient } from "@bobfrankston/iflow-direct";
|
|
7
|
+
import { authenticateOAuth } from "@bobfrankston/oauthsupport";
|
|
7
8
|
import { FileMessageStore } from "@bobfrankston/mailx-store";
|
|
8
9
|
import { loadSettings, getStorePath, getConfigDir, getHistoryDays } from "@bobfrankston/mailx-settings";
|
|
9
10
|
import { EventEmitter } from "node:events";
|
|
@@ -314,13 +315,26 @@ export class ImapManager extends EventEmitter {
|
|
|
314
315
|
if (this.configs.has(account.id))
|
|
315
316
|
return;
|
|
316
317
|
// createAutoImapConfig auto-detects Gmail from server/username and sets up OAuth
|
|
317
|
-
//
|
|
318
|
+
// For OAuth accounts, provide a tokenProvider using oauthsupport
|
|
319
|
+
let tokenProvider;
|
|
320
|
+
if (account.imap.auth === "oauth2" || (!account.imap.password && account.imap.host?.includes("gmail"))) {
|
|
321
|
+
const credPath = path.join(getConfigDir(), "google-credentials.json");
|
|
322
|
+
const tokenDir = path.join(getConfigDir(), "tokens", account.imap.user.replace(/[@.]/g, "_"));
|
|
323
|
+
tokenProvider = async () => {
|
|
324
|
+
const result = await authenticateOAuth(credPath, {
|
|
325
|
+
scope: "https://mail.google.com/ https://www.googleapis.com/auth/contacts.readonly",
|
|
326
|
+
tokenDirectory: tokenDir,
|
|
327
|
+
loginHint: account.imap.user,
|
|
328
|
+
});
|
|
329
|
+
return result?.access_token || "";
|
|
330
|
+
};
|
|
331
|
+
}
|
|
318
332
|
const config = createAutoImapConfig({
|
|
319
333
|
server: account.imap.host,
|
|
320
334
|
port: account.imap.port,
|
|
321
335
|
username: account.imap.user,
|
|
322
336
|
password: account.imap.password,
|
|
323
|
-
|
|
337
|
+
tokenProvider,
|
|
324
338
|
});
|
|
325
339
|
this.configs.set(account.id, config);
|
|
326
340
|
// Register account in DB
|
|
@@ -388,6 +402,11 @@ export class ImapManager extends EventEmitter {
|
|
|
388
402
|
this.db.beginTransaction();
|
|
389
403
|
try {
|
|
390
404
|
for (const msg of msgs) {
|
|
405
|
+
// Debug: log subjects with non-ASCII to trace encoding issues
|
|
406
|
+
if (msg.subject && /[^\x00-\x7F]/.test(msg.subject)) {
|
|
407
|
+
const hex = Buffer.from(msg.subject, "utf-8").subarray(0, 40).toString("hex");
|
|
408
|
+
console.log(` [encoding] subject: "${msg.subject.substring(0, 60)}" hex: ${hex}`);
|
|
409
|
+
}
|
|
391
410
|
if (msg.uid <= highestUid)
|
|
392
411
|
continue; // already have it
|
|
393
412
|
const source = msg.source || "";
|
|
@@ -500,7 +519,8 @@ export class ImapManager extends EventEmitter {
|
|
|
500
519
|
this.emit("folderCountsChanged", accountId, {});
|
|
501
520
|
}
|
|
502
521
|
};
|
|
503
|
-
|
|
522
|
+
const tomorrow = new Date(Date.now() + 86400000); // IMAP BEFORE is exclusive
|
|
523
|
+
messages = await client.fetchMessageByDate(folder.path, startDate, tomorrow, { source: false }, onChunk);
|
|
504
524
|
if (totalStored > 0) {
|
|
505
525
|
console.log(` ${folder.path}: ${totalStored} messages (streamed)`);
|
|
506
526
|
this.db.recalcFolderCounts(folderId);
|