node-imap中RECENT/NEW标记在Outlook邮箱失效的解决求助
解决node-imap连接Outlook时RECENT搜索失效的问题
问题根源
Outlook的IMAP服务器实现与Gmail存在差异,它不会对新到达的邮件自动标记RECENT标签,这直接导致你用["RECENT"]作为搜索条件时无法获取到目标邮件。
可行解决方案
下面提供两种可靠的替代方案:
方案1:搜索未读邮件(UNSEEN)
直接用UNSEEN作为搜索条件,Outlook对该标记的支持更稳定,能准确获取未被读取过的邮件:
var Imap = require("imap"); // version : "^0.8.19", let config = { keepalive: { interval: 4000, idleInterval: 200000, forceNoop: true, }, user: "example@outlook.com", password: "xxxxxxxxxxx", // app password host: "outlook.office365.com", port: 993, tls: true, tlsOptions: { rejectUnauthorized: false }, }; let imap = new Imap(config); imap.connect() imap.once("ready", function () { console.log("Email connection established!"); imap.openBox("INBOX", false, function (err, box) { if (err) { console.log("Error opening inbox"); return; } }); }); imap.on("error", function (err) { console.log(err); }); imap.on("close", function (err) { console.log("connection closed"); }); imap.on("end", function (err) { console.log("connection ended"); }); imap.on("mail", function (newMsgNums) { console.log(`${newMsgNums} mails received!`); // 改用UNSEEN搜索未读邮件 imap.search(["UNSEEN"], function (error, results) { if (!results || results.length == 0) { console.log(`No unread email available!`); return; } var fetchQuery = imap.fetch(results, { bodies: [""], struct: true, }); fetchQuery.on("message", function (msg, seqno) { msg.on("body", async function (stream, info) { console.log(stream); }); msg.on("attributes", function (attrs) { console.log(attrs); }); msg.on("end", function () {}); }); fetchQuery.once("error", function (err) { console.log(err); }); fetchQuery.on("end", function () {}); }); });
方案2:直接获取最新到达的邮件
利用mail事件传入的新邮件数量,结合收件箱的实时总邮件数,直接定位并获取最新的N封邮件(N为newMsgNums),这种方式更精准:
var Imap = require("imap"); // version : "^0.8.19", let config = { keepalive: { interval: 4000, idleInterval: 200000, forceNoop: true, }, user: "example@outlook.com", password: "xxxxxxxxxxx", // app password host: "outlook.office365.com", port: 993, tls: true, tlsOptions: { rejectUnauthorized: false }, }; let imap = new Imap(config); let inboxBox; // 保存打开的收件箱对象 imap.connect() imap.once("ready", function () { console.log("Email connection established!"); imap.openBox("INBOX", false, function (err, box) { if (err) { console.log("Error opening inbox"); return; } inboxBox = box; // 保存box对象供后续获取邮件总数 }); }); imap.on("error", function (err) { console.log(err); }); imap.on("close", function (err) { console.log("connection closed"); }); imap.on("end", function (err) { console.log("connection ended"); }); imap.on("mail", function (newMsgNums) { console.log(`${newMsgNums} mails received!`); if (!inboxBox) { console.log("Inbox not opened yet"); return; } // 计算最新邮件的序列号范围 const startSeq = inboxBox.messages.total - newMsgNums + 1; const endSeq = inboxBox.messages.total; // 直接获取该范围的邮件 var fetchQuery = imap.fetch(`${startSeq}:${endSeq}`, { bodies: [""], struct: true, }); fetchQuery.on("message", function (msg, seqno) { msg.on("body", async function (stream, info) { console.log(stream); }); msg.on("attributes", function (attrs) { console.log(attrs); }); msg.on("end", function () {}); }); fetchQuery.once("error", function (err) { console.log(err); }); fetchQuery.on("end", function () {}); });
注意事项
- 方案2中必须在
openBox回调中保存box对象,才能获取实时的邮件总数。 - 使用方案1时,处理完邮件后建议通过
imap.setFlags方法标记为已读,避免后续重复获取。
内容的提问来源于stack exchange,提问作者G Madhabananda Patra
相关产品推荐
相关产品推荐

