/** * Email Adapter Utility * * This utility provides adapter functions to convert legacy email * formats to the standardized EmailMessage format. * * Use these functions to migrate code gradually without breaking changes. */ import { EmailMessage, EmailContent, EmailAddress, EmailAttachment, EmailFlags } from '@/types/email'; import { normalizeEmailContent } from './email-utils'; /** * Convert a legacy email format to our standardized EmailMessage format * * This adapter function handles all the various ways email data might be structured * in the legacy codebase and converts it to our new standardized format. */ export function adaptLegacyEmail(legacyEmail: any): EmailMessage { if (!legacyEmail) { throw new Error('Cannot adapt a null or undefined email'); } // Handle case where it's already in the right format if ( legacyEmail.content && typeof legacyEmail.content === 'object' && 'isHtml' in legacyEmail.content && 'text' in legacyEmail.content ) { return legacyEmail as EmailMessage; } // Create normalized content const normalizedContent = normalizeEmailContent(legacyEmail); // Normalize flags to standard format let normalizedFlags: EmailFlags = { seen: false, flagged: false, answered: false, deleted: false, draft: false }; // Handle different possible formats for flags if (legacyEmail.flags) { if (typeof legacyEmail.flags === 'object' && !Array.isArray(legacyEmail.flags)) { // Object format: { seen: true, flagged: false, ... } normalizedFlags = { seen: !!legacyEmail.flags.seen, flagged: !!legacyEmail.flags.flagged, answered: !!legacyEmail.flags.answered, deleted: !!legacyEmail.flags.deleted, draft: !!legacyEmail.flags.draft }; } else if (Array.isArray(legacyEmail.flags)) { // Array format: ['\\Seen', '\\Flagged', ...] normalizedFlags.seen = legacyEmail.flags.includes('\\Seen'); normalizedFlags.flagged = legacyEmail.flags.includes('\\Flagged'); normalizedFlags.answered = legacyEmail.flags.includes('\\Answered'); normalizedFlags.deleted = legacyEmail.flags.includes('\\Deleted'); normalizedFlags.draft = legacyEmail.flags.includes('\\Draft'); } } // Normalize attachments to standard format const normalizedAttachments: EmailAttachment[] = Array.isArray(legacyEmail.attachments) ? legacyEmail.attachments.map((att: any) => ({ filename: att.filename || att.name || 'attachment', contentType: att.contentType || att.type || 'application/octet-stream', content: att.content || att.data || undefined, size: att.size || 0, contentId: att.contentId || att.cid || undefined })) : []; // Return a normalized EmailMessage return { id: legacyEmail.id || legacyEmail.uid?.toString() || `email-${Date.now()}`, messageId: legacyEmail.messageId, uid: typeof legacyEmail.uid === 'number' ? legacyEmail.uid : undefined, subject: legacyEmail.subject || '(No subject)', from: Array.isArray(legacyEmail.from) ? legacyEmail.from : [], to: Array.isArray(legacyEmail.to) ? legacyEmail.to : [], cc: Array.isArray(legacyEmail.cc) ? legacyEmail.cc : undefined, bcc: Array.isArray(legacyEmail.bcc) ? legacyEmail.bcc : undefined, date: legacyEmail.date || new Date(), flags: normalizedFlags, preview: legacyEmail.preview || '', content: normalizedContent, attachments: normalizedAttachments, folder: legacyEmail.folder || undefined, size: typeof legacyEmail.size === 'number' ? legacyEmail.size : undefined }; } /** * Helper function to detect if an object is an EmailAddress */ export function isEmailAddress(obj: any): obj is EmailAddress { return obj && typeof obj === 'object' && 'address' in obj && typeof obj.address === 'string'; } /** * Convert legacy email address format to standardized EmailAddress format */ export function adaptEmailAddress(address: any): EmailAddress { if (isEmailAddress(address)) { return { name: address.name || '', address: address.address }; } if (typeof address === 'string') { // Try to extract name and address from string like "Name " const match = address.match(/^(?:"?([^"]*)"?\s)?]+@[^\s>]+)>?$/); if (match) { return { name: match[1] || '', address: match[2] }; } // If no match, assume it's just an email address return { name: '', address }; } // Return a placeholder if we can't parse the address return { name: '', address: 'unknown@example.com' }; }