WishMeLz

生活其实很有趣

nodejs 对接邮箱服务 imap

const Imap = require("node-imap");
const { simpleParser } = require("mailparser");
const conn = require("./db");
// IMAP 配置
const imapConfig = {
    user: "xxx",
    password: "xxx",
    host: "eu1.workspace.org", // 你的域名邮箱 IMAP 服务器
    // port: 993,
    // tls: true,
    port: 143,
    tls: false,
    tlsOptions: {
        rejectUnauthorized: false,
    },
    connTimeout: 60000, // 60秒连接超时
    authTimeout: 30000, // 30秒认证超时
};

const imap = new Imap(imapConfig);

function fetchEmails() {
    return new Promise((resolve, reject) => {
        imap.once("ready", () => {
            // 打开收件箱
            imap.openBox("INBOX", false, (err, box) => {
                if (err) {
                    reject(err);
                    return;
                }

                console.log(`收件箱总邮件数: ${box.messages.total}`);

                // 搜索邮件 - 按日期排序获取最新邮件
                imap.search(["ALL"], (err, results) => {
                    if (err) {
                        reject(err);
                        return;
                    }

                    if (results.length === 0) {
                        console.log("没有找到邮件");
                        imap.end();
                        resolve([]);
                        return;
                    }

                    const recentEmails = results.slice(-5); // 获取最后5个(最新的)
                    console.log(`获取最新${recentEmails.length}封邮件,UID: ${recentEmails.join(", ")}`);

                    const emails = [];
                    let processedCount = 0; // 追踪已处理的邮件数量

                    const fetch = imap.fetch(recentEmails, {
                        bodies: "",
                        struct: true,
                    });

                    fetch.on("message", (msg, seqno) => {
                        console.log(`开始处理邮件 seqno: ${seqno}`);

                        let emailData = {
                            seqno: seqno,
                            headers: {},
                            body: "",
                        };

                        msg.on("body", (stream, info) => {
                            let buffer = "";

                            stream.on("data", (chunk) => {
                                buffer += chunk.toString("utf8");
                            });
                            stream.once("end", () => {
                                simpleParser(buffer)
                                    .then((parsed) => {
                                        let resdata = parsedData(parsed);
                                        emails.push(resdata);
                                        processedCount++;

                                        // 检查是否所有邮件都处理完成
                                        if (processedCount === recentEmails.length) {
                                            console.log(`所有${processedCount}封邮件处理完成`);
                                            // 按日期排序,最新的在前
                                            emails.sort((a, b) => new Date(b.date) - new Date(a.date));
                                            imap.end();
                                            resolve(emails);
                                        }
                                    })
                                    .catch((parseErr) => {
                                        console.error(`解析邮件失败 seqno ${seqno}:`, parseErr);
                                        processedCount++;

                                        // 解析失败也检查是否完成
                                        if (processedCount === recentEmails.length) {
                                            imap.end();
                                            resolve(emails);
                                        }
                                    });
                            });
                        });
                    });

                    fetch.once("error", (err) => {
                        console.error("获取邮件出错:", err);
                        reject(err);
                    });

                    fetch.once("end", () => {
                        console.log("邮件获取流程结束");
                        // 注意:这里不要调用resolve,因为可能还有邮件在解析中
                        // resolve的调用在上面的simpleParser.then()中
                    });
                });
            });
        });

        imap.once("error", (err) => {
            console.error("IMAP连接错误:", err);
            reject(err);
        });

        // 如果imap还没连接,则连接
        if (imap.state !== "authenticated") {
            imap.connect();
        }
    });
}

// 使用示例
async function main() {
    try {
        const emails = await fetchEmails();
        console.log(`获取到 ${emails.length} 封邮件`);
        emails.forEach((email, index) => {
            console.log(`\n=== 邮件 ${index + 1} ===`);
            console.log("主题:", email.subject);
            console.log("发件人:", email.from?.text);
            console.log("收件人:", email.to?.text);
            console.log("日期:", email.date);
            console.log("内容预览:", email.text?.substring(0, 50) + "...");
        });
    } catch (error) {
        console.error("获取邮件失败:", error);
    }
}

// 数据邮件解析数据
function parsedData(parsed) {
    const senderInfo = parsed.from ? parsed.from.value[0] : {};
    const recipientInfo = parsed.to ? parsed.to.value[0] : {};
    return {
        messageId: parsed.messageId || "",
        subject: parsed.subject || "",
        senderName: senderInfo.name || "",
        senderEmail: senderInfo.address || "",
        recipientEmail: recipientInfo.address || "",
        sentDate: parsed.date || new Date(),
        textContent: parsed.text || "",
        htmlContent: parsed.html || "",
        hasAttachments: parsed.attachments && parsed.attachments.length > 0,
    };
}

function watchEmails() {
    const imap = new Imap(imapConfig);

    imap.once("ready", () => {
        imap.openBox("INBOX", false, (err, box) => {
            if (err) throw err;
            console.log("开始监听新邮件...");
            imap.on("mail", (numNewMsgs) => {
                console.log(`收到 ${numNewMsgs} 封新邮件`);
                // 这里可以调用 fetchEmails() 获取新邮件
                main();
            });
        });
    });

    imap.once("error", (err) => {
        console.error("IMAP 错误:", err);
    });

    imap.connect();
}

watchEmails();