"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = expunge; const tools_js_1 = require("../tools.js"); /** * Deletes specified messages by flagging them as Deleted and expunging. * * @param connection - IMAP connection instance * @param range - Message sequence number or UID range * @param options - Expunge options * @param options.uid - If true, use UID EXPUNGE when UIDPLUS is available * @returns True on success, false on failure, or undefined if preconditions not met */ async function expunge(connection, range, options) { let mailbox = (0, tools_js_1.getSelectedMailbox)(connection); if (!mailbox || !range) { // nothing to do here return; } options = options || {}; // Two-step deletion process per IMAP protocol: // Step 1: Mark the target messages with the \Deleted flag. // If that failed, EXPUNGE would not remove the target messages (and without // UIDPLUS it would remove unrelated \Deleted messages), so report the failure instead. if (!(await connection.messageFlagsAdd(range, ['\\Deleted'], options))) { return false; } // Step 2: Issue EXPUNGE to permanently remove \Deleted messages. // With UIDPLUS (RFC 4315): "UID EXPUNGE " removes only the specified UIDs, // leaving other \Deleted messages untouched, important for concurrent access. // Without UIDPLUS: plain "EXPUNGE" removes ALL messages flagged \Deleted in the mailbox. let byUid = options.uid && (0, tools_js_1.hasCapability)(connection, 'UIDPLUS'); let command = byUid ? 'UID EXPUNGE' : 'EXPUNGE'; let attributes = byUid ? [{ type: 'SEQUENCE', value: range }] : false; let response; try { response = await connection.exec(command, attributes); // CONDSTORE (RFC 7162): the server may return HIGHESTMODSEQ in the response code // (e.g., "A OK [HIGHESTMODSEQ 9122] Expunge completed"). // Track this so the client can detect concurrent mailbox changes via mod-sequences. let section = response.response.attributes && response.response.attributes[0] && response.response.attributes[0].section; let responseCode = section && section.length && section[0] && typeof section[0].value === 'string' ? section[0].value : ''; if (responseCode.toUpperCase() === 'HIGHESTMODSEQ') { // A response code always comes with its section, see responseCode above let codeSection = section; // Bounded digit runs only: isNaN() also passes '1e5', which BigInt() rejects with // a throw that the catch below would swallow, making messageDelete() report false // even though the server expunged the messages. let highestModseq = (0, tools_js_1.parseBigIntValue)(codeSection[1] && codeSection[1].value); if (highestModseq && (!mailbox.highestModseq || highestModseq > mailbox.highestModseq)) { mailbox.highestModseq = highestModseq; } } response.next(); return true; } catch (err) { await (0, tools_js_1.reportCommandError)(connection, err); return false; } } module.exports = exports.default; Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });