courrier preview
This commit is contained in:
parent
5160967c75
commit
ddcb428233
@ -35,16 +35,38 @@ function cleanupTableStructures(htmlContent: string): string {
|
|||||||
htmlContent.includes('forwarded message') ||
|
htmlContent.includes('forwarded message') ||
|
||||||
(htmlContent.includes('From:') && htmlContent.includes('Date:') && htmlContent.includes('Subject:'));
|
(htmlContent.includes('From:') && htmlContent.includes('Date:') && htmlContent.includes('Subject:'));
|
||||||
|
|
||||||
|
const isReplyEmail =
|
||||||
|
htmlContent.includes('wrote:') ||
|
||||||
|
htmlContent.includes('<blockquote') ||
|
||||||
|
htmlContent.includes('gmail_quote');
|
||||||
|
|
||||||
// Check if content has complex tables that might cause issues
|
// Check if content has complex tables that might cause issues
|
||||||
const hasComplexTables = tables.length > 0 &&
|
const hasComplexTables = tables.length > 0 &&
|
||||||
(isForwardedEmail || htmlContent.includes('gmail_quote') ||
|
(isForwardedEmail || isReplyEmail);
|
||||||
htmlContent.includes('blockquote') || htmlContent.includes('wrote:'));
|
|
||||||
|
|
||||||
if (hasComplexTables) {
|
if (hasComplexTables) {
|
||||||
console.log(`Found ${tables.length} tables in complex email content`);
|
console.log(`Found ${tables.length} tables in complex email content`);
|
||||||
|
|
||||||
let convertedCount = 0;
|
let convertedCount = 0;
|
||||||
tables.forEach(table => {
|
tables.forEach(table => {
|
||||||
|
// Special handling for tables inside blockquotes (quoted content)
|
||||||
|
if (table.closest('blockquote') ||
|
||||||
|
(isReplyEmail && table.innerHTML.includes('wrote:'))) {
|
||||||
|
console.log('Preserving table inside quoted content');
|
||||||
|
// Apply minimal styling to ensure it renders correctly
|
||||||
|
table.setAttribute('style', 'border-collapse: collapse; width: 100%; max-width: 100%; margin: 8px 0;');
|
||||||
|
// Make sure all cells have some basic styling
|
||||||
|
const cells = table.querySelectorAll('td, th');
|
||||||
|
cells.forEach(cell => {
|
||||||
|
if (cell instanceof HTMLTableCellElement) {
|
||||||
|
cell.style.padding = '4px';
|
||||||
|
cell.style.textAlign = 'left';
|
||||||
|
cell.style.verticalAlign = 'top';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Preserve the main forwarded email header table
|
// Preserve the main forwarded email header table
|
||||||
if (isForwardedEmail &&
|
if (isForwardedEmail &&
|
||||||
table.innerHTML.includes('From:') &&
|
table.innerHTML.includes('From:') &&
|
||||||
@ -180,8 +202,18 @@ const RichEmailEditor: React.FC<RichEmailEditorProps> = ({
|
|||||||
hasBlockquote: initialContent.includes('<blockquote')
|
hasBlockquote: initialContent.includes('<blockquote')
|
||||||
});
|
});
|
||||||
|
|
||||||
// Process HTML content using centralized utility
|
// Check if content is reply or forward to use special handling
|
||||||
const processed = processHtmlContent(initialContent);
|
const isReplyOrForward =
|
||||||
|
initialContent.includes('wrote:') ||
|
||||||
|
initialContent.includes('<blockquote') ||
|
||||||
|
initialContent.includes('Forwarded message') ||
|
||||||
|
initialContent.includes('---------- Forwarded message ----------');
|
||||||
|
|
||||||
|
// Process HTML content using centralized utility with special settings for replies/forwards
|
||||||
|
const processed = processHtmlContent(initialContent, {
|
||||||
|
sanitize: true,
|
||||||
|
preserveReplyFormat: isReplyOrForward
|
||||||
|
});
|
||||||
const sanitizedContent = processed.sanitizedContent;
|
const sanitizedContent = processed.sanitizedContent;
|
||||||
const direction = processed.direction; // Use direction from processed result
|
const direction = processed.direction; // Use direction from processed result
|
||||||
|
|
||||||
@ -194,6 +226,7 @@ const RichEmailEditor: React.FC<RichEmailEditorProps> = ({
|
|||||||
containsQuoteHeader: sanitizedContent.includes('wrote:'),
|
containsQuoteHeader: sanitizedContent.includes('wrote:'),
|
||||||
hasTable: sanitizedContent.includes('<table'),
|
hasTable: sanitizedContent.includes('<table'),
|
||||||
hasBlockquote: sanitizedContent.includes('<blockquote'),
|
hasBlockquote: sanitizedContent.includes('<blockquote'),
|
||||||
|
isReplyOrForward: isReplyOrForward,
|
||||||
firstNChars: sanitizedContent.substring(0, 100).replace(/\n/g, '\\n')
|
firstNChars: sanitizedContent.substring(0, 100).replace(/\n/g, '\\n')
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -213,8 +246,19 @@ const RichEmailEditor: React.FC<RichEmailEditorProps> = ({
|
|||||||
quillRef.current.setText('Error loading content');
|
quillRef.current.setText('Error loading content');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Use direct innerHTML setting for the initial content
|
// Special handling for reply or forwarded content
|
||||||
quillRef.current.root.innerHTML = sanitizedContent;
|
if (isReplyOrForward) {
|
||||||
|
console.log('Using special handling for reply/forward content');
|
||||||
|
|
||||||
|
// Clean up any problematic table structures, with special care for quoted content
|
||||||
|
const cleanedContent = cleanupTableStructures(sanitizedContent);
|
||||||
|
|
||||||
|
// Use direct innerHTML setting with minimal processing for reply/forward content
|
||||||
|
quillRef.current.root.innerHTML = cleanedContent;
|
||||||
|
} else {
|
||||||
|
// Use direct innerHTML setting for regular content
|
||||||
|
quillRef.current.root.innerHTML = sanitizedContent;
|
||||||
|
}
|
||||||
|
|
||||||
// Set the direction for the content
|
// Set the direction for the content
|
||||||
if (quillRef.current && quillRef.current.format) {
|
if (quillRef.current && quillRef.current.format) {
|
||||||
@ -319,8 +363,18 @@ const RichEmailEditor: React.FC<RichEmailEditorProps> = ({
|
|||||||
firstNChars: initialContent.substring(0, 100).replace(/\n/g, '\\n')
|
firstNChars: initialContent.substring(0, 100).replace(/\n/g, '\\n')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Check if content is reply or forward to use special handling
|
||||||
|
const isReplyOrForward =
|
||||||
|
initialContent.includes('wrote:') ||
|
||||||
|
initialContent.includes('<blockquote') ||
|
||||||
|
initialContent.includes('Forwarded message') ||
|
||||||
|
initialContent.includes('---------- Forwarded message ----------');
|
||||||
|
|
||||||
// Process HTML content using centralized utility
|
// Process HTML content using centralized utility
|
||||||
const processed = processHtmlContent(initialContent);
|
const processed = processHtmlContent(initialContent, {
|
||||||
|
sanitize: true,
|
||||||
|
preserveReplyFormat: isReplyOrForward
|
||||||
|
});
|
||||||
const sanitizedContent = processed.sanitizedContent;
|
const sanitizedContent = processed.sanitizedContent;
|
||||||
const direction = processed.direction; // Use direction from processed result
|
const direction = processed.direction; // Use direction from processed result
|
||||||
|
|
||||||
@ -333,6 +387,7 @@ const RichEmailEditor: React.FC<RichEmailEditorProps> = ({
|
|||||||
containsQuoteHeader: sanitizedContent.includes('wrote:'),
|
containsQuoteHeader: sanitizedContent.includes('wrote:'),
|
||||||
hasTable: sanitizedContent.includes('<table'),
|
hasTable: sanitizedContent.includes('<table'),
|
||||||
hasBlockquote: sanitizedContent.includes('<blockquote'),
|
hasBlockquote: sanitizedContent.includes('<blockquote'),
|
||||||
|
isReplyOrForward: isReplyOrForward,
|
||||||
firstNChars: sanitizedContent.substring(0, 100).replace(/\n/g, '\\n')
|
firstNChars: sanitizedContent.substring(0, 100).replace(/\n/g, '\\n')
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -351,11 +406,17 @@ const RichEmailEditor: React.FC<RichEmailEditorProps> = ({
|
|||||||
} else {
|
} else {
|
||||||
// SIMPLIFIED: Set content directly to the root element rather than using clipboard
|
// SIMPLIFIED: Set content directly to the root element rather than using clipboard
|
||||||
if (quillRef.current && quillRef.current.root) {
|
if (quillRef.current && quillRef.current.root) {
|
||||||
// Clean up any problematic table structures first
|
// Special handling for reply or forward content
|
||||||
const cleanedContent = cleanupTableStructures(sanitizedContent);
|
let contentToSet = sanitizedContent;
|
||||||
|
|
||||||
|
if (isReplyOrForward) {
|
||||||
|
console.log('Using special handling for reply/forward content update');
|
||||||
|
// Clean up tables with special care for quoted content
|
||||||
|
contentToSet = cleanupTableStructures(sanitizedContent);
|
||||||
|
}
|
||||||
|
|
||||||
// First set the content
|
// First set the content
|
||||||
quillRef.current.root.innerHTML = cleanedContent;
|
quillRef.current.root.innerHTML = contentToSet;
|
||||||
|
|
||||||
// Then safely apply formatting only if quillRef is valid
|
// Then safely apply formatting only if quillRef is valid
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -84,14 +84,23 @@ export const purify = configureDOMPurify();
|
|||||||
/**
|
/**
|
||||||
* Sanitize HTML content using our email-specific configuration
|
* Sanitize HTML content using our email-specific configuration
|
||||||
*/
|
*/
|
||||||
export function sanitizeHtml(content: string): string {
|
export function sanitizeHtml(content: string, options?: { preserveReplyFormat?: boolean }): string {
|
||||||
if (!content) return '';
|
if (!content) return '';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Sanitize with our configured instance
|
// Special handling for reply/forward emails to be less aggressive with sanitization
|
||||||
|
const extraTags = options?.preserveReplyFormat
|
||||||
|
? ['style', 'blockquote', 'table', 'thead', 'tbody', 'tr', 'td', 'th']
|
||||||
|
: ['style'];
|
||||||
|
|
||||||
|
const extraAttrs = options?.preserveReplyFormat
|
||||||
|
? ['style', 'class', 'align', 'valign', 'bgcolor', 'colspan', 'rowspan', 'width', 'height', 'border']
|
||||||
|
: ['style', 'class'];
|
||||||
|
|
||||||
|
// Sanitize with our configured instance and options
|
||||||
return purify.sanitize(content, {
|
return purify.sanitize(content, {
|
||||||
ADD_TAGS: ['style'], // Allow internal styles temporarily for cleaning
|
ADD_TAGS: extraTags,
|
||||||
ADD_ATTR: ['style', 'class'] // Allow style and class attributes
|
ADD_ATTR: extraAttrs
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to sanitize HTML content:', error);
|
console.error('Failed to sanitize HTML content:', error);
|
||||||
|
|||||||
@ -226,6 +226,7 @@ export function processHtmlContent(
|
|||||||
options?: {
|
options?: {
|
||||||
sanitize?: boolean;
|
sanitize?: boolean;
|
||||||
blockExternalContent?: boolean;
|
blockExternalContent?: boolean;
|
||||||
|
preserveReplyFormat?: boolean;
|
||||||
attachments?: Array<{
|
attachments?: Array<{
|
||||||
filename?: string;
|
filename?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
@ -252,6 +253,7 @@ export function processHtmlContent(
|
|||||||
containsForwardedMessage: htmlContent?.includes('---------- Forwarded message ----------'),
|
containsForwardedMessage: htmlContent?.includes('---------- Forwarded message ----------'),
|
||||||
containsQuoteHeader: htmlContent?.includes('<div class="gmail_quote"'),
|
containsQuoteHeader: htmlContent?.includes('<div class="gmail_quote"'),
|
||||||
sanitize: options?.sanitize,
|
sanitize: options?.sanitize,
|
||||||
|
preserveReplyFormat: options?.preserveReplyFormat,
|
||||||
blockExternalContent: options?.blockExternalContent,
|
blockExternalContent: options?.blockExternalContent,
|
||||||
hasAttachments: options?.attachments?.length || 0
|
hasAttachments: options?.attachments?.length || 0
|
||||||
});
|
});
|
||||||
@ -275,8 +277,13 @@ export function processHtmlContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Special handling for reply/forwarded content with less aggressive sanitization
|
||||||
|
const isReplyOrForward = options?.preserveReplyFormat === true;
|
||||||
|
|
||||||
// Apply sanitization by default unless explicitly turned off
|
// Apply sanitization by default unless explicitly turned off
|
||||||
let sanitizedContent = (options?.sanitize !== false) ? sanitizeHtml(htmlContent) : htmlContent;
|
let sanitizedContent = (options?.sanitize !== false)
|
||||||
|
? sanitizeHtml(htmlContent, { preserveReplyFormat: isReplyOrForward })
|
||||||
|
: htmlContent;
|
||||||
|
|
||||||
// Log content changes from sanitization
|
// Log content changes from sanitization
|
||||||
console.log('HTML sanitization results:', {
|
console.log('HTML sanitization results:', {
|
||||||
@ -284,10 +291,11 @@ export function processHtmlContent(
|
|||||||
sanitizedLength: sanitizedContent.length,
|
sanitizedLength: sanitizedContent.length,
|
||||||
difference: originalContent.length - sanitizedContent.length,
|
difference: originalContent.length - sanitizedContent.length,
|
||||||
percentRemoved: ((originalContent.length - sanitizedContent.length) / originalContent.length * 100).toFixed(2) + '%',
|
percentRemoved: ((originalContent.length - sanitizedContent.length) / originalContent.length * 100).toFixed(2) + '%',
|
||||||
isEmpty: !sanitizedContent || sanitizedContent.trim().length === 0
|
isEmpty: !sanitizedContent || sanitizedContent.trim().length === 0,
|
||||||
|
isReplyOrForward: isReplyOrForward
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check if content is a forwarded message to ensure special handling for tables
|
// Detect if content is a forwarded message to ensure special handling for tables
|
||||||
const isForwardedEmail =
|
const isForwardedEmail =
|
||||||
sanitizedContent.includes('---------- Forwarded message ----------') ||
|
sanitizedContent.includes('---------- Forwarded message ----------') ||
|
||||||
sanitizedContent.includes('Forwarded message') ||
|
sanitizedContent.includes('Forwarded message') ||
|
||||||
@ -295,8 +303,8 @@ export function processHtmlContent(
|
|||||||
sanitizedContent.includes('Subject:') && sanitizedContent.includes('To:'));
|
sanitizedContent.includes('Subject:') && sanitizedContent.includes('To:'));
|
||||||
|
|
||||||
// Special processing for forwarded email styling
|
// Special processing for forwarded email styling
|
||||||
if (isForwardedEmail) {
|
if (isForwardedEmail || isReplyOrForward) {
|
||||||
console.log('Detected forwarded email content, preserving table structure');
|
console.log('Detected forwarded email or reply content, enhancing structure');
|
||||||
// Make sure we're not removing important table structures
|
// Make sure we're not removing important table structures
|
||||||
sanitizedContent = sanitizedContent
|
sanitizedContent = sanitizedContent
|
||||||
// Preserve table styling for email headers
|
// Preserve table styling for email headers
|
||||||
|
|||||||
@ -324,14 +324,26 @@ export function formatReplyEmail(originalEmail: EmailMessage | LegacyEmailMessag
|
|||||||
|
|
||||||
// Create the quoted reply content
|
// Create the quoted reply content
|
||||||
if (htmlContent) {
|
if (htmlContent) {
|
||||||
// Format HTML reply
|
// Format HTML reply with better styling for quoted content
|
||||||
console.log('Formatting HTML reply, quoted content length:', htmlContent.length);
|
console.log('Formatting HTML reply, quoted content length:', htmlContent.length);
|
||||||
|
|
||||||
|
// Apply minimal sanitization to the original content - preserve more structure
|
||||||
|
// We'll do a more comprehensive sanitization later in the flow
|
||||||
|
const sanitizedOriginal = sanitizeHtml(htmlContent, { preserveReplyFormat: true });
|
||||||
|
|
||||||
|
// Check if original content already contains blockquotes or is reply/forward
|
||||||
|
const containsExistingQuote =
|
||||||
|
sanitizedOriginal.includes('<blockquote') ||
|
||||||
|
sanitizedOriginal.includes('wrote:') ||
|
||||||
|
sanitizedOriginal.includes('---------- Forwarded message ----------');
|
||||||
|
|
||||||
|
// Preserve existing quotes and add outer quote
|
||||||
htmlContent = `
|
htmlContent = `
|
||||||
<div style="margin: 20px 0 10px 0; color: #666; border-bottom: 1px solid #ddd; padding-bottom: 5px;">
|
<div style="margin: 20px 0 10px 0; color: #666; border-bottom: 1px solid #ddd; padding-bottom: 5px;">
|
||||||
On ${date}, ${sender} wrote:
|
On ${date}, ${sender} wrote:
|
||||||
</div>
|
</div>
|
||||||
<blockquote style="margin: 0; padding-left: 10px; border-left: 3px solid #ddd; color: #505050; background-color: #f9f9f9; padding: 10px;">
|
<blockquote style="margin: 0; padding-left: 10px; border-left: 3px solid #ddd; color: #505050; background-color: #f9f9f9; padding: 10px;">
|
||||||
${sanitizeHtml(htmlContent)}
|
${sanitizedOriginal}
|
||||||
</blockquote>
|
</blockquote>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -477,7 +489,7 @@ export function processCidReferences(htmlContent: string, attachments?: Array<{
|
|||||||
* Format email for forwarding
|
* Format email for forwarding
|
||||||
*/
|
*/
|
||||||
export function formatForwardedEmail(originalEmail: EmailMessage | LegacyEmailMessage | null): FormattedEmail {
|
export function formatForwardedEmail(originalEmail: EmailMessage | LegacyEmailMessage | null): FormattedEmail {
|
||||||
console.log('formatForwardedEmail called:', { emailId: originalEmail?.id });
|
console.log('formatForwardedEmail called, emailId:', originalEmail?.id);
|
||||||
|
|
||||||
if (!originalEmail) {
|
if (!originalEmail) {
|
||||||
console.warn('formatForwardedEmail: No original email provided');
|
console.warn('formatForwardedEmail: No original email provided');
|
||||||
@ -496,14 +508,6 @@ export function formatForwardedEmail(originalEmail: EmailMessage | LegacyEmailMe
|
|||||||
(email.subject.toLowerCase().startsWith('fwd:') ? email.subject : `Fwd: ${email.subject}`) :
|
(email.subject.toLowerCase().startsWith('fwd:') ? email.subject : `Fwd: ${email.subject}`) :
|
||||||
'Fwd: ';
|
'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
|
// Get email content
|
||||||
const originalContent = email.content;
|
const originalContent = email.content;
|
||||||
|
|
||||||
@ -544,75 +548,66 @@ export function formatForwardedEmail(originalEmail: EmailMessage | LegacyEmailMe
|
|||||||
htmlContent = formatPlainTextToHtml(textContent);
|
htmlContent = formatPlainTextToHtml(textContent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process embedded images with CID references
|
// Get header info for the forwarded message
|
||||||
if (htmlContent && email.attachments && email.attachments.length > 0) {
|
const headerInfo = getFormattedHeaderInfo(email);
|
||||||
console.log('Processing CID references before sanitization');
|
|
||||||
htmlContent = processCidReferences(htmlContent, email.attachments);
|
// Create the forwarded content
|
||||||
}
|
|
||||||
|
|
||||||
// Create the forwarded email HTML content
|
|
||||||
if (htmlContent) {
|
if (htmlContent) {
|
||||||
console.log('Formatting HTML forward, original content length:', htmlContent.length);
|
console.log('Formatting HTML forward, content length:', htmlContent.length);
|
||||||
|
|
||||||
// Important: First sanitize the content portion only
|
// Apply minimal sanitization to the original content - preserve more structure
|
||||||
const sanitizedOriginalContent = sanitizeHtml(htmlContent);
|
// We'll do a more comprehensive sanitization later in the flow
|
||||||
console.log('Sanitized original content length:', sanitizedOriginalContent.length);
|
const sanitizedOriginal = sanitizeHtml(htmlContent, { preserveReplyFormat: true });
|
||||||
|
|
||||||
// Create the complete forwarded email with header info
|
// Create forwarded message with header info
|
||||||
const fullForwardedEmail = `
|
htmlContent = `
|
||||||
<div style="margin: 20px 0 10px 0; color: #666; font-family: Arial, sans-serif;">
|
<div style="margin: 20px 0 10px 0; color: #666; font-family: Arial, sans-serif;">
|
||||||
---------- Forwarded message ----------<br>
|
<div style="border-bottom: 1px solid #ccc; margin-bottom: 10px; padding-bottom: 5px;">
|
||||||
<table style="margin: 10px 0 15px 0; border-collapse: collapse; font-size: 13px; color: #333;">
|
<div>---------------------------- Forwarded Message ----------------------------</div>
|
||||||
<tbody>
|
</div>
|
||||||
<tr>
|
<table style="margin-bottom: 10px; font-size: 14px; border-collapse: collapse;">
|
||||||
<td style="padding: 3px 10px 3px 0; font-weight: bold; text-align: right; vertical-align: top;">From:</td>
|
<tr>
|
||||||
<td style="padding: 3px 0;">${fromStr}</td>
|
<td style="padding: 3px 10px 3px 0; font-weight: bold; text-align: right; vertical-align: top;">From:</td>
|
||||||
</tr>
|
<td style="padding: 3px 0;">${headerInfo.fromStr}</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td style="padding: 3px 10px 3px 0; font-weight: bold; text-align: right; vertical-align: top;">Date:</td>
|
<tr>
|
||||||
<td style="padding: 3px 0;">${date}</td>
|
<td style="padding: 3px 10px 3px 0; font-weight: bold; text-align: right; vertical-align: top;">Date:</td>
|
||||||
</tr>
|
<td style="padding: 3px 0;">${headerInfo.dateStr}</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td style="padding: 3px 10px 3px 0; font-weight: bold; text-align: right; vertical-align: top;">Subject:</td>
|
<tr>
|
||||||
<td style="padding: 3px 0;">${email.subject || ''}</td>
|
<td style="padding: 3px 10px 3px 0; font-weight: bold; text-align: right; vertical-align: top;">Subject:</td>
|
||||||
</tr>
|
<td style="padding: 3px 0;">${headerInfo.subject}</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td style="padding: 3px 10px 3px 0; font-weight: bold; text-align: right; vertical-align: top;">To:</td>
|
<tr>
|
||||||
<td style="padding: 3px 0;">${toStr}</td>
|
<td style="padding: 3px 10px 3px 0; font-weight: bold; text-align: right; vertical-align: top;">To:</td>
|
||||||
</tr>
|
<td style="padding: 3px 0;">${headerInfo.toStr}</td>
|
||||||
${ccStr ? `
|
</tr>
|
||||||
<tr>
|
${headerInfo.ccStr ? `
|
||||||
<td style="padding: 3px 10px 3px 0; font-weight: bold; text-align: right; vertical-align: top;">Cc:</td>
|
<tr>
|
||||||
<td style="padding: 3px 0;">${ccStr}</td>
|
<td style="padding: 3px 10px 3px 0; font-weight: bold; text-align: right; vertical-align: top;">Cc:</td>
|
||||||
</tr>
|
<td style="padding: 3px 0;">${headerInfo.ccStr}</td>
|
||||||
` : ''}
|
</tr>` : ''}
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
|
<div style="border-bottom: 1px solid #ccc; margin-top: 5px; margin-bottom: 15px; padding-bottom: 5px;">
|
||||||
|
<div>----------------------------------------------------------------------</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="forwarded-content" style="margin: 0; color: #333;">
|
||||||
|
${sanitizedOriginal}
|
||||||
</div>
|
</div>
|
||||||
<blockquote style="margin: 0; padding-left: 10px; border-left: 3px solid #ddd; color: #505050; background-color: #f9f9f9; padding: 10px;">
|
|
||||||
${sanitizedOriginalContent}
|
|
||||||
</blockquote>
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Now we have the full forwarded email structure without sanitizing it again
|
|
||||||
htmlContent = fullForwardedEmail;
|
|
||||||
|
|
||||||
console.log('Final forward HTML content length:', htmlContent.length,
|
|
||||||
'contains table:', htmlContent.includes('<table'),
|
|
||||||
'contains forwarded message:', htmlContent.includes('---------- Forwarded message ----------'),
|
|
||||||
'contains sanitized content:', htmlContent.includes(sanitizedOriginalContent.substring(0, 30)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format the plain text version
|
|
||||||
if (textContent) {
|
if (textContent) {
|
||||||
|
// Format plain text forward
|
||||||
textContent = `
|
textContent = `
|
||||||
---------- Forwarded message ----------
|
---------- Forwarded message ----------
|
||||||
From: ${fromStr}
|
From: ${headerInfo.fromStr}
|
||||||
Date: ${date}
|
Date: ${headerInfo.dateStr}
|
||||||
Subject: ${email.subject || ''}
|
Subject: ${headerInfo.subject}
|
||||||
To: ${toStr}
|
To: ${headerInfo.toStr}
|
||||||
${ccStr ? `Cc: ${ccStr}\n` : ''}
|
${headerInfo.ccStr ? `Cc: ${headerInfo.ccStr}` : ''}
|
||||||
|
|
||||||
${textContent}
|
${textContent}
|
||||||
`.trim();
|
`.trim();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user