panel 2 courier api restore
This commit is contained in:
parent
f21f626497
commit
684c0cf4ef
89
app/api/debug-email/route.ts
Normal file
89
app/api/debug-email/route.ts
Normal file
@ -0,0 +1,89 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { getServerSession } from 'next-auth';
|
||||
import { authOptions } from '@/app/api/auth/[...nextauth]/route';
|
||||
import { getImapConnection } from '@/lib/services/email-service';
|
||||
import { simpleParser } from 'mailparser';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
// Verify authentication
|
||||
const session = await getServerSession(authOptions);
|
||||
if (!session?.user?.id) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
try {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const emailId = searchParams.get('id');
|
||||
const folder = searchParams.get('folder') || 'INBOX';
|
||||
|
||||
if (!emailId) {
|
||||
return NextResponse.json({ error: 'Email ID is required' }, { status: 400 });
|
||||
}
|
||||
|
||||
// Connect to IMAP
|
||||
const client = await getImapConnection(session.user.id);
|
||||
|
||||
try {
|
||||
await client.mailboxOpen(folder);
|
||||
|
||||
// Fetch raw email
|
||||
const message = await client.fetchOne(emailId, {
|
||||
source: true,
|
||||
envelope: true,
|
||||
flags: true
|
||||
});
|
||||
|
||||
if (!message) {
|
||||
return NextResponse.json({ error: 'Email not found' }, { status: 404 });
|
||||
}
|
||||
|
||||
// Get raw source content
|
||||
const { source, envelope } = message;
|
||||
const rawSource = source.toString();
|
||||
|
||||
// Parse the email with multiple options to debug
|
||||
const parsedEmail = await simpleParser(rawSource, {
|
||||
skipHtmlToText: true,
|
||||
keepCidLinks: true
|
||||
});
|
||||
|
||||
// Extract all available data
|
||||
return NextResponse.json({
|
||||
id: emailId,
|
||||
folder,
|
||||
date: envelope.date,
|
||||
subject: envelope.subject,
|
||||
from: envelope.from,
|
||||
to: envelope.to,
|
||||
// Raw content (truncated to prevent massive responses)
|
||||
sourcePreview: rawSource.substring(0, 1000) + (rawSource.length > 1000 ? '...' : ''),
|
||||
sourceLength: rawSource.length,
|
||||
// Parsed content
|
||||
htmlPreview: parsedEmail.html ? parsedEmail.html.substring(0, 1000) + (parsedEmail.html.length > 1000 ? '...' : '') : null,
|
||||
htmlLength: parsedEmail.html ? parsedEmail.html.length : 0,
|
||||
textPreview: parsedEmail.text ? parsedEmail.text.substring(0, 1000) + (parsedEmail.text.length > 1000 ? '...' : '') : null,
|
||||
textLength: parsedEmail.text ? parsedEmail.text.length : 0,
|
||||
// Detect if there's HTML and what type of content it contains
|
||||
hasHtml: !!parsedEmail.html,
|
||||
hasStyleTags: typeof parsedEmail.html === 'string' && parsedEmail.html.includes('<style'),
|
||||
hasCss: typeof parsedEmail.html === 'string' && parsedEmail.html.includes('style='),
|
||||
// Headers that might be relevant
|
||||
contentType: parsedEmail.headers.get('content-type'),
|
||||
// Attachment count
|
||||
attachmentCount: parsedEmail.attachments.length
|
||||
});
|
||||
} finally {
|
||||
try {
|
||||
await client.logout();
|
||||
} catch (error) {
|
||||
console.error('Error logging out:', error);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error in debug-email route:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Server error', message: error instanceof Error ? error.message : String(error) },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -127,78 +127,124 @@ export default function ComposeEmail({
|
||||
).join(', ');
|
||||
};
|
||||
|
||||
// Initialize forwarded email with a dead simple approach
|
||||
// Initialize forwarded email with clear structure and style preservation
|
||||
const initializeForwardedEmail = async () => {
|
||||
console.log('Starting initializeForwardedEmail');
|
||||
if (!initialEmail) {
|
||||
console.error('No email available for forwarding');
|
||||
setBody('<div style="color: #666; font-style: italic;">No email available for forwarding</div>');
|
||||
return;
|
||||
}
|
||||
|
||||
// Debug log to see the structure of the email object
|
||||
console.log('Forwarding email object:', JSON.stringify({
|
||||
// Debug the email object structure
|
||||
console.log('Forwarding email object:', {
|
||||
id: initialEmail.id,
|
||||
subject: initialEmail.subject,
|
||||
fromLength: initialEmail.from?.length,
|
||||
from: initialEmail.from,
|
||||
to: initialEmail.to,
|
||||
date: initialEmail.date,
|
||||
hasContent: !!initialEmail.content,
|
||||
hasHTML: !!initialEmail.html,
|
||||
hasText: !!initialEmail.text,
|
||||
contentFetched: initialEmail.contentFetched
|
||||
}, null, 2));
|
||||
hasContent: Boolean(initialEmail.content),
|
||||
contentLength: initialEmail.content?.length,
|
||||
hasHtml: Boolean(initialEmail.html),
|
||||
htmlLength: initialEmail.html?.length
|
||||
});
|
||||
|
||||
try {
|
||||
// Format subject with Fwd: prefix if needed
|
||||
const subject = initialEmail.subject || "(No subject)";
|
||||
if (!subject.match(/^(Fwd|FW|Forward):/i)) {
|
||||
setSubject(`Fwd: ${subject}`);
|
||||
} else {
|
||||
const subjectBase = initialEmail.subject || '(No subject)';
|
||||
const subjectRegex = /^(Fwd|FW|Forward):\s*/i;
|
||||
const subject = subjectRegex.test(subjectBase)
|
||||
? subjectBase
|
||||
: `Fwd: ${subjectBase}`;
|
||||
|
||||
setSubject(subject);
|
||||
|
||||
// Format the forwarded message with a well-structured header
|
||||
const fromString = Array.isArray(initialEmail.from) && initialEmail.from.length > 0
|
||||
? initialEmail.from.map(addr => addr.name
|
||||
? `${addr.name} <${addr.address}>`
|
||||
: addr.address).join(', ')
|
||||
: 'Unknown';
|
||||
|
||||
const toString = Array.isArray(initialEmail.to) && initialEmail.to.length > 0
|
||||
? initialEmail.to.map(addr => addr.name
|
||||
? `${addr.name} <${addr.address}>`
|
||||
: addr.address).join(', ')
|
||||
: '';
|
||||
|
||||
const dateString = initialEmail.date
|
||||
? typeof initialEmail.date === 'string'
|
||||
? new Date(initialEmail.date).toLocaleString()
|
||||
: initialEmail.date.toLocaleString()
|
||||
: new Date().toLocaleString();
|
||||
|
||||
// Create a clean wrapper that won't interfere with the original email's styling
|
||||
const headerHtml = `
|
||||
<div style="border-top: 1px solid #e1e1e1; margin-top: 20px; padding-top: 15px; font-family: Arial, sans-serif; color: #333;">
|
||||
<div style="margin-bottom: 15px;">
|
||||
<div style="font-weight: normal; margin-bottom: 10px;">---------- Forwarded message ---------</div>
|
||||
<div><b>From:</b> ${fromString}</div>
|
||||
<div><b>Date:</b> ${dateString}</div>
|
||||
<div><b>Subject:</b> ${subjectBase}</div>
|
||||
<div><b>To:</b> ${toString}</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Get the content with proper fallbacks
|
||||
let originalContent = '';
|
||||
|
||||
// First try the html field which should contain the raw HTML
|
||||
if (initialEmail.html && initialEmail.html.trim()) {
|
||||
console.log('Using HTML content for forward');
|
||||
originalContent = initialEmail.html;
|
||||
}
|
||||
// Then try the content field
|
||||
else if (initialEmail.content && initialEmail.content.trim()) {
|
||||
console.log('Using content field for forward');
|
||||
originalContent = initialEmail.content;
|
||||
}
|
||||
// Fall back to text with styling if available
|
||||
else if (initialEmail.text && initialEmail.text.trim()) {
|
||||
console.log('Using text content for forward');
|
||||
originalContent = `<div style="white-space: pre-wrap; font-family: monospace;">${initialEmail.text}</div>`;
|
||||
}
|
||||
// Last resort - no content available
|
||||
else {
|
||||
console.log('No content available for forward');
|
||||
originalContent = '<div style="color: #666; font-style: italic; padding: 10px;">No content available</div>';
|
||||
}
|
||||
|
||||
// Get email content - use whatever data we have available
|
||||
const content = initialEmail.content || initialEmail.html || initialEmail.text || '';
|
||||
|
||||
// Get from info - handle various possible formats
|
||||
let from = 'Unknown Sender';
|
||||
if (initialEmail.from) {
|
||||
if (Array.isArray(initialEmail.from) && initialEmail.from.length > 0) {
|
||||
from = initialEmail.from[0].address || 'Unknown';
|
||||
} else if (typeof initialEmail.from === 'string') {
|
||||
from = initialEmail.from;
|
||||
}
|
||||
}
|
||||
|
||||
// Hard-code a simple format that definitely works
|
||||
// Preserve all original structure by wrapping, not modifying the original content
|
||||
const forwardedContent = `
|
||||
<div style="border-top: 1px solid #ccc; margin-top: 20px; padding-top: 10px; color: #666;">
|
||||
<p>---------- Forwarded message ---------</p>
|
||||
<p><b>From:</b> ${from}</p>
|
||||
<p><b>Date:</b> ${new Date().toLocaleString()}</p>
|
||||
<p><b>Subject:</b> ${subject}</p>
|
||||
<p><b>To:</b> ${Array.isArray(initialEmail.to) && initialEmail.to.length > 0 ? initialEmail.to[0].address : ''}</p>
|
||||
</div>
|
||||
${headerHtml}
|
||||
<div class="original-email-content" style="margin-top: 10px; border-left: 2px solid #e1e1e1; padding-left: 15px;">
|
||||
${originalContent}
|
||||
</div>
|
||||
`;
|
||||
|
||||
<div style="margin-top: 20px; padding: 10px; border-left: 2px solid #ccc;">
|
||||
${content ? content : '<p style="color: #666; font-style: italic;">No content available</p>'}
|
||||
</div>`;
|
||||
|
||||
// Just set the HTML directly
|
||||
console.log('Setting body with forwarded content');
|
||||
setBody(forwardedContent);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error initializing forwarded email:', error);
|
||||
// Super simple fallback
|
||||
|
||||
// Even in error case, provide a usable template
|
||||
setBody(`
|
||||
<div style="border-top: 1px solid #ccc; margin-top: 20px; padding-top: 10px;">
|
||||
<p>---------- Forwarded message ---------</p>
|
||||
<p><b>From:</b> ${initialEmail.from ? (Array.isArray(initialEmail.from) ? initialEmail.from[0].address : initialEmail.from) : 'Unknown'}</p>
|
||||
<p><b>Date:</b> ${new Date().toLocaleString()}</p>
|
||||
<p><b>Subject:</b> ${initialEmail.subject || ''}</p>
|
||||
<p><b>To:</b> ${initialEmail.to ? (Array.isArray(initialEmail.to) ? initialEmail.to[0].address : initialEmail.to) : ''}</p>
|
||||
</div>
|
||||
<p style="color: #666; font-style: italic;">Content could not be displayed</p>`);
|
||||
<div style="border-top: 1px solid #e1e1e1; margin-top: 20px; padding-top: 15px; font-family: Arial, sans-serif; color: #333;">
|
||||
<div style="margin-bottom: 15px;">
|
||||
<div style="font-weight: normal; margin-bottom: 10px;">---------- Forwarded message ---------</div>
|
||||
<div><b>From:</b> ${initialEmail.from ? JSON.stringify(initialEmail.from) : 'Unknown'}</div>
|
||||
<div><b>Date:</b> ${new Date().toLocaleString()}</div>
|
||||
<div><b>Subject:</b> ${initialEmail.subject || '(No subject)'}</div>
|
||||
<div><b>To:</b> ${initialEmail.to ? JSON.stringify(initialEmail.to) : ''}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 10px; padding: 10px; color: #d32f2f; font-style: italic;">
|
||||
Error loading original message content. The original message may still be viewable in your inbox.
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -405,12 +405,18 @@ export async function getEmailContent(
|
||||
|
||||
const { source, envelope, flags } = message;
|
||||
|
||||
// Parse the email content
|
||||
const parsedEmail = await simpleParser(source.toString());
|
||||
// Parse the email content, ensuring all styles and structure are preserved
|
||||
const parsedEmail = await simpleParser(source.toString(), {
|
||||
skipHtmlToText: true, // Don't convert HTML to plain text
|
||||
keepCidLinks: true // Keep Content-ID references for inline images
|
||||
});
|
||||
|
||||
// Convert flags from Set to boolean checks
|
||||
const flagsArray = Array.from(flags as Set<string>);
|
||||
|
||||
// Preserve the raw HTML exactly as it was in the original email
|
||||
const rawHtml = parsedEmail.html || '';
|
||||
|
||||
return {
|
||||
id: emailId,
|
||||
messageId: envelope.messageId,
|
||||
@ -445,9 +451,11 @@ export async function getEmailContent(
|
||||
contentType: att.contentType,
|
||||
size: att.size || 0
|
||||
})),
|
||||
html: parsedEmail.html || undefined,
|
||||
// Preserve the exact raw HTML to maintain all styling
|
||||
html: rawHtml,
|
||||
text: parsedEmail.text || undefined,
|
||||
content: parsedEmail.html || parsedEmail.textAsHtml || parsedEmail.text || '',
|
||||
// For content field, prioritize using the raw HTML to preserve all styling
|
||||
content: rawHtml || parsedEmail.text || '',
|
||||
folder,
|
||||
contentFetched: true
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user