courrier clean 2$

This commit is contained in:
alma 2025-04-26 19:23:31 +02:00
parent 4c9fcdeb29
commit afc7f64027
5 changed files with 68 additions and 365 deletions

View File

@ -1,6 +1,46 @@
# Deprecated Functions and Code
# Deprecated Functions and Files
This document tracks functions that have been marked as deprecated and should be removed in future releases.
This document lists functions and files that have been deprecated and should not be used in new code.
## Deprecated Files
### 1. `lib/email-formatter.ts` (REMOVED)
- **Status**: Removed
- **Replacement**: Use `lib/utils/email-formatter.ts` instead
- **Reason**: Consolidated email formatting to a single source of truth
### 2. `cleanHtml` in `lib/mail-parser-wrapper.ts`
- **Status**: Deprecated for email composition
- **Replacement**: Use `cleanHtmlContent` from `lib/utils/email-formatter.ts` instead
- **Reason**: Better handling of text direction and HTML sanitization
## Deprecated Functions
### 1. `formatEmailForReplyOrForward` in `lib/services/email-service.ts` (REMOVED)
- **Status**: Removed
- **Replacement**: Use `formatEmailForReplyOrForward` from `lib/utils/email-formatter.ts`
- **Reason**: Consolidated email formatting to a single source of truth
### 2. `formatSubject` in `lib/services/email-service.ts` (REMOVED)
- **Status**: Removed
- **Replacement**: None specific, handled by centralized formatter
- **Reason**: Internal function of the email formatter
### 3. `createQuoteHeader` in `lib/services/email-service.ts` (REMOVED)
- **Status**: Removed
- **Replacement**: None specific, handled by centralized formatter
- **Reason**: Internal function of the email formatter
## Centralized Email Formatting
All email formatting is now handled by the centralized formatter in `lib/utils/email-formatter.ts`. This file contains:
1. `formatForwardedEmail`: Format emails for forwarding
2. `formatReplyEmail`: Format emails for replying or replying to all
3. `formatEmailForReplyOrForward`: Compatibility function that maps to the above two
4. `cleanHtmlContent`: Safely sanitize HTML content while preserving direction attributes
Use these functions for all email formatting needs.
## Email Parsing and Processing Functions

View File

@ -56,4 +56,23 @@ npm run dev
# Build for production
npm run build
```
```
# Email Formatting
## Centralized Email Formatter
All email formatting is now handled by a centralized formatter in `lib/utils/email-formatter.ts`. This ensures consistent handling of:
- Text direction (RTL/LTR)
- HTML sanitization
- Content formatting for forwards and replies
### Key Functions
- `formatForwardedEmail`: Format emails for forwarding
- `formatReplyEmail`: Format emails for replying
- `cleanHtmlContent`: Sanitize HTML while preserving direction attributes
- `formatEmailForReplyOrForward`: Compatibility function for both
This centralized approach prevents formatting inconsistencies and direction problems when dealing with emails in different languages.

View File

@ -1,6 +1,7 @@
'use server';
import { getEmails, formatEmailForReplyOrForward, EmailMessage, EmailAddress } from '@/lib/services/email-service';
import { getEmails, EmailMessage, EmailAddress } from '@/lib/services/email-service';
import { formatEmailForReplyOrForward } from '@/lib/utils/email-formatter';
/**
* Server action to fetch emails
@ -20,6 +21,7 @@ export async function fetchEmails(userId: string, folder = 'INBOX', page = 1, pe
/**
* Server action to format email for reply or forward operations
* Uses the centralized email formatter
*/
export async function formatEmailServerSide(
email: {
@ -71,7 +73,7 @@ export async function formatEmailServerSide(
contentFetched: true
};
// Use the server-side formatter
// Use the centralized formatter
const formatted = formatEmailForReplyOrForward(serverEmail, type);
return {

View File

@ -1,225 +0,0 @@
'use client';
import DOMPurify from 'dompurify';
/**
* Client-side utilities for formatting email content
* This file contains functions for formatting email content in the browser
* without any server dependencies.
*/
export interface EmailAddress {
address: string;
name?: string;
}
export interface FormattedEmail {
subject: string;
to?: EmailAddress[];
cc?: EmailAddress[];
bcc?: EmailAddress[];
body: string;
}
export interface EmailMessageForFormatting {
subject?: string;
from?: EmailAddress | EmailAddress[];
to?: EmailAddress | EmailAddress[];
date?: Date | string;
html?: string;
text?: string;
cc?: EmailAddress | EmailAddress[];
bcc?: EmailAddress | EmailAddress[];
}
/**
* Format an email for replying or forwarding
* Client-side friendly version that doesn't depend on server modules
*/
export function formatEmailForReply(
originalEmail: EmailMessageForFormatting,
type: 'reply' | 'replyAll' | 'forward' = 'reply'
): FormattedEmail {
// Format the subject with Re: or Fwd: prefix
const subject = formatSubject(originalEmail.subject || '', type);
// Initialize recipients based on reply type
let to: EmailAddress[] = [];
let cc: EmailAddress[] = [];
if (type === 'reply' && originalEmail.from) {
to = Array.isArray(originalEmail.from) ? originalEmail.from : [originalEmail.from];
} else if (type === 'replyAll') {
// To: original sender
if (originalEmail.from) {
to = Array.isArray(originalEmail.from) ? originalEmail.from : [originalEmail.from];
}
// CC: all other recipients
if (originalEmail.to) {
cc = Array.isArray(originalEmail.to) ? originalEmail.to : [originalEmail.to];
}
if (originalEmail.cc) {
const existingCc = Array.isArray(originalEmail.cc) ? originalEmail.cc : [originalEmail.cc];
cc = [...cc, ...existingCc];
}
// Remove duplicates and self from CC (would need user's email here)
// This is simplified - in a real app you'd filter out the current user
cc = cc.filter((value, index, self) =>
index === self.findIndex((t) => t.address === value.address)
);
}
// Create the quoted content with header
const quoteHeader = createQuoteHeader(originalEmail);
// Get the original content, preferring HTML over plain text
let originalContent = '';
if (originalEmail.html) {
// Sanitize any potentially unsafe HTML
originalContent = DOMPurify.sanitize(originalEmail.html);
} else if (originalEmail.text) {
// Convert text to HTML by replacing newlines with br tags
originalContent = originalEmail.text.replace(/\n/g, '<br>');
}
// Combine the header with the original content, ensuring proper direction
const body = `
<div dir="ltr" style="text-align: left;">
<br>
<blockquote style="margin: 0 0 0 0.8ex; border-left: 1px solid #ccc; padding-left: 1ex;">
${quoteHeader}
<div style="direction: ltr; text-align: left;">${originalContent || 'No content available'}</div>
</blockquote>
</div>
`;
return {
subject,
to,
cc,
body
};
}
/**
* Format email subject with appropriate prefix
*/
export function formatSubject(
originalSubject: string,
type: 'reply' | 'replyAll' | 'forward'
): string {
// Trim whitespace
let subject = originalSubject.trim();
// Remove existing prefixes to avoid duplication
subject = subject.replace(/^(Re|Fwd):\s*/gi, '');
// Add appropriate prefix based on action type
if (type === 'forward') {
return `Fwd: ${subject}`;
} else {
return `Re: ${subject}`;
}
}
/**
* Create a formatted quote header with sender and date information
*/
export function createQuoteHeader(email: EmailMessageForFormatting): string {
let fromName = 'Unknown Sender';
let fromEmail = '';
// Extract sender information
if (email.from) {
if (Array.isArray(email.from)) {
fromName = email.from[0].name || email.from[0].address;
fromEmail = email.from[0].address;
} else {
fromName = email.from.name || email.from.address;
fromEmail = email.from.address;
}
}
// Format the date
let dateFormatted = '';
if (email.date) {
const date = typeof email.date === 'string' ? new Date(email.date) : email.date;
// Check if the date is valid
if (!isNaN(date.getTime())) {
dateFormatted = date.toLocaleString('en-US', {
weekday: 'short',
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
}
}
// Generate recipients string
let recipients = '';
if (email.to) {
if (Array.isArray(email.to)) {
recipients = email.to.map(r => r.name || r.address).join(', ');
} else {
recipients = email.to.name || email.to.address;
}
}
// Create the header HTML with explicit LTR direction
return `
<div style="margin-bottom: 10px; color: #555; font-size: 0.9em; direction: ltr; text-align: left;">
<div><strong>From:</strong> ${fromName} &lt;${fromEmail}&gt;</div>
${dateFormatted ? `<div><strong>Date:</strong> ${dateFormatted}</div>` : ''}
<div><strong>Subject:</strong> ${email.subject || 'No Subject'}</div>
<div><strong>To:</strong> ${recipients || 'No Recipients'}</div>
${email.cc ? `<div><strong>Cc:</strong> ${Array.isArray(email.cc) ?
email.cc.map(r => r.name || r.address).join(', ') :
(email.cc.name || email.cc.address)}</div>` : ''}
</div>
<hr style="border: none; border-top: 1px solid #ddd; margin: 10px 0;">
`;
}
/**
* Format an email for forwarding
*/
export function formatEmailForForward(email: EmailMessageForFormatting): FormattedEmail {
// Format the subject with Fwd: prefix
const subject = formatSubject(email.subject || '', 'forward');
// Create the forward header
const forwardHeader = createQuoteHeader(email);
// Get the original content, preferring HTML over plain text
let originalContent = '';
if (email.html) {
// Sanitize any potentially unsafe HTML
originalContent = DOMPurify.sanitize(email.html);
} else if (email.text) {
// Convert text to HTML by replacing newlines with br tags
originalContent = email.text.replace(/\n/g, '<br>');
}
// Combine the header with the original content, ensuring proper direction
const body = `
<div dir="ltr" style="text-align: left;">
<br>
<div style="border-left: 1px solid #ccc; padding-left: 1ex; margin-left: 0.8ex; direction: ltr; text-align: left;">
<div style="font-weight: bold; margin-bottom: 10px; direction: ltr; text-align: left;">---------- Forwarded message ---------</div>
${forwardHeader}
<div style="direction: ltr; text-align: left;">${originalContent || '<div style="padding: 10px; text-align: center; background-color: #f8f8f8; border: 1px dashed #ccc; margin: 10px 0;">No content available</div>'}</div>
</div>
</div>
`;
return {
subject,
body
};
}

View File

@ -628,138 +628,5 @@ export async function testEmailConnection(credentials: EmailCredentials): Promis
}
}
/**
* Format email for reply/forward
*/
export async function formatEmailForReplyOrForward(
email: EmailMessage,
type: 'reply' | 'reply-all' | 'forward'
): Promise<{
to: string;
cc?: string;
subject: string;
body: string;
}> {
// Format the subject with Re: or Fwd: prefix
const subject = await formatSubject(email.subject, type);
// Create the email quote with proper formatting
const quoteHeader = await createQuoteHeader(email);
const quotedContent = email.html || email.text || '';
// Format recipients
let to = '';
let cc = '';
if (type === 'reply') {
// Reply to sender only
to = email.from.map(addr => `${addr.name} <${addr.address}>`).join(', ');
} else if (type === 'reply-all') {
// Reply to sender and all recipients
to = email.from.map(addr => `${addr.name} <${addr.address}>`).join(', ');
// Add all original recipients to CC, except ourselves
const allRecipients = [
...(email.to || []),
...(email.cc || [])
];
cc = allRecipients
.map(addr => `${addr.name} <${addr.address}>`)
.join(', ');
} else if (type === 'forward') {
// Forward case doesn't need to set recipients
to = '';
// Instead, we format the content differently
const formattedDate = email.date ? new Date(email.date).toLocaleString() : '';
const fromText = email.from.map(f => f.name ? `${f.name} <${f.address}>` : f.address).join(', ');
const toText = email.to.map(t => t.name ? `${t.name} <${t.address}>` : t.address).join(', ');
// Return specialized body for forward with improved styling
return {
to: '',
subject,
body: `
<div class="forwarded-message" style="margin-top: 20px;">
<div style="background-color: #f5f5f5; border-left: 3px solid #ddd; padding: 12px; margin-bottom: 15px; border-radius: 4px;">
<p style="margin: 0 0 8px 0; font-weight: 500; color: #555; font-size: 14px;">---------- Forwarded message ---------</p>
<p style="margin: 0 0 6px 0; font-size: 13px;"><span style="font-weight: 600; color: #444;">From:</span> ${fromText}</p>
<p style="margin: 0 0 6px 0; font-size: 13px;"><span style="font-weight: 600; color: #444;">Date:</span> ${formattedDate}</p>
<p style="margin: 0 0 6px 0; font-size: 13px;"><span style="font-weight: 600; color: #444;">Subject:</span> ${email.subject || ''}</p>
<p style="margin: 0 0 6px 0; font-size: 13px;"><span style="font-weight: 600; color: #444;">To:</span> ${toText}</p>
</div>
<div class="forwarded-content" style="border-left: 2px solid #ddd; padding-left: 15px; color: #333;">
${email.html || email.text ? (email.html || `<pre style="white-space: pre-wrap; font-family: inherit; margin: 0;">${email.text || ''}</pre>`) : '<p>No content available</p>'}
</div>
</div>
`
};
}
// Format the email body with improved quote styling for replies
const body = `
<div class="reply-body">
<br/>
<div class="quote-header" style="color: #555; font-size: 13px; margin: 20px 0 10px 0;">${quoteHeader}</div>
<blockquote style="margin: 0; padding: 10px 0 10px 15px; border-left: 3px solid #ddd; color: #555; background-color: #f8f8f8; border-radius: 4px;">
<div class="quoted-content" style="font-size: 13px;">
${quotedContent}
</div>
</blockquote>
</div>`;
return {
to,
cc: cc || undefined,
subject,
body
};
}
/**
* Format subject with appropriate prefix (Re:, Fwd:)
*/
export async function formatSubject(subject: string, type: 'reply' | 'reply-all' | 'forward'): Promise<string> {
// Clean up any existing prefixes
let cleanSubject = subject
.replace(/^(Re|Fwd|FW|Forward):\s*/i, '')
.trim();
// Add appropriate prefix
if (type === 'reply' || type === 'reply-all') {
if (!subject.match(/^Re:/i)) {
return `Re: ${cleanSubject}`;
}
} else if (type === 'forward') {
if (!subject.match(/^(Fwd|FW|Forward):/i)) {
return `Fwd: ${cleanSubject}`;
}
}
return subject;
}
/**
* Create a quote header for reply/forward
*/
export async function createQuoteHeader(email: EmailMessage): Promise<string> {
// Format the date
const date = new Date(email.date);
const formattedDate = date.toLocaleString('en-US', {
weekday: 'short',
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
// Format the sender
const sender = email.from[0];
const fromText = sender?.name
? `${sender.name} <${sender.address}>`
: sender?.address || 'Unknown sender';
return `<div style="font-weight: 500;">On ${formattedDate}, ${fromText} wrote:</div>`;
}
// Email formatting functions have been moved to lib/utils/email-formatter.ts
// Use those functions instead of the ones previously defined here