/** * RFC 5322/MIME Compliant Email Serializer * * Serializes IEmailMetadata objects into RFC 5322 compliant email format. * Provides methods for serializing individual email components (headers, * addresses, Message-IDs, dates, content types). * * Wraps the `mimetext` library for full email serialization. * * @see RFC 5322 - Internet Message Format * @see RFC 2045 - MIME Part One: Format of Internet Message Bodies * @see RFC 2046 - MIME Part Two: Media Types * * @remarks * Requirements: 14.1, 14.2, 14.3 */ import { type IAddress, type IMailbox } from '../../interfaces/messaging/emailAddress'; import type { IEmailMetadata } from '../../interfaces/messaging/emailMetadata'; import { type IContentType, type IMimePart } from '../../interfaces/messaging/mimePart'; /** * RFC 5322/MIME compliant email serializer. * * Provides methods for serializing email headers, addresses, Message-IDs, * dates, and content types. The main `serialize()` method (Task 5.7) will * use `mimetext` for full email serialization. * * @see Design Document: EmailSerializer Class */ export declare class EmailSerializer { /** * Serializes all headers from an IEmailMetadata object into an RFC 5322 * compliant header section string. * * Produces headers with proper CRLF line endings and folds long lines * at 78 characters per RFC 5322 Section 2.2.3. The header section is * terminated with a blank line (CRLF CRLF) to separate it from the body. * * @param email - The email metadata to serialize headers from * @returns The serialized header section string with CRLF line endings, * terminated by a blank line (CRLF CRLF) * * @see RFC 5322 Section 2.2 - Header Fields * @see Requirement 14.1 - RFC 5322 compliant output with proper CRLF line endings * @see Requirement 14.2 - Fold header lines exceeding 78 characters * @see Requirement 14.3 - Separate header section from body with blank line * * @example * ```typescript * const serializer = new EmailSerializer(); * const headers = serializer.serializeHeaders(emailMetadata); * // "From: sender@example.com\r\nTo: recipient@example.com\r\n..." * ``` */ serializeHeaders(email: IEmailMetadata): string; /** * Serializes a single IMailbox into an RFC 5322 compliant mailbox string. * * If a display name is present, formats as name-addr: `"Display Name" ` * Otherwise, formats as addr-spec: `local@domain` * * @param mailbox - The mailbox to serialize * @returns RFC 5322 formatted mailbox string * * @see RFC 5322 Section 3.4 - Address Specification * * @example * ```typescript * const serializer = new EmailSerializer(); * serializer.serializeMailbox({ localPart: 'john', domain: 'example.com', displayName: 'John Doe', address: 'john@example.com' }); * // => '"John Doe" ' * * serializer.serializeMailbox({ localPart: 'john', domain: 'example.com', address: 'john@example.com' }); * // => 'john@example.com' * ``` */ serializeMailbox(mailbox: IMailbox): string; /** * Serializes an array of IAddress objects into a comma-separated * RFC 5322 address list string. * * Supports both individual mailboxes and group addresses. * * @param addresses - Array of addresses to serialize * @returns Comma-separated RFC 5322 formatted address list string * * @see RFC 5322 Section 3.4 - Address Specification * * @example * ```typescript * const serializer = new EmailSerializer(); * serializer.serializeAddressList([mailbox1, mailbox2]); * // => '"Alice" , bob@example.com' * ``` */ serializeAddressList(addresses: IAddress[]): string; /** * Serializes a Message-ID string, ensuring it is enclosed in angle brackets. * * If the Message-ID is already enclosed in angle brackets, it is returned as-is. * Otherwise, angle brackets are added. * * @param messageId - The Message-ID string to serialize * @returns The Message-ID enclosed in angle brackets * * @see RFC 5322 Section 3.6.4 - Identification Fields * * @example * ```typescript * const serializer = new EmailSerializer(); * serializer.serializeMessageId(''); * // => '' * * serializer.serializeMessageId('unique-id@example.com'); * // => '' * ``` */ serializeMessageId(messageId: string): string; /** * Serializes a Date object into an RFC 5322 compliant date-time string. * * Produces format: "day-of-week, DD Mon YYYY HH:MM:SS +0000" * Example: "Thu, 13 Feb 2025 15:30:00 +0000" * * @param date - The Date object to serialize * @returns RFC 5322 formatted date-time string * * @see RFC 5322 Section 3.3 - Date and Time Specification * * @example * ```typescript * const serializer = new EmailSerializer(); * serializer.serializeDate(new Date('2025-02-13T15:30:00Z')); * // => 'Thu, 13 Feb 2025 15:30:00 +0000' * ``` */ serializeDate(date: Date): string; /** * Serializes an IContentType object into an RFC 2045 Content-Type header value. * * Produces format: "type/subtype; param1=value1; param2=value2" * Parameter values containing special characters are quoted. * * @param contentType - The content type to serialize * @returns RFC 2045 formatted Content-Type header value * * @see RFC 2045 Section 5 - Content-Type Header Field * * @example * ```typescript * const serializer = new EmailSerializer(); * serializer.serializeContentType(createContentType('text', 'plain', new Map([['charset', 'utf-8']]))); * // => 'text/plain; charset=utf-8' * * serializer.serializeContentType(createContentType('multipart', 'mixed', new Map([['boundary', '----=_Part_123']]))); * // => 'multipart/mixed; boundary="----=_Part_123"' * ``` */ serializeContentType(contentType: IContentType): string; /** * Serializes an array of IMimePart objects into a multipart body with * proper boundary delimiters per RFC 2046 Section 5.1.1. * * Each part is formatted with its MIME headers (Content-Type, * Content-Transfer-Encoding, Content-Disposition, Content-ID, * Content-Description) followed by a blank line and the encoded body. * Parts are separated by "--boundary" delimiters and the message is * terminated with "--boundary--". * * Handles nested multipart parts recursively. * * @param parts - Array of IMimePart objects to serialize * @param boundary - The boundary string to use as delimiter * @returns The serialized multipart body as Uint8Array * * @see RFC 2046 Section 5.1.1 - Common Syntax * @see Requirement 6.5 - Generate unique boundary string * @see Requirement 6.6 - Format multipart with proper boundary delimiters * * @example * ```typescript * const serializer = new EmailSerializer(); * const parts: IMimePart[] = [ * { contentType: createContentType('text', 'plain'), body: new TextEncoder().encode('Hello'), size: 5 }, * { contentType: createContentType('text', 'html'), body: new TextEncoder().encode('

Hello

'), size: 12 }, * ]; * const boundary = serializer.generateBoundary(); * const result = serializer.serializeMultipart(parts, boundary); * ``` */ serializeMultipart(parts: IMimePart[], boundary: string): Uint8Array; /** * Serializes the body of an email message based on its content type. * * For multipart content types (multipart/*), delegates to serializeMultipart() * using the boundary parameter from the content type. * For single-part content, encodes the first part's body directly based on * its Content-Transfer-Encoding. * * @param parts - Array of IMimePart objects representing the message body * @param contentType - The top-level Content-Type of the message * @returns The serialized body as Uint8Array * * @see Requirement 6.5 - Generate unique boundary for multipart messages * @see Requirement 6.6 - Format multipart with proper boundary delimiters * * @example * ```typescript * const serializer = new EmailSerializer(); * // Single part * const textPart: IMimePart = { * contentType: createContentType('text', 'plain'), * body: new TextEncoder().encode('Hello'), * size: 5, * }; * const body = serializer.serializeBody([textPart], textPart.contentType); * ``` */ serializeBody(parts: IMimePart[], contentType: IContentType): Uint8Array; /** * Encodes a part's body content based on its Content-Transfer-Encoding. * * @param body - The raw body content * @param encoding - The Content-Transfer-Encoding to apply * @returns The encoded body as Uint8Array */ private encodePartBody; /** * Folds a header line at the specified maximum length per RFC 5322 Section 2.2.3. * * Long header lines are broken at appropriate whitespace boundaries by * inserting CRLF followed by a space (folding whitespace). The fold point * is chosen at the last whitespace boundary before the maximum length. * * If no whitespace boundary is found before the maximum length, the line * is folded at the first whitespace boundary after the maximum length. * * @param headerLine - The header line to fold * @param maxLength - Maximum line length before folding (default: 78) * @returns The folded header line with CRLF + space at fold points * * @see RFC 5322 Section 2.2.3 - Long Header Fields * @see Requirement 14.2 - Fold header lines exceeding 78 characters * * @example * ```typescript * const serializer = new EmailSerializer(); * const long = 'Subject: ' + 'a'.repeat(80); * const folded = serializer.foldHeader(long); * // Lines are broken at whitespace boundaries, each <= 78 chars * ``` */ foldHeader(headerLine: string, maxLength?: number): string; /** * Generates a unique boundary string for multipart messages. * * The boundary is designed to be unique and unlikely to appear in * any message content. Uses a combination of a fixed prefix, * timestamp, and random characters. * * @returns A unique boundary string * * @see RFC 2046 Section 5.1.1 - Common Syntax * * @example * ```typescript * const serializer = new EmailSerializer(); * const boundary = serializer.generateBoundary(); * // => '----=_Part_1707836400000_abc123def456' * ``` */ generateBoundary(): string; /** * Encodes a string as an RFC 2047 encoded-word. * * Encoded-words have the format: =?charset?encoding?encoded-text?= * where encoding is either "B" (base64) or "Q" (quoted-printable). * * For 'B' encoding, the text bytes are base64 encoded. * For 'Q' encoding, the text bytes are quoted-printable encoded with * underscore for space per RFC 2047 Section 4.2. * * @param text - The text string to encode * @param charset - The character set (e.g., 'UTF-8', 'ISO-8859-1') * @param encoding - The encoding type: 'B' for base64, 'Q' for quoted-printable * @returns The RFC 2047 encoded-word string * * @see RFC 2047 - MIME Part Three: Message Header Extensions for Non-ASCII Text * @see Requirement 4.2 - Encode non-ASCII subject characters using RFC 2047 encoded-words * @see Requirement 4.3 - Support both Base64 (B) and Quoted-Printable (Q) encoding * * @example * ```typescript * const serializer = new EmailSerializer(); * serializer.encodeEncodedWord('Hello World', 'UTF-8', 'B'); * // => '=?UTF-8?B?SGVsbG8gV29ybGQ=?=' * * serializer.encodeEncodedWord('Hello World', 'UTF-8', 'Q'); * // => '=?UTF-8?Q?Hello_World?=' * ``` */ encodeEncodedWord(text: string, charset: string, encoding: 'B' | 'Q'): string; /** * Encodes binary data as quoted-printable per RFC 2045 Section 6.7. * * Rules: * - Bytes in the printable ASCII range (33-126, except '=') are literal * - All other bytes are encoded as =XX (uppercase hex) * - Lines are limited to 76 characters max; soft line breaks (=\r\n) are * inserted when needed * - Spaces and tabs before line breaks are encoded * - Tab (0x09) and space (0x20) are allowed as literals within a line * * @param data - The binary data to encode as Uint8Array * @returns The quoted-printable encoded data as Uint8Array * * @see RFC 2045 Section 6.7 - Quoted-Printable Content-Transfer-Encoding * @see Requirement 7.7 - Use quoted-printable for text with special characters * @see Requirement 14.8 - Encode body according to Content-Transfer-Encoding header * * @example * ```typescript * const serializer = new EmailSerializer(); * const data = new TextEncoder().encode('Hello World!'); * const encoded = serializer.encodeQuotedPrintable(data); * // encoded contains bytes for 'Hello World!' * * const nonAscii = new Uint8Array([0xC3, 0xA9]); // UTF-8 'é' * const encodedNonAscii = serializer.encodeQuotedPrintable(nonAscii); * // encoded contains bytes for '=C3=A9' * ``` */ encodeQuotedPrintable(data: Uint8Array): Uint8Array; /** * Encodes binary data as base64 per RFC 2045 Section 6.8. * * Produces standard base64 encoding with line breaks inserted every * 76 characters per RFC 2045. * * @param data - The binary data to encode as Uint8Array * @returns The base64 encoded data as Uint8Array * * @see RFC 2045 Section 6.8 - Base64 Content-Transfer-Encoding * @see Requirement 7.6 - Use base64 for binary content * @see Requirement 14.8 - Encode body according to Content-Transfer-Encoding header * * @example * ```typescript * const serializer = new EmailSerializer(); * const data = new TextEncoder().encode('Hello World'); * const encoded = serializer.encodeBase64(data); * // encoded contains bytes for 'SGVsbG8gV29ybGQ=' * ``` */ encodeBase64(data: Uint8Array): Uint8Array; /** * Determines if a parameter value needs to be quoted per RFC 2045. * * Values containing special characters (spaces, semicolons, equals signs, * quotes, backslashes, parentheses, angle brackets, at signs, commas, * or non-printable characters) must be quoted. * * @param value - The parameter value to check * @returns true if the value needs quoting */ private needsQuoting; /** * Escapes special characters in a quoted string per RFC 2045. * * Backslashes and double quotes are escaped with a preceding backslash. * * @param value - The string to escape * @returns The escaped string (without surrounding quotes) */ private escapeQuotedString; /** * Serializes a complete IEmailMetadata object into an RFC 5322 compliant * email message as a Uint8Array. * * Composes the existing `serializeHeaders()` and `serializeBody()` methods * to produce a complete email message with proper CRLF line endings. * The header section is separated from the body by a blank line (CRLF CRLF), * which is already included by `serializeHeaders()`. * * Handles both single-part and multipart emails by delegating to * `serializeBody()` which selects the appropriate serialization strategy * based on the content type. * * @param email - The email metadata to serialize * @returns The complete RFC 5322 email message as Uint8Array * * @see RFC 5322 - Internet Message Format * @see Requirement 14.1 - RFC 5322 compliant output with proper CRLF line endings * * @example * ```typescript * const serializer = new EmailSerializer(); * const rawEmail = serializer.serialize(emailMetadata); * // rawEmail is a Uint8Array containing the full RFC 5322 message * ``` */ serialize(email: IEmailMetadata): Uint8Array; } //# sourceMappingURL=emailSerializer.d.ts.map