panel 2 courier api restore
This commit is contained in:
parent
42615957ec
commit
1dc167ec97
@ -9,6 +9,26 @@ function getEmailAddress(address: AddressObject | AddressObject[] | undefined):
|
|||||||
return address.text;
|
return address.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean up the HTML to make it safe but preserve styles
|
||||||
|
function processHtml(html: string | null): string | null {
|
||||||
|
if (!html) return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Make the content display well in the email context
|
||||||
|
return html
|
||||||
|
// Fix self-closing tags that might break React
|
||||||
|
.replace(/<(br|hr|img|input|link|meta|area|base|col|embed|keygen|param|source|track|wbr)([^>]*)>/gi, '<$1$2 />')
|
||||||
|
// Keep style tags but ensure they're closed properly
|
||||||
|
.replace(/<style([^>]*)>([\s\S]*?)<\/style>/gi, (match) => {
|
||||||
|
// Just return the matched style tag as-is
|
||||||
|
return match;
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error processing HTML:', error);
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
export async function POST(request: Request) {
|
||||||
try {
|
try {
|
||||||
const body = await request.json();
|
const body = await request.json();
|
||||||
@ -23,6 +43,10 @@ export async function POST(request: Request) {
|
|||||||
|
|
||||||
const parsed = await simpleParser(email);
|
const parsed = await simpleParser(email);
|
||||||
|
|
||||||
|
// Process the HTML to preserve styling but make it safe
|
||||||
|
// Handle the case where parsed.html could be a boolean
|
||||||
|
const processedHtml = typeof parsed.html === 'string' ? processHtml(parsed.html) : null;
|
||||||
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
subject: parsed.subject || null,
|
subject: parsed.subject || null,
|
||||||
from: getEmailAddress(parsed.from),
|
from: getEmailAddress(parsed.from),
|
||||||
@ -30,7 +54,7 @@ export async function POST(request: Request) {
|
|||||||
cc: getEmailAddress(parsed.cc),
|
cc: getEmailAddress(parsed.cc),
|
||||||
bcc: getEmailAddress(parsed.bcc),
|
bcc: getEmailAddress(parsed.bcc),
|
||||||
date: parsed.date || null,
|
date: parsed.date || null,
|
||||||
html: parsed.html || null,
|
html: processedHtml,
|
||||||
text: parsed.textAsHtml || parsed.text || null,
|
text: parsed.textAsHtml || parsed.text || null,
|
||||||
attachments: parsed.attachments?.map(att => ({
|
attachments: parsed.attachments?.map(att => ({
|
||||||
filename: att.filename,
|
filename: att.filename,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState, useRef, useEffect } from 'react';
|
import { useState, useRef, useEffect } from 'react';
|
||||||
import { formatEmailForReplyOrForward, EmailMessage } from '@/lib/services/email-service';
|
import { formatEmailForReplyOrForward, EmailMessage, EmailAddress } from '@/lib/services/email-service';
|
||||||
import { X, Paperclip, ChevronDown, ChevronUp, SendHorizontal, Loader2 } from 'lucide-react';
|
import { X, Paperclip, ChevronDown, ChevronUp, SendHorizontal, Loader2 } from 'lucide-react';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
@ -139,82 +139,72 @@ export default function ComposeEmail({
|
|||||||
setSending(true); // Use sending state to show loading
|
setSending(true); // Use sending state to show loading
|
||||||
|
|
||||||
// Format subject with Fwd: prefix if needed
|
// Format subject with Fwd: prefix if needed
|
||||||
const cleanSubject = initialEmail.subject.replace(/^(Fwd|FW|Forward):\s*/i, '').trim();
|
const cleanSubject = initialEmail.subject?.replace(/^(Fwd|FW|Forward):\s*/i, '').trim() || '';
|
||||||
const formattedSubject = initialEmail.subject.match(/^(Fwd|FW|Forward):/i)
|
const formattedSubject = initialEmail.subject?.match(/^(Fwd|FW|Forward):/i)
|
||||||
? initialEmail.subject
|
? initialEmail.subject
|
||||||
: `Fwd: ${cleanSubject}`;
|
: `Fwd: ${cleanSubject}`;
|
||||||
|
|
||||||
setSubject(formattedSubject);
|
setSubject(formattedSubject);
|
||||||
|
|
||||||
// Process the email content
|
// Store the email content directly without complex parsing
|
||||||
const emailContent = initialEmail.content || '';
|
const emailContent = initialEmail.content || '';
|
||||||
let processedContent = '';
|
|
||||||
|
|
||||||
// Only attempt to parse if we have content
|
// Create a forwarding header with proper types
|
||||||
if (emailContent.trim()) {
|
const fromDisplay = Array.isArray(initialEmail.from) && initialEmail.from.length > 0
|
||||||
try {
|
? initialEmail.from.map(f => f.name ? `${f.name} <${f.address}>` : f.address).join(', ')
|
||||||
// Parse email on the server
|
: 'Unknown Sender';
|
||||||
const response = await fetch('/api/parse-email', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ email: emailContent }),
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
const toDisplay = Array.isArray(initialEmail.to) && initialEmail.to.length > 0
|
||||||
if (!response.ok) {
|
? initialEmail.to.map(t => t.name ? `${t.name} <${t.address}>` : t.address).join(', ')
|
||||||
throw new Error(data.error || 'Failed to parse email');
|
: '';
|
||||||
}
|
|
||||||
|
|
||||||
// Use DOMPurify to sanitize the HTML but preserve style tags
|
const ccDisplay = initialEmail.cc && Array.isArray(initialEmail.cc) && initialEmail.cc.length > 0
|
||||||
const htmlContent = data.html || data.text || '';
|
? initialEmail.cc.map(c => c.name ? `${c.name} <${c.address}>` : c.address).join(', ')
|
||||||
|
: '';
|
||||||
|
|
||||||
// Configure DOMPurify to keep certain tags including style
|
const dateDisplay = initialEmail.date
|
||||||
const sanitizedContent = DOMPurify.sanitize(htmlContent, {
|
? initialEmail.date instanceof Date
|
||||||
ADD_TAGS: ['style', 'meta', 'link'],
|
? initialEmail.date.toLocaleString()
|
||||||
ADD_ATTR: ['id', 'class', 'style'],
|
: new Date(initialEmail.date as any).toLocaleString()
|
||||||
WHOLE_DOCUMENT: false
|
: '';
|
||||||
});
|
|
||||||
|
|
||||||
processedContent = sanitizedContent;
|
const subjectDisplay = initialEmail.subject || '(No subject)';
|
||||||
} catch (error) {
|
|
||||||
console.error('Error parsing email content:', error);
|
|
||||||
processedContent = '<div style="color: #666; font-style: italic;">Error processing original content</div>';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
processedContent = '<div style="color: #666; font-style: italic;">No content available</div>';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a clean, well-formatted forwarded message with the original styles preserved
|
// Don't try to parse the content, just wrap it in a container
|
||||||
|
const contentDisplay = emailContent.trim()
|
||||||
|
? `<div class="forwarded-content">${emailContent}</div>`
|
||||||
|
: '<div style="color: #666; font-style: italic;">No content available</div>';
|
||||||
|
|
||||||
|
// Construct the forwarded message with direct header information
|
||||||
const forwardedContent = `
|
const forwardedContent = `
|
||||||
<div style="border-top: 1px solid #e5e7eb; padding-top: 20px; margin-top: 20px; color: #6b7280; font-size: 0.875rem;">
|
<div style="border-top: 1px solid #e5e7eb; padding-top: 20px; margin-top: 20px;">
|
||||||
|
<div style="color: #6b7280; font-size: 0.875rem; margin-bottom: 15px;">
|
||||||
---------- Forwarded message ---------<br/>
|
---------- Forwarded message ---------<br/>
|
||||||
From: ${formatSender(initialEmail.from)}<br/>
|
<strong>From:</strong> ${fromDisplay}<br/>
|
||||||
Date: ${formatDate(initialEmail.date)}<br/>
|
<strong>Date:</strong> ${dateDisplay}<br/>
|
||||||
Subject: ${initialEmail.subject || ''}<br/>
|
<strong>Subject:</strong> ${subjectDisplay}<br/>
|
||||||
To: ${formatRecipients(initialEmail.to)}<br/>
|
<strong>To:</strong> ${toDisplay}<br/>
|
||||||
${initialEmail.cc && initialEmail.cc.length ? `Cc: ${formatRecipients(initialEmail.cc)}<br/>` : ''}
|
${ccDisplay ? `<strong>Cc:</strong> ${ccDisplay}<br/>` : ''}
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top: 10px;">
|
<div style="margin-top: 15px; border-left: 2px solid #e5e7eb; padding-left: 10px;">
|
||||||
${processedContent}
|
${contentDisplay}
|
||||||
</div>
|
</div>
|
||||||
`;
|
</div>`;
|
||||||
|
|
||||||
// Set the formatted content
|
// Set the formatted content
|
||||||
setBody(forwardedContent);
|
setBody(forwardedContent);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error initializing forwarded email:', error);
|
console.error('Error initializing forwarded email:', error);
|
||||||
const errorContent = `
|
// Fallback content for error case
|
||||||
|
setBody(`
|
||||||
<div style="border-top: 1px solid #e5e7eb; padding-top: 20px; margin-top: 20px; color: #6b7280; font-size: 0.875rem;">
|
<div style="border-top: 1px solid #e5e7eb; padding-top: 20px; margin-top: 20px; color: #6b7280; font-size: 0.875rem;">
|
||||||
---------- Forwarded message ---------<br/>
|
---------- Forwarded message ---------<br/>
|
||||||
From: ${initialEmail.from ? formatSender(initialEmail.from) : 'Unknown'}<br/>
|
<strong>From:</strong> ${initialEmail.from ? JSON.stringify(initialEmail.from) : 'Unknown'}<br/>
|
||||||
Date: ${initialEmail.date ? formatDate(initialEmail.date) : ''}<br/>
|
<strong>Date:</strong> ${initialEmail.date ? new Date(initialEmail.date as any).toLocaleString() : ''}<br/>
|
||||||
Subject: ${initialEmail.subject || ''}<br/>
|
<strong>Subject:</strong> ${initialEmail.subject || ''}<br/>
|
||||||
To: ${initialEmail.to ? formatRecipients(initialEmail.to) : ''}<br/>
|
<strong>To:</strong> ${initialEmail.to ? JSON.stringify(initialEmail.to) : ''}<br/>
|
||||||
</div>
|
</div>
|
||||||
<div style="color: #ef4444; font-style: italic; margin-top: 10px;">Error loading forwarded content</div>`;
|
<div style="color: #ef4444; font-style: italic; margin-top: 10px;">Error loading forwarded content</div>`);
|
||||||
setBody(errorContent);
|
|
||||||
} finally {
|
} finally {
|
||||||
setSending(false);
|
setSending(false);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user