Mail: instant first paint from the last saved accounts, folders and list; Outlook folders in one batched call; gzip for app files and large mail responses
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
fb7aabff61
commit
84a0ea10e9
6 files changed
+69
-17
No files matched your search
@@ -56,7 +56,9 @@ const free = () => 21000 + Math.floor(Math.random() * 20000);
|
||||
r = await A('/api/mail/status'); ok('status lists the account with its unread count (2 unread in the inbox)', r.json.connected && r.json.accounts.length === 1 && r.json.accounts[0].unread === 2 && r.json.unread === 2, r.json);
|
||||
|
||||
r = await A('/api/mail/status?light=1'); ok('the light status lists the accounts without asking the mail servers (what lets the Mail tab draw at once)', r.json.connected && r.json.accounts.length === 1 && !r.json.accounts[0].error, r.json);
|
||||
const t0 = Date.now(); r = await A('/api/mail/status'); const t1 = Date.now(); r = await A('/api/mail/status'); ok('the full status is answered from a short-lived cache the second time (counts are refreshed at most every 30 s)', Date.now() - t1 <= Math.max(50, t1 - t0), [t1 - t0, Date.now() - t1]);
|
||||
{ const first = (await A('/api/mail/status')).json.unread; // unread counts are cached for 30 s: change the real mailbox behind the hub's back and the number stays
|
||||
const c = new ImapFlow({ host: '127.0.0.1', port: imapPort, secure: false, doSTARTTLS: false, auth: { user: ME, pass: PASS }, logger: false }); await c.connect(); const lock = await c.getMailboxLock('INBOX');
|
||||
try { await c.messageFlagsAdd('1', ['\\Seen']); const again = (await A('/api/mail/status')).json.unread; ok('the full status serves a cached unread count for up to 30 s (so opening Mail never waits on the mail servers)', again === first, [first, again]); await c.messageFlagsRemove('1', ['\\Seen']); } finally { lock.release(); await c.logout(); } }
|
||||
|
||||
// ================= reading =================
|
||||
r = await A('/api/mail/folders?acct=' + gm.id); const names = r.json.map(f => f.name);
|
||||
|
||||
+3
-1
@@ -42,6 +42,7 @@ const SECRET = 'mail-test-secret-'.repeat(3);
|
||||
const tok = (rq.headers.authorization || '').replace('Bearer ', '');
|
||||
if (!ms.goodTokens.has(tok)) return out(rs, 401, { error: { code: 'InvalidAuthenticationToken', message: 'expired' } });
|
||||
const g = p.slice(5);
|
||||
if (g === '/$batch' && rq.method === 'POST') { ms.batches = (ms.batches || 0) + 1; const reqs = JSON.parse(b).requests, self = `http://127.0.0.1:${server.address().port}/v1.0`; const responses = []; for (const q of reqs) { const r = await fetch(self + q.url, { method: q.method, headers: { authorization: rq.headers.authorization } }); responses.push({ id: q.id, status: r.status, body: await r.json().catch(() => ({})) }); } return out(rs, 200, { responses }); }
|
||||
if (g === '/me') return out(rs, 200, { displayName: 'Nate', mail: 'nate@outlook.com' });
|
||||
let m;
|
||||
if ((m = /^\/me\/mailFolders\/(\w+)$/.exec(g))) { const f = { inbox: folder('inbox', 'Inbox', 3, 10), drafts: folder('drafts', 'Drafts', 0, 1), sentitems: folder('sentitems', 'Sent Items', 0, 4), archive: folder('archive', 'Archive', 0, 0), junkemail: folder('junkemail', 'Junk Email', 0, 0), deleteditems: folder('deleteditems', 'Deleted Items', 0, 2) }[m[1]]; return f ? out(rs, 200, f) : out(rs, 404, { error: { message: 'no folder' } }); }
|
||||
@@ -101,7 +102,8 @@ const SECRET = 'mail-test-secret-'.repeat(3);
|
||||
r = await call('uann', '/api/mail/messages'); ok("and cannot read it", r.status === 409, r.status);
|
||||
|
||||
// ================= reading =================
|
||||
r = await call('unate', '/api/mail/folders'); const names = (r.json || []).map(f => f.name);
|
||||
ms.batches = 0; r = await call('unate', '/api/mail/folders'); const names = (r.json || []).map(f => f.name);
|
||||
ok('the folder list costs one batched call to Microsoft, not seven', ms.batches === 1, ms.batches);
|
||||
ok('folders: the usual six first with unread counts, then your own; internal ones hidden', names.slice(0, 6).join() === 'Inbox,Drafts,Sent,Archive,Junk,Deleted' && names.includes('Receipts') && !names.includes('Outbox') && r.json[0].unread === 3 && names.filter(n => n === 'Inbox').length === 1, r.json);
|
||||
r = await call('unate', '/api/mail/messages?folder=inbox'); ok('the inbox lists messages, newest first, with who, read state and attachment flag', r.status === 200 && r.json.items.length === 2 && r.json.items[0].from.address === 'ann@example.com' && r.json.items[0].read === false && r.json.items[0].attach === true && r.json.items[1].flagged === true, r.json);
|
||||
ok('and says there may be more', r.json.more === true && r.json.next === 2, r.json);
|
||||
|
||||
Reference in new issue
Block a user