@agenticmail/api 0.5.60 → 0.5.62
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/dist/index.js +84 -7
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1539,7 +1539,65 @@ async function closeCaches() {
|
|
|
1539
1539
|
}
|
|
1540
1540
|
receiverCache.clear();
|
|
1541
1541
|
}
|
|
1542
|
-
async function
|
|
1542
|
+
async function findUidByMessageId(receiver, messageId, maxAttempts = 8) {
|
|
1543
|
+
const target = normalizeMessageId(messageId);
|
|
1544
|
+
const client = receiver.getImapClient();
|
|
1545
|
+
const tryHeaderSearch = async () => {
|
|
1546
|
+
const lock = await client.getMailboxLock("INBOX");
|
|
1547
|
+
try {
|
|
1548
|
+
const results = await client.search(
|
|
1549
|
+
{ header: ["Message-ID", messageId] },
|
|
1550
|
+
{ uid: true }
|
|
1551
|
+
);
|
|
1552
|
+
if (Array.isArray(results) && results.length > 0) {
|
|
1553
|
+
return results[results.length - 1];
|
|
1554
|
+
}
|
|
1555
|
+
} finally {
|
|
1556
|
+
lock.release();
|
|
1557
|
+
}
|
|
1558
|
+
return 0;
|
|
1559
|
+
};
|
|
1560
|
+
const tryEnvelopeScan = async () => {
|
|
1561
|
+
const lock = await client.getMailboxLock("INBOX");
|
|
1562
|
+
try {
|
|
1563
|
+
const status = await client.status("INBOX", { messages: true });
|
|
1564
|
+
const total = status?.messages ?? 0;
|
|
1565
|
+
if (total === 0) return 0;
|
|
1566
|
+
const start = Math.max(1, total - 9);
|
|
1567
|
+
const range = `${start}:${total}`;
|
|
1568
|
+
let bestUid = 0;
|
|
1569
|
+
for await (const msg of client.fetch(range, { uid: true, envelope: true })) {
|
|
1570
|
+
if (!msg.envelope?.messageId) continue;
|
|
1571
|
+
if (normalizeMessageId(msg.envelope.messageId) === target) {
|
|
1572
|
+
if (msg.uid > bestUid) bestUid = msg.uid;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
return bestUid;
|
|
1576
|
+
} finally {
|
|
1577
|
+
lock.release();
|
|
1578
|
+
}
|
|
1579
|
+
};
|
|
1580
|
+
const delays = [0, 250, 500, 750, 1e3, 1250, 1500, 2e3];
|
|
1581
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
1582
|
+
if (delays[i]) await new Promise((r) => setTimeout(r, delays[i]));
|
|
1583
|
+
try {
|
|
1584
|
+
const headerHit = await tryHeaderSearch();
|
|
1585
|
+
if (headerHit > 0) return headerHit;
|
|
1586
|
+
const scanHit = await tryEnvelopeScan();
|
|
1587
|
+
if (scanHit > 0) return scanHit;
|
|
1588
|
+
} catch (err) {
|
|
1589
|
+
if (i === maxAttempts - 1) {
|
|
1590
|
+
console.warn(`[mail] findUidByMessageId attempt ${i + 1} failed for ${messageId}: ${err.message}`);
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
return 0;
|
|
1595
|
+
}
|
|
1596
|
+
function normalizeMessageId(id) {
|
|
1597
|
+
if (!id) return "";
|
|
1598
|
+
return id.trim().replace(/^<+|>+$/g, "").toLowerCase();
|
|
1599
|
+
}
|
|
1600
|
+
async function notifyLocalRecipientsOfNewMail(accountManager, toField, ccField, bccField, fromAgent, subject, messageId, config) {
|
|
1543
1601
|
const collected = [];
|
|
1544
1602
|
const push = (v) => {
|
|
1545
1603
|
if (!v) return;
|
|
@@ -1574,12 +1632,29 @@ async function notifyLocalRecipientsOfNewMail(accountManager, toField, ccField,
|
|
|
1574
1632
|
}
|
|
1575
1633
|
if (!recipient || notified.has(recipient.id)) continue;
|
|
1576
1634
|
notified.add(recipient.id);
|
|
1635
|
+
let uid = 0;
|
|
1636
|
+
let lookup = "no-message-id";
|
|
1637
|
+
if (messageId) {
|
|
1638
|
+
try {
|
|
1639
|
+
const recipientPassword = getAgentPassword(recipient);
|
|
1640
|
+
const receiver = await getReceiver(
|
|
1641
|
+
recipient.stalwartPrincipal,
|
|
1642
|
+
recipientPassword,
|
|
1643
|
+
config
|
|
1644
|
+
);
|
|
1645
|
+
uid = await findUidByMessageId(receiver, messageId);
|
|
1646
|
+
lookup = uid > 0 ? "resolved" : "failed";
|
|
1647
|
+
} catch {
|
|
1648
|
+
lookup = "failed";
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1577
1651
|
pushEventToAgent(recipient.id, {
|
|
1578
1652
|
type: "new",
|
|
1579
|
-
|
|
1580
|
-
//
|
|
1581
|
-
//
|
|
1582
|
-
|
|
1653
|
+
uid,
|
|
1654
|
+
// Tell consumers whether the UID is real or a sentinel — preserves
|
|
1655
|
+
// backwards compat (uid is still always a number) while giving
|
|
1656
|
+
// clients a reliable signal to fall back to /mail/inbox.
|
|
1657
|
+
uidLookup: lookup,
|
|
1583
1658
|
internal: true,
|
|
1584
1659
|
from: { name: fromAgent.name, address: fromAgent.email },
|
|
1585
1660
|
subject,
|
|
@@ -1726,7 +1801,8 @@ function createMailRoutes(accountManager, config, db, gatewayManager) {
|
|
|
1726
1801
|
bcc,
|
|
1727
1802
|
agent,
|
|
1728
1803
|
subject,
|
|
1729
|
-
result.messageId
|
|
1804
|
+
result.messageId,
|
|
1805
|
+
config
|
|
1730
1806
|
).catch((err) => {
|
|
1731
1807
|
console.warn(`[mail] Internal SSE notify failed: ${err.message}`);
|
|
1732
1808
|
});
|
|
@@ -2336,7 +2412,8 @@ function createMailRoutes(accountManager, config, db, gatewayManager) {
|
|
|
2336
2412
|
mailOpts.bcc,
|
|
2337
2413
|
agent,
|
|
2338
2414
|
mailOpts.subject,
|
|
2339
|
-
result.messageId
|
|
2415
|
+
result.messageId,
|
|
2416
|
+
config
|
|
2340
2417
|
).catch((err) => {
|
|
2341
2418
|
console.warn(`[mail] Internal SSE notify (approve) failed: ${err.message}`);
|
|
2342
2419
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agenticmail/api",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.62",
|
|
4
4
|
"description": "REST API server for AgenticMail — email and SMS endpoints for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"prepublishOnly": "npm run build"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@agenticmail/core": "^0.5.
|
|
30
|
+
"@agenticmail/core": "^0.5.61",
|
|
31
31
|
"cors": "^2.8.5",
|
|
32
32
|
"dotenv": "^16.4.7",
|
|
33
33
|
"express": "^4.21.0",
|