- Move client.connect() inside try/catch in withClient - Add logImapError() writing full stack to /vaults/imap-errors.log for diagnosis - Extend patch-imapflow.cjs to guard this.remainder.trim() in parser-instance.js - Root cause of reported crash was undefined args.q (callers passing 'query' not 'q') Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
87 lines
3.3 KiB
JavaScript
87 lines
3.3 KiB
JavaScript
#!/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');
|
|
}
|
|
}
|