Render inbound email HTML body in admin inbox
Worker now extracts both text/plain and text/html MIME parts and sends htmlBody in the webhook payload. Server stores it on the submission. Admin inbox renders htmlBody in a sandboxed iframe when present, falling back to plain text with whitespace preserved. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+16
-14
@@ -84,35 +84,37 @@ function parseEmail(raw, message) {
|
||||
const date = headers['date'] ?? new Date().toISOString()
|
||||
const messageId = headers['message-id'] ?? ''
|
||||
|
||||
// Extract plain text body — skip MIME boundaries and HTML parts
|
||||
const bodyLines = lines.slice(bodyStart)
|
||||
const plainText = extractPlainText(raw, bodyLines)
|
||||
const plainText = extractPart(raw, bodyLines, 'text/plain')
|
||||
const htmlBody = extractPart(raw, bodyLines, 'text/html')
|
||||
|
||||
return {
|
||||
from,
|
||||
to,
|
||||
subject,
|
||||
body: plainText,
|
||||
htmlBody: htmlBody || null,
|
||||
date,
|
||||
messageId,
|
||||
source: 'inbound-email',
|
||||
}
|
||||
}
|
||||
|
||||
function extractPlainText(raw, bodyLines) {
|
||||
// Look for Content-Type: text/plain section in multipart emails
|
||||
const textPlainMatch = /Content-Type: text\/plain[^\r\n]*\r?\n(?:[^\r\n]+\r?\n)*\r?\n([\s\S]*?)(?=--|\z)/i.exec(raw)
|
||||
if (textPlainMatch) {
|
||||
return decodeEmailBody(textPlainMatch[1]).trim()
|
||||
function extractPart(raw, bodyLines, contentType) {
|
||||
const escaped = contentType.replace('/', '\\/')
|
||||
const re = new RegExp(`Content-Type: ${escaped}[^\\r\\n]*\\r?\\n(?:[^\\r\\n]+\\r?\\n)*\\r?\\n([\\s\\S]*?)(?=--|$)`, 'i')
|
||||
const match = re.exec(raw)
|
||||
if (match) return decodeEmailBody(match[1]).trim()
|
||||
|
||||
if (contentType === 'text/plain') {
|
||||
const joined = bodyLines.join('\n')
|
||||
if (/<[a-z][\s\S]*>/i.test(joined)) {
|
||||
return joined.replace(/<[^>]+>/g, '').replace(/ /g, ' ').replace(/&/g, '&').replace(/\s{3,}/g, '\n\n').trim()
|
||||
}
|
||||
return joined.trim()
|
||||
}
|
||||
|
||||
// Fallback: join body lines, strip HTML tags if present
|
||||
const joined = bodyLines.join('\n')
|
||||
if (/<[a-z][\s\S]*>/i.test(joined)) {
|
||||
return joined.replace(/<[^>]+>/g, '').replace(/ /g, ' ').replace(/&/g, '&').replace(/\s{3,}/g, '\n\n').trim()
|
||||
}
|
||||
|
||||
return joined.trim()
|
||||
return null
|
||||
}
|
||||
|
||||
function decodeEmailBody(text) {
|
||||
|
||||
Reference in New Issue
Block a user