Neah/lib/email-formatter.ts
2025-04-26 11:46:03 +02:00

209 lines
5.9 KiB
TypeScript

'use client';
/**
* Client-side utilities for formatting email content
* This file contains functions for formatting email content in the browser
* without any server dependencies.
*/
interface EmailAddress {
name?: string;
address: string;
}
interface FormattedEmail {
to: string;
cc?: string;
subject: string;
body: string;
}
/**
* Format an email for replying or forwarding
* Client-side friendly version that doesn't depend on server modules
*/
export function formatEmailForReply(
email: any,
type: 'reply' | 'reply-all' = 'reply'
): FormattedEmail {
// Format the subject with Re: prefix
const subject = formatSubject(email.subject || '(No subject)', type);
// Format recipients
let to = '';
let cc = '';
// Process 'to' field for reply
if (typeof email.from === 'string') {
to = email.from;
} else if (Array.isArray(email.from)) {
to = email.from.map((addr: EmailAddress) =>
addr.name && addr.name !== addr.address
? `${addr.name} <${addr.address}>`
: addr.address
).join(', ');
} else if (email.fromName || email.from) {
// Handle cases where from is an object with name and address
if (email.fromName && email.from && email.fromName !== email.from) {
to = `${email.fromName} <${email.from}>`;
} else {
to = email.from;
}
}
// For reply-all, include other recipients in cc
if (type === 'reply-all' && email.to) {
if (typeof email.to === 'string') {
cc = email.to;
} else if (Array.isArray(email.to)) {
cc = email.to.map((addr: EmailAddress) =>
addr.name && addr.name !== addr.address
? `${addr.name} <${addr.address}>`
: addr.address
).join(', ');
}
// Include cc recipients from original email too if available
if (email.cc) {
const ccList = typeof email.cc === 'string'
? email.cc
: Array.isArray(email.cc)
? email.cc.map((addr: EmailAddress) => addr.address).join(', ')
: '';
if (ccList) {
cc = cc ? `${cc}, ${ccList}` : ccList;
}
}
}
// Create quote header
const quoteHeader = createQuoteHeader(email);
// Format body with quote
let body = `<br/><br/>${quoteHeader}<blockquote style="margin: 0 0 0 0.8ex; border-left: 1px solid #ccc; padding-left: 1ex;">`;
// Add quoted content
if (email.content) {
body += email.content;
} else if (email.html) {
body += email.html;
} else if (email.text) {
body += `<pre>${email.text}</pre>`;
} else if (email.body) {
body += email.body;
} else {
body += '<div style="color: #666; font-style: italic;">No content available</div>';
}
body += '</blockquote>';
return {
to,
cc,
subject,
body
};
}
function formatSubject(subject: string, type: 'reply' | 'reply-all' | 'forward'): string {
// Clean up existing prefixes first
let cleanSubject = subject.replace(/^(Re|Fwd|FW|Forward):\s*/gi, '');
cleanSubject = cleanSubject.trim() || '(No subject)';
// Add appropriate prefix
if (type === 'forward') {
return `Fwd: ${cleanSubject}`;
} else {
// For reply and reply-all
return `Re: ${cleanSubject}`;
}
}
function createQuoteHeader(email: any): string {
let from = 'Unknown Sender';
let date = email.date ? new Date(email.date).toLocaleString() : 'Unknown Date';
let subject = email.subject || '(No subject)';
let to = '';
// Extract from
if (typeof email.from === 'string') {
from = email.from;
} else if (Array.isArray(email.from)) {
from = email.from.map((addr: EmailAddress) =>
addr.name ? `${addr.name} <${addr.address}>` : addr.address
).join(', ');
} else if (email.fromName || email.from) {
from = email.fromName && email.fromName !== email.from
? `${email.fromName} <${email.from}>`
: email.from;
}
// Extract to
if (typeof email.to === 'string') {
to = email.to;
} else if (Array.isArray(email.to)) {
to = email.to.map((addr: EmailAddress) =>
addr.name ? `${addr.name} <${addr.address}>` : addr.address
).join(', ');
}
return `
<div style="color: #666; margin-bottom: 10px; font-family: Arial, sans-serif;">
<div>On ${date}, ${from} wrote:</div>
</div>
`;
}
/**
* Format an email for forwarding
*/
export function formatEmailForForward(email: any): {
subject: string;
headerHtml: string;
} {
// Format subject with Fwd: prefix
const subject = formatSubject(email.subject || '(No subject)', 'forward');
// Get sender information
let fromString = 'Unknown Sender';
if (typeof email.from === 'string') {
fromString = email.from;
} else if (Array.isArray(email.from)) {
fromString = email.from.map((addr: EmailAddress) =>
addr.name ? `${addr.name} <${addr.address}>` : addr.address
).join(', ');
} else if (email.fromName && email.from) {
fromString = email.fromName !== email.from
? `${email.fromName} <${email.from}>`
: email.from;
}
// Get recipient information
let toString = '';
if (typeof email.to === 'string') {
toString = email.to;
} else if (Array.isArray(email.to)) {
toString = email.to.map((addr: EmailAddress) =>
addr.name ? `${addr.name} <${addr.address}>` : addr.address
).join(', ');
}
// Create header for forwarded email
const headerHtml = `
<div style="border-top: 1px solid #e1e1e1; margin-top: 20px; padding-top: 15px; font-family: Arial, sans-serif;">
<div style="margin-bottom: 15px;">
<div style="font-weight: normal; margin-bottom: 10px;">---------- Forwarded message ---------</div>
<div><b>From:</b> ${fromString}</div>
<div><b>Date:</b> ${email.date ? new Date(email.date).toLocaleString() : 'Unknown Date'}</div>
<div><b>Subject:</b> ${email.subject || '(No subject)'}</div>
<div><b>To:</b> ${toString || 'Unknown Recipient'}</div>
</div>
</div>
`;
return {
subject,
headerHtml
};
}