diff --git a/components/email/BulkActionsToolbar.tsx b/components/email/BulkActionsToolbar.tsx index 04a70e79..da260fe5 100644 --- a/components/email/BulkActionsToolbar.tsx +++ b/components/email/BulkActionsToolbar.tsx @@ -20,7 +20,7 @@ export default function BulkActionsToolbar({ onBulkAction }: BulkActionsToolbarProps) { return ( -
Mark as read
+Mark as unread
${text.replace(/\n/g, '
')}
` : 'No content available
'); + // Format subject with Re: prefix + const subject = email.subject ? + (email.subject.toLowerCase().startsWith('re:') ? email.subject : `Re: ${email.subject}`) : + 'Re: '; - // Wrap the original content in proper styling without losing the HTML structure - const cleanHtml = ` - ${replyHeader} -- ${contentHtml} -- `; + // Get recipient addresses + const { to, cc } = getRecipientAddresses(email, type); - // Plain text version - const plainText = ` -On ${dateStr}, ${fromStr} wrote: -------------------------------------------------------------------- -${text.split('\n').join('\n> ')} - `; - - return { - to, - cc, - subject: subject.startsWith('Re:') ? subject : `Re: ${subject}`, - content: { - text: plainText.trim(), - html: cleanHtml, - isHtml: true, - direction: 'ltr' + // Get email content and sanitize it + const originalContent = email.content; + + // Extract text and html content + let htmlContent = ''; + let textContent = ''; + let direction: 'ltr' | 'rtl' = 'ltr'; + + // Handle different content formats + if (typeof originalContent === 'string') { + console.log('formatReplyEmail: content is string, length:', originalContent.length); + // Simple string content + textContent = originalContent; + const isHtml = isHtmlContent(originalContent); + if (isHtml) { + htmlContent = originalContent; + } else { + // If it's plain text, convert to HTML + htmlContent = formatPlainTextToHtml(originalContent); } + } + else if (originalContent) { + console.log('formatReplyEmail: content is object:', { + hasHtml: !!originalContent.html, + htmlLength: originalContent.html?.length || 0, + hasText: !!originalContent.text, + textLength: originalContent.text?.length || 0, + direction: originalContent.direction + }); + + // Standard EmailContent object + htmlContent = originalContent.html || ''; + textContent = originalContent.text || ''; + direction = originalContent.direction || 'ltr' as const; + + // If no HTML but has text, convert text to HTML + if (!htmlContent && textContent) { + htmlContent = formatPlainTextToHtml(textContent); + } + } + + // Get quote header + const { fromStr, dateStr } = getFormattedHeaderInfo(email); + + // Use the from name if available, otherwise use email address + const sender = fromStr; + const date = dateStr; + + // Create the quoted reply content + if (htmlContent) { + // Format HTML reply + console.log('Formatting HTML reply, quoted content length:', htmlContent.length); + htmlContent = ` +
+ ${sanitizeHtml(htmlContent)} ++ `; + } + + if (textContent) { + // Format plain text reply + const lines = textContent.split(/\r\n|\r|\n/); + textContent = `On ${date}, ${sender} wrote:\n\n${lines.map(line => `> ${line}`).join('\n')}`; + } + + const result = { + to, + cc: cc || undefined, + subject, + content: { + html: htmlContent, + text: textContent, + isHtml: true, + direction, + }, + attachments: email.attachments?.map(att => { + // Create properly typed attachment + if ('name' in att) { + return { + filename: att.filename || att.name || 'attachment', + contentType: att.contentType || 'application/octet-stream', + content: att.content + }; + } + return { + filename: att.filename || 'attachment', + contentType: att.contentType || 'application/octet-stream', + content: att.content + }; + }) }; + + console.log('formatReplyEmail result:', { + to: result.to, + subject: result.subject, + hasHtml: !!result.content.html, + htmlLength: result.content.html?.length || 0, + hasText: !!result.content.text, + textLength: result.content.text?.length || 0 + }); + + return result; } /** * Format email for forwarding */ export function formatForwardedEmail(originalEmail: EmailMessage | LegacyEmailMessage | null): FormattedEmail { + console.log('formatForwardedEmail called:', { emailId: originalEmail?.id }); + if (!originalEmail) { + console.warn('formatForwardedEmail: No original email provided'); return { to: '', subject: '', - content: { - text: '', - html: '', - isHtml: false, - direction: 'ltr' as const - } + content: { text: '', html: '', isHtml: false, direction: 'ltr' } }; } + + // Adapt legacy format if needed + const email = 'content' in originalEmail ? originalEmail : adaptLegacyEmail(originalEmail); + + // Format subject with Fwd: prefix + const subject = email.subject ? + (email.subject.toLowerCase().startsWith('fwd:') ? email.subject : `Fwd: ${email.subject}`) : + 'Fwd: '; + + // Get original email info for headers + const { fromStr, toStr, ccStr, dateStr } = getFormattedHeaderInfo(email); + + console.log('Forward header info:', { fromStr, toStr, dateStr, subject }); + + // Original sent date + const date = dateStr; + + // Get email content + const originalContent = email.content; + + // Extract text and html content + let htmlContent = ''; + let textContent = ''; + let direction: 'ltr' | 'rtl' = 'ltr'; + + // Handle different content formats + if (typeof originalContent === 'string') { + console.log('formatForwardedEmail: content is string, length:', originalContent.length); + // Simple string content + textContent = originalContent; + const isHtml = isHtmlContent(originalContent); + if (isHtml) { + htmlContent = originalContent; + } else { + // If it's plain text, convert to HTML + htmlContent = formatPlainTextToHtml(originalContent); + } + } + else if (originalContent) { + console.log('formatForwardedEmail: content is object:', { + hasHtml: !!originalContent.html, + htmlLength: originalContent.html?.length || 0, + hasText: !!originalContent.text, + textLength: originalContent.text?.length || 0, + direction: originalContent.direction + }); + + // Standard EmailContent object + htmlContent = originalContent.html || ''; + textContent = originalContent.text || ''; + direction = originalContent.direction || 'ltr' as const; + + // If no HTML but has text, convert text to HTML + if (!htmlContent && textContent) { + htmlContent = formatPlainTextToHtml(textContent); + } + } - // Get header information - const { fromStr, toStr, ccStr, dateStr, subject } = getFormattedHeaderInfo(originalEmail); - - // Extract content using the centralized extraction function - const { text, html } = extractEmailContent(originalEmail); - - // Create a traditional forward format with dashed separator - const forwardHeader = ` -
| From: | +${fromStr} | +
| Date: | +${date} | +
| Subject: | +${email.subject || ''} | +
| To: | +${toStr} | +
| Cc: | +${ccStr} | +
| From: | -${fromStr} | -
| Date: | -${dateStr} | -
| Subject: | -${subject || ''} | -
| To: | -${toStr} | -
| Cc: | -${ccStr} | -
${text.replace(/\n/g, '
')}
` : 'No content available
'); - - const cleanHtml = `${forwardHeader}${contentHtml}`; - - // Plain text version - with clearer formatting - const plainText = ` ----------------------------- Forwarded Message ---------------------------- + // Format the plain text version + if (textContent) { + textContent = ` +---------- Forwarded message ---------- From: ${fromStr} -Date: ${dateStr} -Subject: ${subject || ''} +Date: ${date} +Subject: ${email.subject || ''} To: ${toStr} -${ccStr ? `Cc: ${ccStr}` : ''} ----------------------------------------------------------------------- +${ccStr ? `Cc: ${ccStr}\n` : ''} -${text} - `; - - // Check if original has attachments - const attachments = originalEmail.attachments || []; - - return { +${textContent} + `.trim(); + } + + const result = { to: '', - subject: subject.startsWith('Fwd:') ? subject : `Fwd: ${subject}`, + subject, content: { - text: plainText.trim(), - html: cleanHtml, + html: htmlContent, + text: textContent, isHtml: true, - direction: 'ltr' + direction, }, - // Only include attachments if they exist - attachments: attachments.length > 0 ? attachments.map(att => ({ - filename: att.filename || 'attachment', - contentType: att.contentType || 'application/octet-stream', - content: att.content - })) : undefined + attachments: email.attachments?.map(att => { + // Create properly typed attachment + if ('name' in att) { + return { + filename: att.filename || att.name || 'attachment', + contentType: att.contentType || 'application/octet-stream', + content: att.content + }; + } + return { + filename: att.filename || 'attachment', + contentType: att.contentType || 'application/octet-stream', + content: att.content + }; + }) }; + + console.log('formatForwardedEmail result:', { + subject: result.subject, + hasHtml: !!result.content.html, + htmlLength: result.content.html?.length || 0, + hasText: !!result.content.text, + textLength: result.content.text?.length || 0 + }); + + return result; } /**