courrier preview
This commit is contained in:
parent
193a265109
commit
d88fc133d2
@ -352,7 +352,13 @@ export default function ComposeEmail(props: ComposeEmailProps) {
|
|||||||
ref={editorRef}
|
ref={editorRef}
|
||||||
initialContent={emailContent}
|
initialContent={emailContent}
|
||||||
initialDirection={detectTextDirection(emailContent)}
|
initialDirection={detectTextDirection(emailContent)}
|
||||||
onChange={setEmailContent}
|
onChange={(html) => {
|
||||||
|
// Store the content
|
||||||
|
setEmailContent(html);
|
||||||
|
|
||||||
|
// But don't update direction on every keystroke
|
||||||
|
// The RichTextEditor will handle direction changes internally
|
||||||
|
}}
|
||||||
className="min-h-[320px] border rounded-md bg-white text-gray-800 flex-1"
|
className="min-h-[320px] border rounded-md bg-white text-gray-800 flex-1"
|
||||||
placeholder="Write your message here..."
|
placeholder="Write your message here..."
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { EmailContent } from '@/types/email';
|
import { EmailContent } from '@/types/email';
|
||||||
import { detectTextDirection } from '@/lib/utils/text-direction';
|
import { detectTextDirection, applyTextDirection } from '@/lib/utils/text-direction';
|
||||||
import DOMPurify from 'isomorphic-dompurify';
|
import DOMPurify from 'isomorphic-dompurify';
|
||||||
|
|
||||||
interface EmailContentDisplayProps {
|
interface EmailContentDisplayProps {
|
||||||
@ -94,13 +94,16 @@ const EmailContentDisplay: React.FC<EmailContentDisplayProps> = ({
|
|||||||
return htmlToDisplay;
|
return htmlToDisplay;
|
||||||
}, [htmlToDisplay, showQuotedText]);
|
}, [htmlToDisplay, showQuotedText]);
|
||||||
|
|
||||||
// Sanitize HTML content before rendering
|
// Sanitize HTML content and apply proper direction
|
||||||
const sanitizedHTML = useMemo(() => {
|
const sanitizedHTML = useMemo(() => {
|
||||||
return DOMPurify.sanitize(processedHTML);
|
const clean = DOMPurify.sanitize(processedHTML);
|
||||||
}, [processedHTML]);
|
|
||||||
|
// Apply text direction consistently using our utility
|
||||||
|
return applyTextDirection(clean, safeContent.text);
|
||||||
|
}, [processedHTML, safeContent.text]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`email-content-display ${className}`} dir={safeContent.direction}>
|
<div className={`email-content-display ${className}`}>
|
||||||
<div
|
<div
|
||||||
className="email-content-inner"
|
className="email-content-inner"
|
||||||
dangerouslySetInnerHTML={{ __html: sanitizedHTML }}
|
dangerouslySetInnerHTML={{ __html: sanitizedHTML }}
|
||||||
@ -121,10 +124,6 @@ const EmailContentDisplay: React.FC<EmailContentDisplayProps> = ({
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.email-content-display[dir="rtl"] {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.email-content-inner img {
|
.email-content-inner img {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
@ -139,7 +138,8 @@ const EmailContentDisplay: React.FC<EmailContentDisplayProps> = ({
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.email-content-display[dir="rtl"] .email-content-inner blockquote {
|
/* RTL blockquote styling will be handled by the direction attribute now */
|
||||||
|
[dir="rtl"] blockquote {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
border-left: none;
|
border-left: none;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { EmailMessage, EmailContent, EmailAddress, LegacyEmailMessage } from '@/types/email';
|
import { EmailMessage, EmailContent, EmailAddress, LegacyEmailMessage } from '@/types/email';
|
||||||
import { sanitizeHtml } from './email-utils';
|
import { sanitizeHtml } from './email-utils';
|
||||||
|
import { detectTextDirection } from './text-direction';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapts a legacy email format to the standardized EmailMessage format
|
* Adapts a legacy email format to the standardized EmailMessage format
|
||||||
@ -224,17 +225,7 @@ function normalizeContent(email: LegacyEmailMessage): EmailContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detects the text direction (LTR or RTL) based on the content
|
* Normalizes addresses to EmailAddress objects
|
||||||
*/
|
|
||||||
function detectTextDirection(text: string): 'ltr' | 'rtl' {
|
|
||||||
// Simple RTL detection for common RTL languages
|
|
||||||
// This is a basic implementation and can be enhanced
|
|
||||||
const rtlChars = /[\u0591-\u07FF\u200F\u202B\u202E\uFB1D-\uFDFD\uFE70-\uFEFC]/;
|
|
||||||
return rtlChars.test(text) ? 'rtl' : 'ltr';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalizes email addresses to the EmailAddress format
|
|
||||||
*/
|
*/
|
||||||
function normalizeAddresses(addresses: string | EmailAddress[] | undefined): EmailAddress[] {
|
function normalizeAddresses(addresses: string | EmailAddress[] | undefined): EmailAddress[] {
|
||||||
if (!addresses) {
|
if (!addresses) {
|
||||||
|
|||||||
@ -9,6 +9,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import DOMPurify from 'isomorphic-dompurify';
|
import DOMPurify from 'isomorphic-dompurify';
|
||||||
|
import { sanitizeHtml } from './email-utils';
|
||||||
|
import { applyTextDirection } from './text-direction';
|
||||||
// Instead of importing, implement the formatDateRelative function directly
|
// Instead of importing, implement the formatDateRelative function directly
|
||||||
// import { formatDateRelative } from './date-formatter';
|
// import { formatDateRelative } from './date-formatter';
|
||||||
|
|
||||||
@ -133,59 +135,6 @@ export function formatEmailDate(date: Date | string | undefined): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sanitize HTML content before processing or displaying
|
|
||||||
* Implements email industry standards for proper, consistent, and secure rendering
|
|
||||||
*
|
|
||||||
* @param html HTML content to sanitize
|
|
||||||
* @returns Sanitized HTML with preserved styling and structure
|
|
||||||
*/
|
|
||||||
export function sanitizeHtml(html: string): string {
|
|
||||||
if (!html) return '';
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Use DOMPurify with comprehensive email HTML standards
|
|
||||||
const clean = DOMPurify.sanitize(html, {
|
|
||||||
ADD_TAGS: [
|
|
||||||
'html', 'head', 'body', 'style', 'link', 'meta', 'title',
|
|
||||||
'table', 'caption', 'col', 'colgroup', 'thead', 'tbody', 'tfoot', 'tr', 'td', 'th',
|
|
||||||
'div', 'span', 'img', 'br', 'hr', 'section', 'article', 'header', 'footer',
|
|
||||||
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'blockquote', 'pre', 'code',
|
|
||||||
'ul', 'ol', 'li', 'dl', 'dt', 'dd', 'a', 'b', 'i', 'u', 'em',
|
|
||||||
'strong', 'del', 'ins', 'mark', 'small', 'sub', 'sup', 'q', 'abbr'
|
|
||||||
],
|
|
||||||
ADD_ATTR: [
|
|
||||||
'style', 'class', 'id', 'name', 'href', 'src', 'alt', 'title', 'width', 'height',
|
|
||||||
'border', 'cellspacing', 'cellpadding', 'bgcolor', 'background', 'color',
|
|
||||||
'align', 'valign', 'dir', 'lang', 'target', 'rel', 'charset', 'media',
|
|
||||||
'colspan', 'rowspan', 'scope', 'span', 'size', 'face', 'hspace', 'vspace',
|
|
||||||
'data-*'
|
|
||||||
],
|
|
||||||
KEEP_CONTENT: true,
|
|
||||||
WHOLE_DOCUMENT: false,
|
|
||||||
ALLOW_DATA_ATTR: true,
|
|
||||||
ALLOW_UNKNOWN_PROTOCOLS: true, // Needed for some email clients
|
|
||||||
FORBID_TAGS: ['script', 'iframe', 'object', 'embed', 'form', 'input', 'button', 'select', 'textarea'],
|
|
||||||
FORBID_ATTR: ['onerror', 'onload', 'onclick', 'onmouseover', 'onmouseout'],
|
|
||||||
FORCE_BODY: false
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fix common email rendering issues
|
|
||||||
return clean
|
|
||||||
// Fix for Outlook WebVML content
|
|
||||||
.replace(/<!--\[if\s+gte\s+mso/g, '<!--[if gte mso')
|
|
||||||
// Fix for broken image paths that might be relative
|
|
||||||
.replace(/(src|background)="(?!http|data|https|cid)/gi, '$1="https://');
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Error sanitizing HTML:', e);
|
|
||||||
// Fall back to a basic sanitization approach
|
|
||||||
return html
|
|
||||||
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
|
|
||||||
.replace(/on\w+="[^"]*"/g, '')
|
|
||||||
.replace(/(javascript|jscript|vbscript|mocha):/gi, 'removed:');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format an email for forwarding - CENTRAL IMPLEMENTATION
|
* Format an email for forwarding - CENTRAL IMPLEMENTATION
|
||||||
* All other formatting functions should be deprecated in favor of this one
|
* All other formatting functions should be deprecated in favor of this one
|
||||||
@ -423,46 +372,58 @@ export function encodeComposeContent(content: string): string {
|
|||||||
.join('\n') + '\n\n' + content;
|
.join('\n') + '\n\n' + content;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Legacy email formatter functions - renamed to avoid conflicts
|
/**
|
||||||
|
* COMPATIBILITY LAYER: For backward compatibility with the old email-formatter.ts
|
||||||
|
* Use the newer formatReplyEmail function instead when possible.
|
||||||
|
*
|
||||||
|
* @deprecated Use formatReplyEmail instead
|
||||||
|
*/
|
||||||
export function formatReplyEmailLegacy(email: any): string {
|
export function formatReplyEmailLegacy(email: any): string {
|
||||||
const originalSender = email.sender?.name || email.sender?.email || 'Unknown Sender';
|
|
||||||
const originalDate = formatDateRelative(new Date(email.date));
|
|
||||||
|
|
||||||
// Use our own sanitizeHtml function consistently
|
// Use our own sanitizeHtml function consistently
|
||||||
const sanitizedBody = sanitizeHtml(email.content || '');
|
const sanitizedBody = sanitizeHtml(email.content || '');
|
||||||
|
|
||||||
return `
|
// Format the reply with consistent direction handling
|
||||||
<p></p>
|
const replyContent = `
|
||||||
<p>On ${originalDate}, ${originalSender} wrote:</p>
|
<br/>
|
||||||
<blockquote class="quoted-content">
|
<br/>
|
||||||
|
<blockquote>
|
||||||
|
On ${email.date}, ${email.from} wrote:
|
||||||
|
<br/>
|
||||||
${sanitizedBody}
|
${sanitizedBody}
|
||||||
</blockquote>
|
</blockquote>
|
||||||
`.trim();
|
`;
|
||||||
|
|
||||||
|
// Apply consistent text direction
|
||||||
|
return applyTextDirection(replyContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COMPATIBILITY LAYER: For backward compatibility with the old email-formatter.ts
|
||||||
|
* Use the newer formatForwardedEmail function instead when possible.
|
||||||
|
*
|
||||||
|
* @deprecated Use formatForwardedEmail instead
|
||||||
|
*/
|
||||||
export function formatForwardedEmailLegacy(email: any): string {
|
export function formatForwardedEmailLegacy(email: any): string {
|
||||||
const originalSender = email.sender?.name || email.sender?.email || 'Unknown Sender';
|
|
||||||
const originalRecipients = email.to?.map((recipient: any) =>
|
|
||||||
recipient.name || recipient.email
|
|
||||||
).join(', ') || 'Unknown Recipients';
|
|
||||||
const originalDate = formatDateRelative(new Date(email.date));
|
|
||||||
const originalSubject = email.subject || 'No Subject';
|
|
||||||
|
|
||||||
// Use our own sanitizeHtml function consistently
|
// Use our own sanitizeHtml function consistently
|
||||||
const sanitizedBody = sanitizeHtml(email.content || '');
|
const sanitizedBody = sanitizeHtml(email.content || '');
|
||||||
|
|
||||||
return `
|
// Format the forwarded content with consistent direction handling
|
||||||
<p></p>
|
const forwardedContent = `
|
||||||
<p>---------- Forwarded message ---------</p>
|
<br/>
|
||||||
<p><strong>From:</strong> ${originalSender}</p>
|
<br/>
|
||||||
<p><strong>Date:</strong> ${originalDate}</p>
|
<div>
|
||||||
<p><strong>Subject:</strong> ${originalSubject}</p>
|
---------- Forwarded message ---------<br/>
|
||||||
<p><strong>To:</strong> ${originalRecipients}</p>
|
From: ${email.from}<br/>
|
||||||
<br>
|
Date: ${email.date}<br/>
|
||||||
<div class="email-original-content">
|
Subject: ${email.subject}<br/>
|
||||||
|
To: ${email.to}<br/>
|
||||||
|
<br/>
|
||||||
${sanitizedBody}
|
${sanitizedBody}
|
||||||
</div>
|
</div>
|
||||||
`.trim();
|
`;
|
||||||
|
|
||||||
|
// Apply consistent text direction
|
||||||
|
return applyTextDirection(forwardedContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatReplyToAllEmail(email: any): string {
|
export function formatReplyToAllEmail(email: any): string {
|
||||||
|
|||||||
@ -17,21 +17,12 @@ import {
|
|||||||
} from '@/types/email';
|
} from '@/types/email';
|
||||||
import { adaptLegacyEmail } from '@/lib/utils/email-adapters';
|
import { adaptLegacyEmail } from '@/lib/utils/email-adapters';
|
||||||
import { decodeInfomaniakEmail, adaptMimeEmail, isMimeFormat } from './email-mime-decoder';
|
import { decodeInfomaniakEmail, adaptMimeEmail, isMimeFormat } from './email-mime-decoder';
|
||||||
import { detectTextDirection } from '@/lib/utils/text-direction';
|
import { detectTextDirection, applyTextDirection } from '@/lib/utils/text-direction';
|
||||||
|
|
||||||
// Reset any existing hooks to start clean
|
// Reset any existing hooks to start clean
|
||||||
DOMPurify.removeAllHooks();
|
DOMPurify.removeAllHooks();
|
||||||
|
|
||||||
// Configure DOMPurify for auto text direction
|
// Remove the hook that adds dir="auto" - we'll handle direction explicitly instead
|
||||||
DOMPurify.addHook('afterSanitizeAttributes', function(node) {
|
|
||||||
if (node instanceof HTMLElement) {
|
|
||||||
// Only set direction if not already specified
|
|
||||||
if (!node.hasAttribute('dir')) {
|
|
||||||
// Add dir attribute only if not present
|
|
||||||
node.setAttribute('dir', 'auto');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Configure DOMPurify to preserve direction attributes
|
// Configure DOMPurify to preserve direction attributes
|
||||||
DOMPurify.setConfig({
|
DOMPurify.setConfig({
|
||||||
@ -119,11 +110,14 @@ export function sanitizeHtml(html: string): string {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Fix common email rendering issues
|
// Fix common email rendering issues
|
||||||
return clean
|
const fixedHtml = clean
|
||||||
// Fix for Outlook WebVML content
|
// Fix for Outlook WebVML content
|
||||||
.replace(/<!--\[if\s+gte\s+mso/g, '<!--[if gte mso')
|
.replace(/<!--\[if\s+gte\s+mso/g, '<!--[if gte mso')
|
||||||
// Fix for broken image paths that might be relative
|
// Fix for broken image paths that might be relative
|
||||||
.replace(/(src|background)="(?!http|data|https|cid)/gi, '$1="https://');
|
.replace(/(src|background)="(?!http|data|https|cid)/gi, '$1="https://');
|
||||||
|
|
||||||
|
// We don't manually add direction here anymore - applyTextDirection will handle it
|
||||||
|
return fixedHtml;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error sanitizing HTML:', e);
|
console.error('Error sanitizing HTML:', e);
|
||||||
// Fall back to a basic sanitization approach
|
// Fall back to a basic sanitization approach
|
||||||
@ -190,30 +184,34 @@ export function normalizeEmailContent(email: any): EmailMessage {
|
|||||||
/**
|
/**
|
||||||
* Render normalized email content into HTML for display
|
* Render normalized email content into HTML for display
|
||||||
*/
|
*/
|
||||||
export function renderEmailContent(content: EmailContent): string {
|
export function renderEmailContent(content: EmailContent | null): string {
|
||||||
console.log('renderEmailContent received:', JSON.stringify(content, null, 2));
|
|
||||||
|
|
||||||
if (!content) {
|
if (!content) {
|
||||||
console.log('No content provided to renderEmailContent');
|
|
||||||
return '<div class="email-content-empty">No content available</div>';
|
return '<div class="email-content-empty">No content available</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const safeContent = {
|
||||||
|
text: content.text || '',
|
||||||
|
html: content.html,
|
||||||
|
isHtml: content.isHtml,
|
||||||
|
direction: content.direction || 'ltr'
|
||||||
|
};
|
||||||
|
|
||||||
// If we have HTML content and isHtml flag is true, use it
|
// If we have HTML content and isHtml flag is true, use it
|
||||||
if (content.isHtml && content.html) {
|
if (safeContent.isHtml && safeContent.html) {
|
||||||
console.log('Rendering HTML content, length:', content.html.length);
|
// Apply text direction consistently using the utility
|
||||||
return `<div class="email-content" dir="${content.direction || 'ltr'}">${content.html}</div>`;
|
return applyTextDirection(safeContent.html, safeContent.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, format the text content with basic HTML
|
// Otherwise, format the text content with basic HTML
|
||||||
const text = content.text || '';
|
const text = safeContent.text;
|
||||||
console.log('Rendering text content, length:', text.length);
|
|
||||||
const formattedText = text
|
const formattedText = text
|
||||||
.replace(/&/g, '&')
|
.replace(/&/g, '&')
|
||||||
.replace(/</g, '<')
|
.replace(/</g, '<')
|
||||||
.replace(/>/g, '>')
|
.replace(/>/g, '>')
|
||||||
.replace(/\n/g, '<br>');
|
.replace(/\n/g, '<br>');
|
||||||
|
|
||||||
return `<div class="email-content plain-text" dir="${content.direction || 'ltr'}">${formattedText}</div>`;
|
// Apply text direction consistently
|
||||||
|
return applyTextDirection(formattedText, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add interface for email formatting functions
|
// Add interface for email formatting functions
|
||||||
@ -305,33 +303,35 @@ export function formatReplyEmail(originalEmail: EmailMessage | LegacyEmailMessag
|
|||||||
|
|
||||||
// Extract original content
|
// Extract original content
|
||||||
const originalTextContent =
|
const originalTextContent =
|
||||||
originalEmail.content?.text ||
|
typeof originalEmail?.content === 'object' ? originalEmail.content.text :
|
||||||
(typeof originalEmail.content === 'string' ? originalEmail.content : '');
|
typeof originalEmail?.content === 'string' ? originalEmail.content :
|
||||||
|
originalEmail?.text || '';
|
||||||
|
|
||||||
const originalHtmlContent =
|
const originalHtmlContent =
|
||||||
originalEmail.content?.html ||
|
typeof originalEmail?.content === 'object' ? originalEmail.content.html :
|
||||||
originalEmail.html ||
|
originalEmail?.html ||
|
||||||
(typeof originalEmail.content === 'string' && originalEmail.content.includes('<')
|
(typeof originalEmail?.content === 'string' && originalEmail?.content.includes('<')
|
||||||
? originalEmail.content
|
? originalEmail.content
|
||||||
: '');
|
: '');
|
||||||
|
|
||||||
// Get the direction from the original email
|
// Get the direction from the original email
|
||||||
const originalDirection =
|
const originalDirection =
|
||||||
originalEmail.content?.direction ||
|
typeof originalEmail?.content === 'object' ? originalEmail.content.direction :
|
||||||
(originalTextContent ? detectTextDirection(originalTextContent) : 'ltr');
|
detectTextDirection(originalTextContent);
|
||||||
|
|
||||||
// Create HTML content that preserves the directionality
|
// Create content with appropriate quote formatting
|
||||||
const htmlContent = `
|
const replyBody = `
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
<div class="email-original-content" dir="${originalDirection}">
|
|
||||||
<blockquote style="border-left: 2px solid #ddd; padding-left: 10px; margin: 10px 0; color: #505050;">
|
<blockquote style="border-left: 2px solid #ddd; padding-left: 10px; margin: 10px 0; color: #505050;">
|
||||||
<p>On ${dateStr}, ${fromStr} wrote:</p>
|
<p>On ${dateStr}, ${fromStr} wrote:</p>
|
||||||
${originalHtmlContent || originalTextContent.replace(/\n/g, '<br>')}
|
${originalHtmlContent || originalTextContent.replace(/\n/g, '<br>')}
|
||||||
</blockquote>
|
</blockquote>
|
||||||
</div>
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
// Apply consistent text direction
|
||||||
|
const htmlContent = applyTextDirection(replyBody);
|
||||||
|
|
||||||
// Create plain text content
|
// Create plain text content
|
||||||
const textContent = `
|
const textContent = `
|
||||||
|
|
||||||
@ -406,45 +406,49 @@ export function formatForwardedEmail(originalEmail: EmailMessage | LegacyEmailMe
|
|||||||
|
|
||||||
// Extract original content
|
// Extract original content
|
||||||
const originalTextContent =
|
const originalTextContent =
|
||||||
originalEmail.content?.text ||
|
typeof originalEmail?.content === 'object' ? originalEmail.content.text :
|
||||||
(typeof originalEmail.content === 'string' ? originalEmail.content : '');
|
typeof originalEmail?.content === 'string' ? originalEmail.content :
|
||||||
|
originalEmail?.text || '';
|
||||||
|
|
||||||
const originalHtmlContent =
|
const originalHtmlContent =
|
||||||
originalEmail.content?.html ||
|
typeof originalEmail?.content === 'object' ? originalEmail.content.html :
|
||||||
originalEmail.html ||
|
originalEmail?.html ||
|
||||||
(typeof originalEmail.content === 'string' && originalEmail.content.includes('<')
|
(typeof originalEmail?.content === 'string' && originalEmail?.content.includes('<')
|
||||||
? originalEmail.content
|
? originalEmail.content
|
||||||
: '');
|
: '');
|
||||||
|
|
||||||
// Get the direction from the original email
|
// Get the direction from the original email
|
||||||
const originalDirection =
|
const originalDirection =
|
||||||
originalEmail.content?.direction ||
|
typeof originalEmail?.content === 'object' ? originalEmail.content.direction :
|
||||||
(originalTextContent ? detectTextDirection(originalTextContent) : 'ltr');
|
detectTextDirection(originalTextContent);
|
||||||
|
|
||||||
// Create HTML content that preserves the directionality
|
// Create forwarded content with header information
|
||||||
const htmlContent = `
|
const forwardBody = `
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
<div class="email-forwarded-content">
|
<div class="email-forwarded-content">
|
||||||
<p>---------- Forwarded message ---------</p>
|
<p>---------- Forwarded message ---------</p>
|
||||||
<p><strong>From:</strong> ${fromStr}</p>
|
<p><strong>From:</strong> ${fromStr}</p>
|
||||||
<p><strong>Date:</strong> ${dateStr}</p>
|
<p><strong>Date:</strong> ${dateStr}</p>
|
||||||
<p><strong>Subject:</strong> ${originalEmail.subject || ''}</p>
|
<p><strong>Subject:</strong> ${originalEmail?.subject || ''}</p>
|
||||||
<p><strong>To:</strong> ${toStr}</p>
|
<p><strong>To:</strong> ${toStr}</p>
|
||||||
${ccStr ? `<p><strong>Cc:</strong> ${ccStr}</p>` : ''}
|
${ccStr ? `<p><strong>Cc:</strong> ${ccStr}</p>` : ''}
|
||||||
<div style="margin-top: 15px; border-top: 1px solid #eee; padding-top: 15px;" dir="${originalDirection}">
|
<div style="margin-top: 15px; border-top: 1px solid #eee; padding-top: 15px;">
|
||||||
${originalHtmlContent || originalTextContent.replace(/\n/g, '<br>')}
|
${originalHtmlContent || originalTextContent.replace(/\n/g, '<br>')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
// Apply consistent text direction
|
||||||
|
const htmlContent = applyTextDirection(forwardBody);
|
||||||
|
|
||||||
// Create plain text content
|
// Create plain text content
|
||||||
const textContent = `
|
const textContent = `
|
||||||
|
|
||||||
---------- Forwarded message ---------
|
---------- Forwarded message ---------
|
||||||
From: ${fromStr}
|
From: ${fromStr}
|
||||||
Date: ${dateStr}
|
Date: ${dateStr}
|
||||||
Subject: ${originalEmail.subject || ''}
|
Subject: ${originalEmail?.subject || ''}
|
||||||
To: ${toStr}
|
To: ${toStr}
|
||||||
${ccStr ? `Cc: ${ccStr}\n` : ''}
|
${ccStr ? `Cc: ${ccStr}\n` : ''}
|
||||||
|
|
||||||
@ -475,10 +479,21 @@ export function formatEmailForReplyOrForward(
|
|||||||
subject: string;
|
subject: string;
|
||||||
content: EmailContent;
|
content: EmailContent;
|
||||||
} {
|
} {
|
||||||
|
// Use our dedicated formatters but ensure the return is properly typed
|
||||||
if (type === 'forward') {
|
if (type === 'forward') {
|
||||||
const { subject, content } = formatForwardedEmail(email);
|
const formatted = formatForwardedEmail(email);
|
||||||
return { subject, content };
|
return {
|
||||||
|
to: formatted.to,
|
||||||
|
subject: formatted.subject,
|
||||||
|
content: formatted.content
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
return formatReplyEmail(email, type);
|
const formatted = formatReplyEmail(email, type);
|
||||||
|
return {
|
||||||
|
to: formatted.to,
|
||||||
|
cc: formatted.cc,
|
||||||
|
subject: formatted.subject,
|
||||||
|
content: formatted.content
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user