mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-01 08:12:43 +00:00
37 lines
1.6 KiB
TypeScript
37 lines
1.6 KiB
TypeScript
import { PKPASS_MAX_BYTES, PKPASS_MAX_PER_MAIL, isPkpassAttachment, readPkpass } from '@/lib/structured-mail/pkpass';
|
|
import type { StructuredCard } from '@/lib/structured-mail';
|
|
import type { CardSource } from './sources';
|
|
|
|
/**
|
|
* Cards from Apple Wallet passes attached to a trusted message. Reads only
|
|
* `email.attachments`, the message's own parts: never the parts the viewer
|
|
* unwraps from an attached .eml or a TNEF winmail.dat, which the sender's
|
|
* authentication says nothing about. At most three passes, each downloaded
|
|
* from the message's own JMAP account and capped at 5 MB; stops between
|
|
* downloads once the message is closed. Never throws.
|
|
*/
|
|
export const pkpassSource: CardSource = async ({ email, mailDate, blob, signal }) => {
|
|
try {
|
|
const { client, accountId } = blob;
|
|
if (!client || signal.aborted) return [];
|
|
const attachments = (Array.isArray(email.attachments) ? email.attachments : [])
|
|
.filter((att) => !!att && typeof att.blobId === 'string' && att.blobId !== '' && isPkpassAttachment(att))
|
|
.slice(0, PKPASS_MAX_PER_MAIL);
|
|
const cards: StructuredCard[] = [];
|
|
for (const att of attachments) {
|
|
if (signal.aborted) return [];
|
|
let bytes: ArrayBuffer;
|
|
try {
|
|
// One byte past the cap, so a blob larger than its listed size is noticed and refused.
|
|
bytes = await client.fetchBlobArrayBuffer(att.blobId, att.name, att.type, accountId, PKPASS_MAX_BYTES + 1);
|
|
} catch {
|
|
continue;
|
|
}
|
|
cards.push(...await readPkpass(bytes, { mailDate }));
|
|
}
|
|
return signal.aborted ? [] : cards;
|
|
} catch {
|
|
return [];
|
|
}
|
|
};
|