@bobfrankston/mailx 1.0.234 → 1.0.235
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 +3 -3
- package/packages/mailx-imap/index.js +26 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/mailx",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.235",
|
|
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.2",
|
|
25
25
|
"@bobfrankston/miscinfo": "^1.0.8",
|
|
26
26
|
"@bobfrankston/oauthsupport": "^1.0.22",
|
|
27
|
-
"@bobfrankston/msger": "^0.1.
|
|
27
|
+
"@bobfrankston/msger": "^0.1.297",
|
|
28
28
|
"@capacitor/android": "^8.3.0",
|
|
29
29
|
"@capacitor/cli": "^8.3.0",
|
|
30
30
|
"@capacitor/core": "^8.3.0",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"@bobfrankston/iflow-node": "^0.1.2",
|
|
79
79
|
"@bobfrankston/miscinfo": "^1.0.8",
|
|
80
80
|
"@bobfrankston/oauthsupport": "^1.0.22",
|
|
81
|
-
"@bobfrankston/msger": "^0.1.
|
|
81
|
+
"@bobfrankston/msger": "^0.1.297",
|
|
82
82
|
"@capacitor/android": "^8.3.0",
|
|
83
83
|
"@capacitor/cli": "^8.3.0",
|
|
84
84
|
"@capacitor/core": "^8.3.0",
|
|
@@ -1009,9 +1009,15 @@ export class ImapManager extends EventEmitter {
|
|
|
1009
1009
|
// the previous high. upsertMessage's primary-key dedup handles it.
|
|
1010
1010
|
void highestUid;
|
|
1011
1011
|
let stored = 0;
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1012
|
+
let errors = 0;
|
|
1013
|
+
// Don't wrap the whole batch in one transaction: a single bad row
|
|
1014
|
+
// would roll back the entire batch. E.g. a message with a malformed
|
|
1015
|
+
// Date header gave `new Date(rawStr).getTime() === NaN`, SQLite
|
|
1016
|
+
// coerced that to NULL, the NOT NULL constraint failed, and the
|
|
1017
|
+
// whole Gmail sync lost 200 messages per tick. Now each row runs
|
|
1018
|
+
// standalone — bad rows are logged and skipped.
|
|
1019
|
+
for (const msg of msgs) {
|
|
1020
|
+
try {
|
|
1015
1021
|
const flags = [];
|
|
1016
1022
|
if (msg.seen)
|
|
1017
1023
|
flags.push("\\Seen");
|
|
@@ -1021,12 +1027,20 @@ export class ImapManager extends EventEmitter {
|
|
|
1021
1027
|
flags.push("\\Answered");
|
|
1022
1028
|
if (msg.draft)
|
|
1023
1029
|
flags.push("\\Draft");
|
|
1030
|
+
// Sanitize date: reject NaN (from malformed RFC 822 Date headers)
|
|
1031
|
+
// and fall back to "now" so the message still lands in the DB.
|
|
1032
|
+
let dateMs = Date.now();
|
|
1033
|
+
if (msg.date instanceof Date) {
|
|
1034
|
+
const t = msg.date.getTime();
|
|
1035
|
+
if (Number.isFinite(t))
|
|
1036
|
+
dateMs = t;
|
|
1037
|
+
}
|
|
1024
1038
|
this.db.upsertMessage({
|
|
1025
1039
|
accountId, folderId, uid: msg.uid,
|
|
1026
1040
|
messageId: msg.messageId || "",
|
|
1027
1041
|
inReplyTo: msg.inReplyTo || "",
|
|
1028
1042
|
references: msg.references || [],
|
|
1029
|
-
date:
|
|
1043
|
+
date: dateMs,
|
|
1030
1044
|
subject: msg.subject || "",
|
|
1031
1045
|
from: toEmailAddress(msg.from?.[0] || {}),
|
|
1032
1046
|
to: toEmailAddresses(msg.to || []),
|
|
@@ -1035,12 +1049,15 @@ export class ImapManager extends EventEmitter {
|
|
|
1035
1049
|
});
|
|
1036
1050
|
stored++;
|
|
1037
1051
|
}
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1052
|
+
catch (e) {
|
|
1053
|
+
errors++;
|
|
1054
|
+
if (errors <= 3) {
|
|
1055
|
+
console.error(` [api] upsert ${accountId}/${folderId}/${msg.uid} (${msg.messageId}): ${e.message}`);
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1043
1058
|
}
|
|
1059
|
+
if (errors > 0)
|
|
1060
|
+
console.error(` [api] storeApiMessages: ${errors} of ${msgs.length} rows failed (${stored} stored)`);
|
|
1044
1061
|
return stored;
|
|
1045
1062
|
}
|
|
1046
1063
|
/** Kill and recreate the persistent ops connection */
|