panel 2 courier api restore
This commit is contained in:
parent
f805463949
commit
5d058428fd
@ -11,38 +11,81 @@ function getEmailAddress(address: AddressObject | AddressObject[] | undefined):
|
|||||||
|
|
||||||
export async function POST(request: Request) {
|
export async function POST(request: Request) {
|
||||||
try {
|
try {
|
||||||
|
console.log('[DEBUG] Parse-email API called');
|
||||||
|
|
||||||
const body = await request.json();
|
const body = await request.json();
|
||||||
const emailContent = body.email || body.emailContent;
|
const emailContent = body.email || body.emailContent;
|
||||||
|
|
||||||
if (!emailContent || typeof emailContent !== 'string') {
|
if (!emailContent || typeof emailContent !== 'string') {
|
||||||
|
console.error('[DEBUG] Parse-email API error: Invalid email content');
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: 'Invalid email content' },
|
{ error: 'Invalid email content' },
|
||||||
{ status: 400 }
|
{ status: 400 }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsed = await simpleParser(emailContent);
|
console.log('[DEBUG] Parse-email API processing email content, length:', emailContent.length);
|
||||||
|
console.log('[DEBUG] Content sample:', emailContent.substring(0, 100) + '...');
|
||||||
|
|
||||||
return NextResponse.json({
|
try {
|
||||||
subject: parsed.subject || null,
|
const parsed = await simpleParser(emailContent);
|
||||||
from: getEmailAddress(parsed.from),
|
|
||||||
to: getEmailAddress(parsed.to),
|
console.log('[DEBUG] Parse-email API successfully parsed email:', {
|
||||||
cc: getEmailAddress(parsed.cc),
|
hasSubject: !!parsed.subject,
|
||||||
bcc: getEmailAddress(parsed.bcc),
|
hasHtml: !!parsed.html,
|
||||||
date: parsed.date || null,
|
hasText: !!parsed.text,
|
||||||
html: parsed.html || null,
|
hasTextAsHtml: !!parsed.textAsHtml,
|
||||||
text: parsed.textAsHtml || parsed.text || null,
|
fromCount: parsed.from ? (Array.isArray(parsed.from) ? parsed.from.length : 1) : 0,
|
||||||
attachments: parsed.attachments?.map(att => ({
|
attachmentCount: parsed.attachments?.length || 0
|
||||||
filename: att.filename,
|
});
|
||||||
contentType: att.contentType,
|
|
||||||
size: att.size
|
return NextResponse.json({
|
||||||
})) || [],
|
subject: parsed.subject || null,
|
||||||
headers: parsed.headers || {}
|
from: getEmailAddress(parsed.from),
|
||||||
});
|
to: getEmailAddress(parsed.to),
|
||||||
|
cc: getEmailAddress(parsed.cc),
|
||||||
|
bcc: getEmailAddress(parsed.bcc),
|
||||||
|
date: parsed.date || null,
|
||||||
|
html: parsed.html || parsed.textAsHtml || null,
|
||||||
|
text: parsed.text || null,
|
||||||
|
attachments: parsed.attachments?.map(att => ({
|
||||||
|
filename: att.filename,
|
||||||
|
contentType: att.contentType,
|
||||||
|
size: att.size
|
||||||
|
})) || [],
|
||||||
|
headers: parsed.headers || {}
|
||||||
|
});
|
||||||
|
} catch (parseError) {
|
||||||
|
console.error('[DEBUG] Parse-email API error parsing email:', parseError);
|
||||||
|
|
||||||
|
// Try simpler parsing method for more resilience
|
||||||
|
try {
|
||||||
|
console.log('[DEBUG] Attempting fallback parsing method');
|
||||||
|
const resultObj: any = { text: emailContent, html: null };
|
||||||
|
|
||||||
|
// Simple check if it might be HTML
|
||||||
|
if (emailContent.includes('<html') || emailContent.includes('<body')) {
|
||||||
|
resultObj.html = emailContent;
|
||||||
|
} else {
|
||||||
|
// Convert plain text to HTML
|
||||||
|
resultObj.html = emailContent
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/\n/g, '<br>');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[DEBUG] Fallback parsing generated simple result');
|
||||||
|
return NextResponse.json(resultObj);
|
||||||
|
} catch (fallbackError) {
|
||||||
|
console.error('[DEBUG] Even fallback parsing failed:', fallbackError);
|
||||||
|
throw parseError; // Throw the original error
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error parsing email:', error);
|
console.error('[DEBUG] Parse-email API unhandled error:', error);
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: 'Failed to parse email' },
|
{ error: 'Failed to parse email', details: error instanceof Error ? error.message : 'Unknown error' },
|
||||||
{ status: 500 }
|
{ status: 500 }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
273
app/courrier/[id]/route.ts
Normal file
273
app/courrier/[id]/route.ts
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { ImapFlow } from 'imapflow';
|
||||||
|
import { getServerSession } from 'next-auth';
|
||||||
|
import { authOptions } from '@/app/api/auth/[...nextauth]/route';
|
||||||
|
import { prisma } from '@/lib/prisma';
|
||||||
|
import { simpleParser } from 'mailparser';
|
||||||
|
|
||||||
|
// Simple in-memory cache for email content
|
||||||
|
const emailContentCache = new Map<string, { content: string, timestamp: number }>();
|
||||||
|
const CACHE_TTL = 30 * 60 * 1000; // 30 minutes in milliseconds
|
||||||
|
|
||||||
|
export async function GET(
|
||||||
|
request: Request,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
console.log(`[DEBUG] GET request for single email ID: ${params.id}`);
|
||||||
|
|
||||||
|
const session = await getServerSession(authOptions);
|
||||||
|
if (!session || !session.user?.id) {
|
||||||
|
console.log('[DEBUG] Not authenticated');
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Not authenticated" },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { id } = params;
|
||||||
|
if (!id) {
|
||||||
|
console.log('[DEBUG] Missing email ID');
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Missing email ID" },
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check cache first
|
||||||
|
const cacheKey = `${session.user.id}:${id}`;
|
||||||
|
const cachedContent = emailContentCache.get(cacheKey);
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
if (cachedContent && now - cachedContent.timestamp < CACHE_TTL) {
|
||||||
|
console.log(`[DEBUG] Using cached content for email ${id}`);
|
||||||
|
return NextResponse.json({
|
||||||
|
id,
|
||||||
|
content: cachedContent.content,
|
||||||
|
contentFetched: true,
|
||||||
|
fromCache: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get mail credentials
|
||||||
|
const credentials = await prisma.mailCredentials.findUnique({
|
||||||
|
where: {
|
||||||
|
userId: session.user.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!credentials) {
|
||||||
|
console.log('[DEBUG] No mail credentials found');
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "No mail credentials found" },
|
||||||
|
{ status: 404 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const folder = searchParams.get("folder") || "INBOX";
|
||||||
|
console.log(`[DEBUG] Fetching email ${id} from folder ${folder}`);
|
||||||
|
|
||||||
|
// Create IMAP client
|
||||||
|
let imapClient: any = null;
|
||||||
|
try {
|
||||||
|
imapClient = new ImapFlow({
|
||||||
|
host: credentials.host,
|
||||||
|
port: credentials.port,
|
||||||
|
secure: true,
|
||||||
|
auth: {
|
||||||
|
user: credentials.email,
|
||||||
|
pass: credentials.password,
|
||||||
|
},
|
||||||
|
logger: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
await imapClient.connect();
|
||||||
|
console.log(`[DEBUG] Connected to IMAP server to fetch email ${id}`);
|
||||||
|
|
||||||
|
// Select mailbox
|
||||||
|
const mailboxData = await imapClient.mailboxOpen(folder);
|
||||||
|
console.log(`[DEBUG] Opened mailbox ${folder}, total messages: ${mailboxData.exists}`);
|
||||||
|
|
||||||
|
// Fetch the complete email with its source
|
||||||
|
const message = await imapClient.fetchOne(Number(id), {
|
||||||
|
source: true,
|
||||||
|
envelope: true
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!message) {
|
||||||
|
console.log(`[DEBUG] Email ${id} not found`);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Email not found" },
|
||||||
|
{ status: 404 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { source, envelope } = message;
|
||||||
|
console.log(`[DEBUG] Successfully fetched email source, length: ${source.length}`);
|
||||||
|
|
||||||
|
// Parse the full email content
|
||||||
|
const parsedEmail = await simpleParser(source.toString());
|
||||||
|
console.log(`[DEBUG] Parsed email source: has HTML: ${!!parsedEmail.html}, has text: ${!!parsedEmail.text}`);
|
||||||
|
|
||||||
|
// Prioritize HTML content with fallbacks
|
||||||
|
const content = parsedEmail.html || parsedEmail.textAsHtml || parsedEmail.text || '';
|
||||||
|
|
||||||
|
// Cache the content
|
||||||
|
emailContentCache.set(cacheKey, {
|
||||||
|
content,
|
||||||
|
timestamp: now
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the content
|
||||||
|
return NextResponse.json({
|
||||||
|
id,
|
||||||
|
subject: envelope.subject,
|
||||||
|
content,
|
||||||
|
contentFetched: true
|
||||||
|
});
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error("[DEBUG] Error fetching email content:", error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
error: "Failed to fetch email content",
|
||||||
|
message: error.message,
|
||||||
|
details: error.stack
|
||||||
|
},
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
// Close the mailbox and connection
|
||||||
|
if (imapClient) {
|
||||||
|
try {
|
||||||
|
await imapClient.mailboxClose();
|
||||||
|
await imapClient.logout();
|
||||||
|
console.log(`[DEBUG] Closed IMAP connection for email ${id}`);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[DEBUG] Error closing IMAP connection:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error("[DEBUG] Unhandled error in GET:", error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
error: "Internal server error",
|
||||||
|
message: error.message,
|
||||||
|
details: error.stack
|
||||||
|
},
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle marking emails as read
|
||||||
|
export async function POST(
|
||||||
|
request: Request,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
console.log(`[DEBUG] POST request for email ID: ${params.id}`);
|
||||||
|
|
||||||
|
const session = await getServerSession(authOptions);
|
||||||
|
if (!session || !session.user?.id) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Not authenticated" },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { id } = params;
|
||||||
|
if (!id) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Missing email ID" },
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = await request.json();
|
||||||
|
const { action } = body;
|
||||||
|
|
||||||
|
if (action !== 'mark-read' && action !== 'mark-unread') {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Invalid action. Supported actions: mark-read, mark-unread" },
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[DEBUG] Processing action ${action} for email ${id}`);
|
||||||
|
|
||||||
|
// Get mail credentials
|
||||||
|
const credentials = await prisma.mailCredentials.findUnique({
|
||||||
|
where: {
|
||||||
|
userId: session.user.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!credentials) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "No mail credentials found" },
|
||||||
|
{ status: 404 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const folder = searchParams.get("folder") || "INBOX";
|
||||||
|
|
||||||
|
// Create IMAP client
|
||||||
|
let imapClient: any = null;
|
||||||
|
try {
|
||||||
|
imapClient = new ImapFlow({
|
||||||
|
host: credentials.host,
|
||||||
|
port: credentials.port,
|
||||||
|
secure: true,
|
||||||
|
auth: {
|
||||||
|
user: credentials.email,
|
||||||
|
pass: credentials.password,
|
||||||
|
},
|
||||||
|
logger: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
await imapClient.connect();
|
||||||
|
console.log(`[DEBUG] Connected to IMAP server for ${action}`);
|
||||||
|
|
||||||
|
// Select mailbox
|
||||||
|
await imapClient.mailboxOpen(folder);
|
||||||
|
console.log(`[DEBUG] Opened mailbox ${folder} for ${action}`);
|
||||||
|
|
||||||
|
// Set flag based on action
|
||||||
|
if (action === 'mark-read') {
|
||||||
|
await imapClient.messageFlagsAdd(Number(id), ['\\Seen']);
|
||||||
|
console.log(`[DEBUG] Marked email ${id} as read`);
|
||||||
|
} else {
|
||||||
|
await imapClient.messageFlagsRemove(Number(id), ['\\Seen']);
|
||||||
|
console.log(`[DEBUG] Marked email ${id} as unread`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, action });
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error(`[DEBUG] Error ${action}:`, error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: `Failed to ${action}`, message: error.message },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
// Close the mailbox and connection
|
||||||
|
if (imapClient) {
|
||||||
|
try {
|
||||||
|
await imapClient.mailboxClose();
|
||||||
|
await imapClient.logout();
|
||||||
|
console.log(`[DEBUG] Closed IMAP connection after ${action}`);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[DEBUG] Error closing IMAP connection:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error("[DEBUG] Unhandled error in POST:", error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Internal server error", message: error.message },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -888,6 +888,38 @@ export default function CourrierPage() {
|
|||||||
throw new Error('Email not found in list');
|
throw new Error('Email not found in list');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if we need to fetch full content
|
||||||
|
if (!selectedEmail.content || selectedEmail.content.length === 0) {
|
||||||
|
console.log('[DEBUG] Fetching full content for email:', emailId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/api/courrier/${emailId}?folder=${encodeURIComponent(selectedEmail.folder || 'INBOX')}`);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Failed to fetch email content: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fullContent = await response.json();
|
||||||
|
|
||||||
|
// Update the email content with the fetched full content
|
||||||
|
selectedEmail.content = fullContent.content;
|
||||||
|
selectedEmail.contentFetched = true;
|
||||||
|
|
||||||
|
// Update the email in the list too so we don't refetch
|
||||||
|
setEmails(prevEmails =>
|
||||||
|
prevEmails.map(email =>
|
||||||
|
email.id === emailId
|
||||||
|
? { ...email, content: fullContent.content, contentFetched: true }
|
||||||
|
: email
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('[DEBUG] Successfully fetched full content for email:', emailId);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[DEBUG] Error fetching full content:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set selected email from our existing data (which now includes full content)
|
// Set selected email from our existing data (which now includes full content)
|
||||||
setSelectedEmail(selectedEmail);
|
setSelectedEmail(selectedEmail);
|
||||||
|
|
||||||
@ -1507,6 +1539,44 @@ export default function CourrierPage() {
|
|||||||
if (!selectedEmail) return;
|
if (!selectedEmail) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Ensure we have full content before proceeding
|
||||||
|
if (!selectedEmail.content || selectedEmail.content.length === 0) {
|
||||||
|
console.log('[DEBUG] Need to fetch content before reply/forward');
|
||||||
|
setContentLoading(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/api/courrier/${selectedEmail.id}?folder=${encodeURIComponent(selectedEmail.folder || 'INBOX')}`);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Failed to fetch email content: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fullContent = await response.json();
|
||||||
|
|
||||||
|
// Update the email content with the fetched full content
|
||||||
|
selectedEmail.content = fullContent.content;
|
||||||
|
selectedEmail.contentFetched = true;
|
||||||
|
|
||||||
|
// Update the email in the list too so we don't refetch
|
||||||
|
setEmails(prevEmails =>
|
||||||
|
prevEmails.map(email =>
|
||||||
|
email.id === selectedEmail.id
|
||||||
|
? { ...email, content: fullContent.content, contentFetched: true }
|
||||||
|
: email
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('[DEBUG] Successfully fetched content for reply/forward');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[DEBUG] Error fetching content for reply:', error);
|
||||||
|
alert('Failed to load email content for reply. Please try again.');
|
||||||
|
setContentLoading(false);
|
||||||
|
return; // Exit if we couldn't get the content
|
||||||
|
}
|
||||||
|
|
||||||
|
setContentLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
const getReplyTo = () => {
|
const getReplyTo = () => {
|
||||||
if (type === 'forward') return '';
|
if (type === 'forward') return '';
|
||||||
return selectedEmail.from;
|
return selectedEmail.from;
|
||||||
|
|||||||
@ -90,8 +90,27 @@ export default function ComposeEmail({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const emailToProcess = replyTo || forwardFrom;
|
const emailToProcess = replyTo || forwardFrom;
|
||||||
|
console.log('[DEBUG] Initializing compose content with email:',
|
||||||
|
emailToProcess ? {
|
||||||
|
id: emailToProcess.id,
|
||||||
|
subject: emailToProcess.subject,
|
||||||
|
hasContent: !!emailToProcess.content,
|
||||||
|
contentLength: emailToProcess.content ? emailToProcess.content.length : 0,
|
||||||
|
preview: emailToProcess.preview
|
||||||
|
} : 'null'
|
||||||
|
);
|
||||||
|
|
||||||
if (!emailToProcess?.content) {
|
if (!emailToProcess?.content) {
|
||||||
console.error('No email content found to process');
|
console.error('[DEBUG] No email content found to process');
|
||||||
|
composeBodyRef.current.innerHTML = `
|
||||||
|
<div class="compose-area" contenteditable="true">
|
||||||
|
<br/>
|
||||||
|
<div style="color: #ef4444;">Error: No original message content available.</div>
|
||||||
|
<div style="color: #64748b; font-size: 0.875rem; margin-top: 0.5rem;">
|
||||||
|
Please select the email again or try refreshing the page.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,6 +122,8 @@ export default function ComposeEmail({
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
console.log('[DEBUG] Sending content to parse-email API, length:', emailToProcess.content.length);
|
||||||
|
|
||||||
// Parse the original email using the API
|
// Parse the original email using the API
|
||||||
const response = await fetch('/api/parse-email', {
|
const response = await fetch('/api/parse-email', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -112,12 +133,24 @@ export default function ComposeEmail({
|
|||||||
body: JSON.stringify({ email: emailToProcess.content }),
|
body: JSON.stringify({ email: emailToProcess.content }),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('[DEBUG] Parse-email API response status:', response.status);
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
console.log('[DEBUG] Parse-email API response:', {
|
||||||
|
hasHtml: !!data.html,
|
||||||
|
hasText: !!data.text,
|
||||||
|
subject: data.subject,
|
||||||
|
error: data.error
|
||||||
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(data.error || 'Failed to parse email');
|
throw new Error(data.error || 'Failed to parse email');
|
||||||
}
|
}
|
||||||
|
|
||||||
const emailContent = data.html || data.text || '';
|
const emailContent = data.html || data.text || '';
|
||||||
|
if (!emailContent) {
|
||||||
|
console.warn('[DEBUG] No HTML or text content returned from parser');
|
||||||
|
}
|
||||||
|
|
||||||
// Format the reply/forward content
|
// Format the reply/forward content
|
||||||
const quotedContent = forwardFrom ? `
|
const quotedContent = forwardFrom ? `
|
||||||
@ -167,14 +200,18 @@ export default function ComposeEmail({
|
|||||||
// Update compose state
|
// Update compose state
|
||||||
setComposeBody(formattedContent);
|
setComposeBody(formattedContent);
|
||||||
setLocalContent(formattedContent);
|
setLocalContent(formattedContent);
|
||||||
|
console.log('[DEBUG] Successfully set compose content');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error initializing compose content:', error);
|
console.error('[DEBUG] Error initializing compose content:', error);
|
||||||
if (composeBodyRef.current) {
|
if (composeBodyRef.current) {
|
||||||
const errorContent = `
|
const errorContent = `
|
||||||
<div class="compose-area" contenteditable="true">
|
<div class="compose-area" contenteditable="true">
|
||||||
<br/>
|
<br/>
|
||||||
<div style="color: #ef4444;">Error loading original message.</div>
|
<div style="color: #ef4444;">Error loading original message.</div>
|
||||||
|
<div style="color: #64748b; font-size: 0.875rem; margin-top: 0.5rem;">
|
||||||
|
Technical details: ${error instanceof Error ? error.message : 'Unknown error'}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
composeBodyRef.current.innerHTML = errorContent;
|
composeBodyRef.current.innerHTML = errorContent;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user