handle email mime types (fixes #5), plus fix email display in letter view page
This commit is contained in:
parent
8b4dba62e1
commit
b5bb27e1b2
2 changed files with 70 additions and 4 deletions
|
@ -2,6 +2,66 @@ import NDK, { NDKEvent, type NDKEventId, NDKKind, type NDKUser } from '@nostr-de
|
|||
import { isValidNip05 } from '$lib/utils.svelte';
|
||||
import { TokenInfoWithMailSubscriptionDuration } from '@arx/utils';
|
||||
|
||||
function parseTextPlainContent(mimeMessage: string) {
|
||||
const boundary = mimeMessage.split('\n')[0];
|
||||
|
||||
// --7408fffb1a494ae39c2dde2c60878849
|
||||
// Content-Type: text/plain
|
||||
// Content-Transfer-Encoding: 7bit
|
||||
//
|
||||
// test
|
||||
// --7408fffb1a494ae39c2dde2c60878849
|
||||
// Content-Type: text/html
|
||||
// Content-Transfer-Encoding: 7bit
|
||||
|
||||
const boundaries = mimeMessage.split(boundary + '\n');
|
||||
boundaries.shift();
|
||||
|
||||
const bodies = [];
|
||||
|
||||
for (const body of boundaries) {
|
||||
const headers: Record<string, string> = {};
|
||||
const lines = body.split('\r\n');
|
||||
let isLookingForHeaders = true;
|
||||
let content = '';
|
||||
for (const line of lines) {
|
||||
if (line.trim() === '') {
|
||||
isLookingForHeaders = false;
|
||||
content += line + '\n';
|
||||
} else {
|
||||
if (!isLookingForHeaders) {
|
||||
content += line + '\n';
|
||||
continue;
|
||||
}
|
||||
const [key, value] = line.split(': ');
|
||||
headers[key.toLowerCase()] = value;
|
||||
}
|
||||
}
|
||||
bodies.push({ headers, content: content.trim() });
|
||||
}
|
||||
|
||||
if (bodies.length === 0) return mimeMessage;
|
||||
|
||||
let chosenBody = bodies.find((body) => body.headers['Content-Type'] === 'text/plain');
|
||||
if (!chosenBody) chosenBody = bodies[0];
|
||||
|
||||
const encoding = chosenBody.headers['content-transfer-encoding'];
|
||||
if (!encoding) return chosenBody.content; // assume plain text
|
||||
|
||||
switch (encoding.toLowerCase()) {
|
||||
case '7bit':
|
||||
return chosenBody.content;
|
||||
case 'base64':
|
||||
return atob(chosenBody.content.replaceAll('\n', ''));
|
||||
case 'quoted-printable':
|
||||
return chosenBody.content
|
||||
.replace(/=\r\n/g, '')
|
||||
.replace(/=([0-9A-F]{2})/g, (_, p1) => String.fromCharCode(parseInt(p1, 16)));
|
||||
default:
|
||||
return `Cannot decode ${encoding} encoded message. This is a bug, please report it.`;
|
||||
}
|
||||
}
|
||||
|
||||
export class Letter {
|
||||
id: NDKEventId;
|
||||
subject: string;
|
||||
|
@ -28,13 +88,19 @@ export class Letter {
|
|||
): Promise<Letter> {
|
||||
if (decryptedMessage.kind !== NDKKind.Article) throw new Error('Not a letter');
|
||||
|
||||
let rawContent = decryptedMessage.content;
|
||||
let content = '';
|
||||
let email = decryptedMessage.tags.find((t) => t[0] === 'email:from')?.[1];
|
||||
if (rawContent.startsWith('--') && email) content = parseTextPlainContent(rawContent);
|
||||
else content = rawContent;
|
||||
|
||||
const letter = new Letter();
|
||||
letter.id = encryptedMessage.id;
|
||||
letter.subject = decryptedMessage.tags.find((t) => t[0] === 'subject')?.[1] ?? 'No subject';
|
||||
letter.from = decryptedMessage.author;
|
||||
letter.content = decryptedMessage.content;
|
||||
letter.content = content;
|
||||
letter.date = new Date(decryptedMessage.created_at! * 1000);
|
||||
letter.emailAddress = decryptedMessage.tags.find((t) => t[0] === 'email:from')?.[1];
|
||||
letter.emailAddress = email;
|
||||
let stampToken = decryptedMessage.tags.find((t) => t[0] === 'stamp')?.[1];
|
||||
if (stampToken) {
|
||||
try {
|
||||
|
|
|
@ -70,13 +70,13 @@
|
|||
<div class="sender-recipient">
|
||||
<div class="user-row">
|
||||
<span class="label">From:</span>
|
||||
<NostrIdentifier user={letter.from.npub} />
|
||||
<NostrIdentifier user={letter.from.npub} emailAddress={letter.emailAddress} />
|
||||
</div>
|
||||
<div class="user-row">
|
||||
<span class="label">To:</span>
|
||||
<div class="recipients">
|
||||
{#each letter.recipients as recipient}
|
||||
<NostrIdentifier user={recipient.npub} />
|
||||
<NostrIdentifier user={recipient.npub} emailAddress={recipient.emailAddress} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue