#!/usr/bin/env node // Patches imapflow to handle Poste.io servers returning IMAP NO/BAD/BYE // responses where some TEXT attributes have undefined .value, causing // `val.value.trim()` to throw "Cannot read properties of undefined". const fs = require('fs'); const path = require('path'); const file = path.join(__dirname, '../node_modules/imapflow/lib/imap-flow.js'); let src = fs.readFileSync(file, 'utf8'); const patches = [ { bad: `.map(val => val.value.trim())`, fixed: `.map(val => (val.value != null ? val.value.trim() : ''))`, }, { bad: `section[0].value.toUpperCase().trim()`, fixed: `(section[0].value || '').toUpperCase().trim()`, }, { bad: `attr.value.toUpperCase().trim()`, fixed: `(attr.value || '').toUpperCase().trim()`, }, { bad: `val.value.toUpperCase().trim()`, fixed: `(val.value || '').toUpperCase().trim()`, }, { bad: `contentType.value.toLowerCase().trim()`, fixed: `(contentType.value || '').toLowerCase().trim()`, }, { bad: `disposition.value.toLowerCase().trim()`, fixed: `(disposition.value || '').toLowerCase().trim()`, }, ]; let total = 0; for (const p of patches) { const re = new RegExp(p.bad.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'); const count = (src.match(re) || []).length; if (count > 0) { src = src.replaceAll(p.bad, p.fixed); total += count; console.log(`[patch-imapflow] patched ${count} occurrence(s) of: ${p.bad}`); } } if (total > 0) { fs.writeFileSync(file, src, 'utf8'); console.log(`[patch-imapflow] total patched ${total} occurrence(s) in imap-flow.js`); } else { console.log('[patch-imapflow] already patched or patterns not found — no changes made'); } // Also patch parser-instance.js (this.remainder can be undefined on malformed Poste.io responses) const parserFile = path.join(__dirname, '../node_modules/imapflow/lib/handler/parser-instance.js'); if (fs.existsSync(parserFile)) { let parserSrc = fs.readFileSync(parserFile, 'utf8'); let parserPatched = 0; const parserPatches = [ { bad: `this.humanReadable = this.remainder.trim();`, fixed: `this.humanReadable = (this.remainder || '').trim();` }, { bad: `this.humanReadable = this.remainder.substring(i + 1).trim();`, fixed: `this.humanReadable = (this.remainder || '').substring(i + 1).trim();` }, ]; for (const p of parserPatches) { if (parserSrc.includes(p.bad)) { parserSrc = parserSrc.replaceAll(p.bad, p.fixed); parserPatched++; console.log(`[patch-imapflow] patched parser-instance.js: ${p.bad}`); } } if (parserPatched > 0) fs.writeFileSync(parserFile, parserSrc, 'utf8'); } // Also patch nodemailer inside imapflow (malformed Content-Type headers) const nodemailerFile = path.join(__dirname, '../node_modules/imapflow/node_modules/nodemailer/lib/mime-node/index.js'); if (fs.existsSync(nodemailerFile)) { let nodemailerSrc = fs.readFileSync(nodemailerFile, 'utf8'); const nodemailerBad = `this.contentType = structured.value.trim().toLowerCase();`; const nodemailerFixed = `this.contentType = ((structured && structured.value) || '').trim().toLowerCase();`; if (nodemailerSrc.includes(nodemailerBad)) { nodemailerSrc = nodemailerSrc.replaceAll(nodemailerBad, nodemailerFixed); fs.writeFileSync(nodemailerFile, nodemailerSrc, 'utf8'); console.log('[patch-imapflow] patched nodemailer mime-node/index.js'); } }