import type { Transform } from 'node:stream';
import type { ImapFlow } from './imap-flow.js';
import { type ConnectionErrorSite, type ImapFlowError } from './errors.js';
import type { ImapAttributeList, ImapAttributeNode, ImapResponse } from './handler/types.js';
import type { FetchMessageObject, ListResponse, ListTreeResponse, MailboxObject, MessageEnvelopeObject, MessageStructureObject, ImapFlowEvents, StatusQuery } from './types.js';
export { AuthenticationFailure } from './errors.js';
export declare const EXPANDED_RANGE_LIMIT = 16777216;
export declare const MAX_UINT32_DIGITS = 10;
export declare const noop: () => void;
/**
 * A stream decoder returned by getDecoder(). The Japanese decoder reports the `limited`
 * flag once it has buffered all it will accept; a streaming iconv decoder never sets it.
 */
export type CharsetDecoder = Transform & {
    limited?: boolean | undefined;
};
/**
 * Builds an error describing a connection that is gone, stamped so it can be traced back to
 * where it came from: the connection id always travels on it, and each site names itself
 * through `meta` (`rejectedFrom`, plus the command or mailbox path it belongs to).
 *
 * A stack trace only records where an error was built, and close() hands a rejection to every
 * pending request and every queued lock in the same tick, so without these an error that
 * reaches a global unhandledRejection handler arrives with nothing that identifies the
 * connection it came from, let alone which of the rejected promises carried it.
 *
 * Takes the connection id rather than the connection, so the stamping stays in one place
 * without every caller having to be a full ImapFlow instance.
 *
 * @param cid - Connection id
 * @param code - Error code, e.g. 'NoConnection'
 * @param message - Error message
 * @param meta - Fields to stamp on the error
 * @returns The stamped error
 */
export declare function buildConnectionError(cid: string, code: string, message: string, meta?: ConnectionErrorSite | undefined): ImapFlowError;
/**
 * Re-stamps an existing connection error for a different rejection site.
 *
 * The same failure can be handed to more than one promise - close() rejects the in-flight
 * command, and runIdle() then rejects everything queued behind it - and each of those is a
 * separate promise with a separate consumer. Sharing one error object reports whichever of
 * them escapes under the first site's marker, which is the attribution these markers exist to
 * give.
 *
 * Everything describing *what went wrong* is carried over, because a re-stamped error reaches
 * user code through run() and callers branch on `responseStatus`, `serverResponseCode` and
 * friends. Everything describing *where it was rejected* is dropped, because the new site owns
 * those and a leftover `command` from the previous site is exactly as misleading as a leftover
 * `rejectedFrom`. The original travels on as `cause`.
 *
 * @param err - The error being re-stamped
 * @param meta - Fields for the new site, e.g. { rejectedFrom: 'preCheckWaiter' }
 * @returns A separate error describing the same failure at the new site
 */
export declare function restampConnectionError(err: ImapFlowError, meta?: ConnectionErrorSite | undefined): ImapFlowError;
/**
 * Creates a promise whose rejection is observed as soon as it exists.
 *
 * close() rejects every promise it owns - the in-flight and queued commands, the pending
 * connect(), the queued mailbox locks, the waiters for an IDLE break - synchronously, from a
 * socket event. A consumer that only reaches its `await` a microtask later has not attached a
 * handler yet at the moment Node decides whether the rejection was observed, and the whole
 * worker dies on the resulting unhandledRejection. The pre-attached observer settles that
 * question; the rejection still propagates normally to whoever awaits the returned promise.
 *
 * Creation and guarding are one call because splitting them is what actually goes wrong: the
 * guard was hand-attached at three of the four sites and the fourth (the IDLE-break waiter)
 * went unguarded, on exactly the path a server BYE takes.
 *
 * @param executor - Promise executor, (resolve, reject) => {}
 * @returns The promise, with its rejection already observed
 */
export declare function guardedPromise<T>(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): Promise<T>;
/**
 * The already-rejected form of guardedPromise(), for a call that has to hand back a rejected
 * promise rather than throw.
 *
 * @param error - Rejection reason
 * @returns Rejected promise, with its rejection already observed
 */
export declare function guardedReject(error: Error): Promise<never>;
/**
 * Clears a timer that may already have been dropped. `clearTimeout()` accepts undefined but not
 * null, and the connection nulls its timer fields once cleared, so every site clears through here.
 *
 * @param timer - Timer handle returned by setTimeout, or null/undefined when none is armed
 */
export declare function clearTimer(timer: NodeJS.Timeout | null | undefined): void;
/**
 * Detaches a background timer from the event loop, so it cannot keep the process alive on its
 * own. Applied to every background timer (auto-IDLE, IDLE restart, fallback polling, throttle
 * back-off, held-lock diagnostics); connection and greeting deadlines are deliberately left
 * attached, because a caller is waiting for connect() to settle.
 *
 * @param timer - Timer handle returned by setTimeout
 * @returns The same timer handle
 */
export declare function unrefTimer<T extends NodeJS.Timeout | null | undefined>(timer: T): T;
/**
 * Logs a failure from background connection work at the level its cause deserves.
 *
 * Background work (IDLE sessions, polling timers, auto-IDLE) is interrupted by every normal
 * disconnect, so a rejection carrying one of the CONNECTION_GONE_CODES is expected rather
 * than notable and goes to debug. The three codes describe the same situation reached
 * through different guards: write() throws NoConnection or StateLogout, exec() rejects
 * EConnectionClosed for the window where the socket is destroyed but close() has not run
 * yet, and close() rejects pending requests with NoConnection.
 *
 * A connection error carrying `reason` is the exception. That field holds the server's
 * untagged BYE text ("Too many simultaneous connections", "Account is disabled"), which
 * serverBye() only records - this log call is the one place it becomes visible, and it is
 * usually the answer to why a client is reconnecting in a loop. Those stay at warn.
 *
 * Shared so the classification cannot drift between the call sites that make this decision.
 *
 * @param connection - IMAP connection instance
 * @param msg - What failed, so the entries stay distinguishable in the log
 * @param err - The error to log
 */
export declare function logConnectionError(connection: ImapFlow, msg: string, err: ImapFlowError | null | undefined): void;
/**
 * Checks whether IMAP4rev2 semantics are active for the connection: either the
 * client enabled IMAP4rev2 explicitly, or the server is rev2-only (advertises
 * IMAP4rev2 without IMAP4rev1), in which case rev2 is the base protocol without
 * any ENABLE (RFC 9051 Appendix A). UTF-8 mailbox names apply in both cases.
 *
 * @param connection - IMAP connection instance
 * @returns True if IMAP4rev2 semantics apply to this session
 */
export declare function isRev2Active(connection: ImapFlow): boolean;
/**
 * Checks a capability, accounting for extensions that RFC 9051 folds into base
 * IMAP4rev2. Falls back to the plain capability lookup on IMAP4rev1 sessions,
 * so behavior against rev1 servers is unchanged.
 *
 * @param connection - IMAP connection instance
 * @param capability - Capability name, e.g. 'UIDPLUS'
 * @returns True if the capability (or its rev2-folded equivalent) is available
 */
export declare function hasCapability(connection: ImapFlow, capability: string): boolean;
/**
 * Builds the attribute list for a STATUS request - the standalone STATUS command
 * or the LIST-STATUS return option - from a status query object. Items the current
 * session cannot request (RECENT under IMAP4rev2, HIGHESTMODSEQ without CONDSTORE)
 * are silently dropped.
 *
 * @param connection - IMAP connection instance
 * @param statusQuery - Status data items to request, e.g. {messages: true}
 * @returns Attribute token list for the command compiler
 */
export declare function buildStatusQueryAttributes(connection: ImapFlow, statusQuery: StatusQuery | undefined): ImapAttributeNode[];
/**
 * Encodes a mailbox path to modified UTF-7 if the server does not support UTF8=ACCEPT.
 *
 * @param connection - IMAP connection instance
 * @param path - Mailbox path to encode
 * @returns Encoded mailbox path
 */
export declare function encodePath(connection: ImapFlow, path: string | undefined): string;
/**
 * Decodes a mailbox path from modified UTF-7 if the server does not support UTF8=ACCEPT.
 *
 * @param connection - IMAP connection instance
 * @param path - Mailbox path to decode
 * @returns Decoded mailbox path
 */
export declare function decodePath(connection: ImapFlow, path: string | undefined): string;
/**
 * Normalizes a mailbox path by joining array segments with the namespace delimiter,
 * uppercasing INBOX, and prepending the namespace prefix if needed.
 *
 * @param connection - IMAP connection instance
 * @param path - Mailbox path or array of path segments
 * @param skipNamespace - If true, skips prepending the namespace prefix
 * @returns Normalized mailbox path
 */
export declare function normalizePath(connection: ImapFlow, path: string | string[], skipNamespace?: boolean): string;
/**
 * Compares two mailbox paths for equality after normalization.
 *
 * @param connection - IMAP connection instance
 * @param a - First mailbox path
 * @param b - Second mailbox path
 * @returns True if the paths are equal after normalization
 */
export declare function comparePaths(connection: ImapFlow, a: string | undefined, b: string | undefined): boolean;
/**
 * Parses a capability response list into a Map of capability names to values.
 *
 * @param list - Array of capability objects from IMAP response
 * @returns Map of capability names to `true` or numeric values
 */
export declare function updateCapabilities(list: ImapAttributeList | null | undefined): Map<string, boolean | number>;
/**
 * Extracts the IMAP response status code (e.g. AUTHENTICATIONFAILED, NONEXISTENT)
 * from a parsed server response.
 *
 * @param response - Parsed IMAP server response
 * @returns Uppercase status code string, or false if not found
 */
export declare function getStatusCode(response: ImapResponse | string | false | undefined): string | false;
/**
 * Emits a state-change event from inside the command pipeline. A listener that throws must not
 * abort the code that emitted it: select() emits before it releases the response, so the throw
 * would leave the reader loop waiting forever, and close() would never get to emit 'close'. The
 * error is logged instead, the same contract untagged handlers and the 'response' event get.
 *
 * @param connection - IMAP connection instance
 * @param event - Event name
 * @param args - Event arguments
 */
export declare function emitSafe<K extends keyof ImapFlowEvents>(connection: ImapFlow, event: K, ...args: ImapFlowEvents[K]): void;
/**
 * Collects the values of the TEXT tokens of a parsed response (the human-readable
 * part of a status response, a greeting or a BYE).
 *
 * @param attributes - Attributes of a parsed IMAP response
 * @returns Values of the TEXT tokens, in order
 */
export declare function getTextValues(attributes: ImapAttributeList | undefined): string[];
/**
 * Compiles an IMAP response object back into a human-readable string.
 *
 * @param response - Parsed IMAP server response
 * @returns Compiled response text, or false if no response
 */
export declare function getErrorText(response: ImapResponse | string | false | undefined): Promise<string | false>;
/**
 * Enhances an IMAP command error with the server response code and text.
 *
 * @param err - Error object with a `response` property
 * @returns The enhanced error with `serverResponseCode` and string `response`
 */
export declare function enhanceCommandError(err: ImapFlowError): Promise<ImapFlowError>;
/**
 * Enhances a failed command's error (see enhanceCommandError()) and logs it, the shared first
 * step of every command's failure path. The caller decides whether to throw or return.
 *
 * @param connection - IMAP connection instance
 * @param err - The command error
 */
export declare function reportCommandError(connection: ImapFlow, err: ImapFlowError): Promise<void>;
/**
 * Whether the session is authenticated, that is in the AUTHENTICATED or SELECTED state, which
 * every mailbox-level command requires.
 *
 * @param connection - IMAP connection instance
 */
export declare function isAuthenticatedState(connection: ImapFlow): boolean;
/**
 * Returns the selected mailbox, or false when the connection is not in the SELECTED state.
 * Message-level commands use it as their precondition, which also narrows the mailbox type.
 *
 * @param connection - IMAP connection instance
 */
export declare function getSelectedMailbox(connection: ImapFlow): MailboxObject | false;
/**
 * Converts a flat list of mailbox folders into a tree structure.
 *
 * @param folders - Array of folder objects from LIST/LSUB response
 * @returns Tree structure with a `root` flag and nested `folders` arrays
 */
export declare function getFolderTree(folders: ListResponse[]): ListTreeResponse;
/**
 * Derives a flag color name from a message's flags Set using Apple Mail color flag rules.
 *
 * @param flags - Message flags Set
 * @returns Color name (e.g. 'red', 'orange') or null if not flagged
 */
export declare function getFlagColor(flags: Set<string>): string | null;
/**
 * Converts a color name to the corresponding flag add/remove operations for Apple Mail color flags.
 *
 * @param color - Color name (e.g. 'red', 'orange', 'yellow')
 * @returns Object with `add` and `remove` arrays of flag strings, or null if invalid color
 */
export declare function getColorFlags(color: string | null | undefined): {
    add: string[];
    remove: string[];
} | null;
/**
 * Formats a raw untagged FETCH response into a structured message object.
 *
 * @param untagged - Parsed untagged IMAP response
 * @param mailbox - Current mailbox state object
 * @param idHashAlgorithm - Hash for the fallback message id, `md5` unless the client was told otherwise
 * @returns Formatted message object with properties like seq, uid, flags, envelope, etc.
 */
export declare function formatMessageResponse(untagged: ImapResponse, mailbox: MailboxObject, idHashAlgorithm?: string): Promise<FetchMessageObject>;
/**
 * Strips surrounding double quotes from a name string.
 *
 * @param name - Raw name string potentially wrapped in quotes
 * @returns Name with surrounding quotes removed
 */
export declare function processName(name: unknown): string;
/**
 * Decodes an ENVELOPE text field for display: encoded words first, then the
 * surrounding quotes some servers leave in place.
 *
 * @param value - Raw field value from an ENVELOPE response
 * @returns Decoded, unquoted text
 */
export declare function decodeText(value: string): string;
/**
 * Parses a raw IMAP ENVELOPE response into a structured envelope object.
 *
 * @param entry - Raw envelope data array from IMAP response
 * @returns Parsed envelope with date, subject, from, to, cc, bcc, messageId, etc.
 */
export declare function parseEnvelope(entry: ImapAttributeList): MessageEnvelopeObject;
/**
 * Parses structured MIME parameter arrays (including RFC 2231 continuations)
 * into a flat key-value object.
 *
 * @param arr - Raw parameter array from BODYSTRUCTURE response
 * @returns Key-value object of decoded parameters
 */
export declare function getStructuredParams(arr: ImapAttributeList | null | undefined): {
    [key: string]: string;
};
/**
 * Parses a raw IMAP BODYSTRUCTURE response into a structured tree of body parts.
 *
 * @param entry - Raw BODYSTRUCTURE data array from IMAP response
 * @returns Parsed body structure tree with part numbers, types, parameters, and child nodes
 */
export declare function parseBodystructure(entry: ImapAttributeList): MessageStructureObject;
/**
 * Checks if a value is a Date object.
 *
 * @param obj - Value to check
 * @returns True if the value is a Date object
 */
export declare function isDate(obj: unknown): obj is Date;
/**
 * Converts a value to a valid Date object, or returns null.
 *
 * @param value - Date object or date string to convert
 * @returns Valid Date object, or null if conversion fails
 */
export declare function toValidDate(value: unknown): Date | null;
/**
 * Formats a date value into IMAP date format (DD-Mon-YYYY).
 *
 * @param value - Date to format
 * @returns Formatted date string, or undefined if invalid
 */
export declare function formatDate(value: unknown): string | undefined;
/**
 * Formats a date value into IMAP date-time format (DD-Mon-YYYY HH:MM:SS +0000).
 *
 * @param value - Date to format
 * @returns Formatted date-time string, or undefined if invalid
 */
export declare function formatDateTime(value: unknown): string | undefined;
/**
 * Normalizes a flag string. Returns false for non-settable flags (e.g. \Recent),
 * and capitalizes system flags properly.
 *
 * @param flag - Flag string to normalize
 * @returns Normalized flag string, or false if the flag cannot be set
 */
export declare function formatFlag(flag: string): string | false;
/**
 * Checks if a flag can be used in the given mailbox based on permanent flags.
 *
 * @param mailbox - Mailbox object with permanentFlags
 * @param flag - Flag to check
 * @returns True if the flag is allowed
 */
export declare function canUseFlag(mailbox: MailboxObject | false | null | undefined, flag: string): boolean;
/**
 * Checks that a value is a valid IMAP sequence number or UID: a non-zero
 * 32-bit unsigned integer (nz-number in the RFC 9051 grammar). Guards range
 * expansion against untrusted server input such as 'Infinity' or '0:*'.
 *
 * @param value - Value to check
 * @returns True if the value is a valid sequence number/UID
 */
export declare function isValidSequenceValue(value: unknown): value is number;
/**
 * Checks that an untrusted response value is a pure decimal digit run no longer than
 * the given bound.
 *
 * `!isNaN(value)` is not usable for this: it also passes '1e5', ' 12 ', '0x10' and
 * 'Infinity'. BigInt() throws on all of them and Number() silently returns a value the
 * grammar never allowed, so both are wrong in a response handler that is only trying to
 * read one field. The length bound is checked before the pattern so an arbitrarily long
 * digit run is rejected without any conversion work.
 *
 * @param value - Raw value from the response.
 * @param maxDigits - Maximum number of digits accepted.
 * @returns True if the value is a decimal string within the bound.
 */
export declare function isDecimalString(value: unknown, maxDigits: number): value is string;
/**
 * Checks whether a server-supplied string is unsafe to use as a key on a plain object.
 * Assigning "__proto__" writes through the prototype setter instead of creating an own
 * property, and reading "constructor" or "prototype" resolves to an inherited member.
 *
 * @param key - Candidate key from a server response.
 * @returns True if the key must not be used.
 */
export declare function isUnsafeKey(key: unknown): boolean;
/**
 * Reads a parsed attribute list of atoms or strings (a flag list, a capability list) into
 * an array of strings. Any element can be a parsed NIL, and the list itself can be NIL,
 * so both levels are guarded here rather than at each call site.
 *
 * @param list - Parsed attribute list from a response.
 * @returns The string values, in order, with unusable entries dropped.
 */
export declare function getStringList(list: unknown): string[];
/**
 * Parses an untrusted decimal value from a server response into a BigInt.
 *
 * @param value - Raw value from the response.
 * @param maxDigits - Maximum number of digits accepted. Defaults to MAX_NUMBER64_DIGITS.
 * @returns The parsed value, or false when it is not usable.
 */
export declare function parseBigIntValue(value: unknown, maxDigits?: number): bigint | false;
/**
 * Parses an untrusted decimal value from a server response into a Number. Values beyond
 * the safe integer range are rejected rather than rounded: a silently rounded count or
 * UID corrupts every range computation derived from it.
 *
 * @param value - Raw value from the response.
 * @param maxDigits - Maximum number of digits accepted. Defaults to MAX_NUMBER64_DIGITS.
 * @returns The parsed value, or false when it is not usable.
 */
export declare function parseUintValue(value: unknown, maxDigits?: number): number | false;
/**
 * Expands an IMAP sequence range string (e.g. "1:3,5,7:9") into an array of numbers.
 *
 * Entries with endpoints that are not valid nz-numbers are skipped - the input
 * may come from an untrusted server, and 'Infinity' or similar garbage would
 * otherwise loop without bound. The whole set is expanded to at most
 * EXPANDED_RANGE_LIMIT entries in total: legitimate responses never reach the limit
 * (the mailbox would need that many messages), while hostile input is cut off
 * instead of exhausting memory. The total is capped, not just each range -
 * otherwise "1:16777216,1:16777216,..." would multiply the per-range bound by an
 * unbounded number of ranges.
 *
 * @param range - IMAP sequence range string
 * @returns Array of expanded sequence numbers
 */
export declare function expandRange(range: unknown): number[];
/**
 * Returns a stream decoder for the given charset. Uses a special Japanese
 * charset decoder for JIS/ISO-2022-JP, otherwise delegates to iconv-lite.
 *
 * @param charset - Character set name. Defaults to 'ascii'.
 * @param maxBytes - Bound for the bytes the decoder may buffer. Only
 *   relevant for the Japanese decoder, which must buffer its whole input before
 *   it can decode: without the bound a server could defeat a caller's maxBytes
 *   download limit simply by labelling the part with a Japanese charset.
 * @returns A stream decoder (Transform stream) for the charset
 */
export declare function getDecoder(charset?: string | undefined, maxBytes?: number | undefined): CharsetDecoder;
/**
 * Packs an array of message sequence numbers into a compact IMAP range string
 * (e.g. [1,2,3,5,7,8] becomes "1:3,5,7:8").
 *
 * @param list - Sequence number or array of sequence numbers
 * @returns Packed IMAP sequence range string
 */
export declare function packMessageRange(list: number | number[] | null | undefined): string;
