apple-mail-mcp 2.19.0 → 2.19.2
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 +10 -0
- package/build/cli.js +18 -2
- package/build/index.js +19 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -331,6 +331,16 @@ List messages in a mailbox.
|
|
|
331
331
|
|
|
332
332
|
**Returns:** List of messages with ID, date, subject, and sender.
|
|
333
333
|
|
|
334
|
+
⚠️ **Row dates differ by backend.** On the **IMAP** path each row carries both
|
|
335
|
+
`dateSent` (the message's `Date:` header) and `dateReceived` (mailbox arrival —
|
|
336
|
+
`INTERNALDATE`, falling back to the header date if the server withholds it).
|
|
337
|
+
They differ legitimately by transit time; when they differ by **years**, the
|
|
338
|
+
mailbox was migrated or re-imported and the arrival timestamp was reset — trust
|
|
339
|
+
`dateSent` for chronology ([#224](https://github.com/sweetrb/apple-mail-mcp/issues/224)).
|
|
340
|
+
On the **AppleScript** path rows carry only `dateReceived` (Mail's `date
|
|
341
|
+
received`); `dateSent` is not yet emitted there. Sort order keys on the header
|
|
342
|
+
date on both backends, which is the stable one.
|
|
343
|
+
|
|
334
344
|
---
|
|
335
345
|
|
|
336
346
|
#### `send-email`
|
package/build/cli.js
CHANGED
|
@@ -58093,13 +58093,25 @@ function formatRow(m, account, path) {
|
|
|
58093
58093
|
const read = m.flags?.has("\\Seen") ? "read" : "unread";
|
|
58094
58094
|
return ` - ID: ${encodeImapId(account, path, m.uid)} | ${date} | ${subject} (from: ${from}) [${read}]`;
|
|
58095
58095
|
}
|
|
58096
|
+
function isoOrEmpty(d) {
|
|
58097
|
+
if (!d) return "";
|
|
58098
|
+
const parsed = d instanceof Date ? d : new Date(d);
|
|
58099
|
+
return Number.isNaN(parsed.getTime()) ? "" : parsed.toISOString();
|
|
58100
|
+
}
|
|
58096
58101
|
function structuredRow(m, account, path) {
|
|
58097
58102
|
const env = m.envelope ?? {};
|
|
58098
58103
|
return {
|
|
58099
58104
|
id: encodeImapId(account, path, m.uid),
|
|
58100
58105
|
subject: env.subject || "(no subject)",
|
|
58101
58106
|
sender: senderName(env.from),
|
|
58102
|
-
|
|
58107
|
+
// ⚠️ `env.date` is the `Date:` HEADER — imapflow builds ENVELOPE from the
|
|
58108
|
+
// header block — so emitting it as `dateReceived` made the same field name
|
|
58109
|
+
// mean "sent" here and "arrived" on the AppleScript path. Both are now
|
|
58110
|
+
// emitted under the name that is true of them, matching `messageSummary`.
|
|
58111
|
+
// `dateReceived` falls back to the header date when the server withheld
|
|
58112
|
+
// INTERNALDATE, which is the old behaviour and never invents a value.
|
|
58113
|
+
dateSent: isoOrEmpty(env.date),
|
|
58114
|
+
dateReceived: isoOrEmpty(m.internalDate ?? env.date),
|
|
58103
58115
|
isRead: m.flags?.has("\\Seen") ?? false,
|
|
58104
58116
|
isFlagged: m.flags?.has("\\Flagged") ?? false,
|
|
58105
58117
|
flagColorIndex: mailFlagColorIndex(m.flags),
|
|
@@ -58145,7 +58157,11 @@ async function fetchMailboxMatches(client, path, criteria, newestCount) {
|
|
|
58145
58157
|
// BODYSTRUCTURE rides along so `hasAttachments` is computed rather
|
|
58146
58158
|
// than assumed. Measured on 50 real messages: ~390ms -> ~465ms for
|
|
58147
58159
|
// the fetch (~17%), same single round trip, no extra request.
|
|
58148
|
-
|
|
58160
|
+
//
|
|
58161
|
+
// INTERNALDATE rides along for the same reason, and is why `dateReceived`
|
|
58162
|
+
// can finally mean what it says: imapflow's `envelope.date` is built from
|
|
58163
|
+
// the header block, so it IS the `Date:` header, not arrival time.
|
|
58164
|
+
{ envelope: true, flags: true, bodyStructure: true, internalDate: true },
|
|
58149
58165
|
{ uid: true }
|
|
58150
58166
|
)) {
|
|
58151
58167
|
byUid.set(msg.uid, msg);
|
package/build/index.js
CHANGED
|
@@ -65132,7 +65132,7 @@ function splitIds(raw) {
|
|
|
65132
65132
|
return raw.split(/[\s,]+/).map(bareId).filter(Boolean);
|
|
65133
65133
|
}
|
|
65134
65134
|
function parseHeaderBlock(input) {
|
|
65135
|
-
const text = (input ?? "").replace(/\r\n/g, "\n");
|
|
65135
|
+
const text = (input ?? "").replace(/\r\n|\r/g, "\n");
|
|
65136
65136
|
const blank = text.search(/\n\n/);
|
|
65137
65137
|
const raw = (blank === -1 ? text : text.slice(0, blank)).replace(/\n+$/, "");
|
|
65138
65138
|
const headers = [];
|
|
@@ -65503,13 +65503,25 @@ function formatRow(m, account, path) {
|
|
|
65503
65503
|
const read = m.flags?.has("\\Seen") ? "read" : "unread";
|
|
65504
65504
|
return ` - ID: ${encodeImapId(account, path, m.uid)} | ${date3} | ${subject} (from: ${from}) [${read}]`;
|
|
65505
65505
|
}
|
|
65506
|
+
function isoOrEmpty(d) {
|
|
65507
|
+
if (!d) return "";
|
|
65508
|
+
const parsed = d instanceof Date ? d : new Date(d);
|
|
65509
|
+
return Number.isNaN(parsed.getTime()) ? "" : parsed.toISOString();
|
|
65510
|
+
}
|
|
65506
65511
|
function structuredRow(m, account, path) {
|
|
65507
65512
|
const env = m.envelope ?? {};
|
|
65508
65513
|
return {
|
|
65509
65514
|
id: encodeImapId(account, path, m.uid),
|
|
65510
65515
|
subject: env.subject || "(no subject)",
|
|
65511
65516
|
sender: senderName(env.from),
|
|
65512
|
-
|
|
65517
|
+
// ⚠️ `env.date` is the `Date:` HEADER — imapflow builds ENVELOPE from the
|
|
65518
|
+
// header block — so emitting it as `dateReceived` made the same field name
|
|
65519
|
+
// mean "sent" here and "arrived" on the AppleScript path. Both are now
|
|
65520
|
+
// emitted under the name that is true of them, matching `messageSummary`.
|
|
65521
|
+
// `dateReceived` falls back to the header date when the server withheld
|
|
65522
|
+
// INTERNALDATE, which is the old behaviour and never invents a value.
|
|
65523
|
+
dateSent: isoOrEmpty(env.date),
|
|
65524
|
+
dateReceived: isoOrEmpty(m.internalDate ?? env.date),
|
|
65513
65525
|
isRead: m.flags?.has("\\Seen") ?? false,
|
|
65514
65526
|
isFlagged: m.flags?.has("\\Flagged") ?? false,
|
|
65515
65527
|
flagColorIndex: mailFlagColorIndex(m.flags),
|
|
@@ -65555,7 +65567,11 @@ async function fetchMailboxMatches(client, path, criteria, newestCount) {
|
|
|
65555
65567
|
// BODYSTRUCTURE rides along so `hasAttachments` is computed rather
|
|
65556
65568
|
// than assumed. Measured on 50 real messages: ~390ms -> ~465ms for
|
|
65557
65569
|
// the fetch (~17%), same single round trip, no extra request.
|
|
65558
|
-
|
|
65570
|
+
//
|
|
65571
|
+
// INTERNALDATE rides along for the same reason, and is why `dateReceived`
|
|
65572
|
+
// can finally mean what it says: imapflow's `envelope.date` is built from
|
|
65573
|
+
// the header block, so it IS the `Date:` header, not arrival time.
|
|
65574
|
+
{ envelope: true, flags: true, bodyStructure: true, internalDate: true },
|
|
65559
65575
|
{ uid: true }
|
|
65560
65576
|
)) {
|
|
65561
65577
|
byUid.set(msg.uid, msg);
|
package/package.json
CHANGED