diff --git a/package.json b/package.json index 1f2e0c0..610c51c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "siteforge", "private": true, - "version": "1.1.17", + "version": "1.1.18", "type": "module", "scripts": { "dev": "vite", diff --git a/server/routes/inbound-email.js b/server/routes/inbound-email.js index f8efe93..5bf9d6d 100644 --- a/server/routes/inbound-email.js +++ b/server/routes/inbound-email.js @@ -6,6 +6,18 @@ import { MAX_CONTACT_SUBMISSIONS } from '../config.js' // RFC 5322 msg-id: "<" printable-ASCII-no-whitespace ">" const MESSAGE_ID_RE = /^<[\x21-\x7E]+>$/ +function decodeHtmlBody(raw) { + if (typeof raw !== 'string' || !raw.trim()) return null + const s = raw.trim() + if (s.startsWith('<')) return s // already plain HTML + try { + const decoded = Buffer.from(s.replace(/\s+/g, ''), 'base64').toString('utf8') + return decoded.trimStart().startsWith('<') ? decoded : s + } catch { + return s + } +} + export function register(app) { app.post('/api/inbound-email', (req, res) => { const secret = process.env.INBOUND_EMAIL_SECRET @@ -47,7 +59,7 @@ export function register(app) { name: fromName || fromEmail, email: fromEmail, message: [subject ? `Subject: ${subject}` : '', body ?? ''].filter(Boolean).join('\n\n'), - htmlBody: typeof htmlBody === 'string' && htmlBody.trim() ? htmlBody.trim() : null, + htmlBody: decodeHtmlBody(htmlBody), messageType: 'general', subscribe: false, archived: false, diff --git a/src/EmailPage.tsx b/src/EmailPage.tsx index f922059..68e5999 100644 --- a/src/EmailPage.tsx +++ b/src/EmailPage.tsx @@ -82,6 +82,11 @@ function formatDate(value: string | null | undefined): string { return Number.isNaN(d.getTime()) ? '—' : d.toLocaleString() } +function decodeHtmlBody(raw: string): string { + if (!raw || raw.trimStart().startsWith('<')) return raw + try { return atob(raw.replace(/\s+/g, '')) } catch { return raw } +} + function formatShortDate(value: string | null | undefined): string { if (!value) return '—' const d = new Date(value) @@ -671,7 +676,7 @@ function EmailClient({ onLogout }: { onLogout: () => void }) {