You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js集成node-IMAP调用API时邮件丢失问题求助

邮件丢失问题排查与修复

核心问题分析

你的代码存在两个关键逻辑错误,直接导致邮件丢失,且生产环境因网络延迟问题更严重:

  1. 错误存储异步函数而非Promise
    在msg.on('body')中,你将异步函数存入messages数组,但Promise.all只会处理Promise实例,不会自动执行这些函数。这意味着大部分邮件的解析逻辑根本没有运行,自然不会出现在结果中。

  2. fetch的end事件触发过早
    生产环境网络延迟更高,node-imap的seq.fetch触发end事件时,部分邮件的body事件可能还未触发(网络传输慢导致),此时messages数组还没收集到所有邮件的解析任务,最终结果就会缺失这些邮件。

修复后的代码

import Imap from 'node-imap'
import { simpleParser } from 'mailparser'
import { inspect } from 'util'

export default async function handler(req, res) {
  try {
    const cred = req.body

    const imap = new Imap({
      user: cred.email,
      password: cred.password,
      host: cred.server,
      port: 993,
      tls: true
    })

    imap.on('ready', async function () {
      try {
        const messages = await fetchMessages(imap)
        res.status(200).json(messages)
      } catch (error) {
        console.error('Error fetching messages:', error)
        res.status(500).json({ error: 'An error occurred while fetching messages' })
      } finally {
        imap.end()
      }
    })

    imap.once('error', function (err) {
      console.error('IMAP Error:', err)
      res.status(500).json({ error: 'An error occurred while connecting to the mail server' })
    })

    imap.once('end', function () {
      console.log('Connection ended')
    })

    imap.connect()
  } catch (error) {
    console.error('Error:', error)
    res.status(500).json({ error: 'An unexpected error occurred' })
  }
}

async function fetchMessages(imap) {
  return new Promise((resolve, reject) => {
    imap.openBox('INBOX', true, (err, box) => {
      if (err) {
        reject(err)
        return
      }

      const messagePromises = []

      const f = imap.seq.fetch('1:*', {
        bodies: '',
        struct: true
      })

      f.on('message', function (msg, seqno) {
        // 为每封邮件创建一个Promise,确保完整解析后再加入数组
        const messagePromise = new Promise((resolveMsg, rejectMsg) => {
          let parsedEmail = null
          let emailAttributes = null

          msg.on('body', async function (stream, info) {
            try {
              const buffer = await parseMessage(stream)
              parsedEmail = await simpleParser(buffer)
              // 当属性和正文都就绪时,返回完整邮件数据
              if (emailAttributes) {
                resolveMsg({ ...parsedEmail, attributes: emailAttributes })
              }
            } catch (error) {
              console.error('Error parsing message body:', error)
              rejectMsg(error)
            }
          })

          msg.on('attributes', function (attrs) {
            emailAttributes = attrs
            // 当属性和正文都就绪时,返回完整邮件数据
            if (parsedEmail) {
              resolveMsg({ ...parsedEmail, attributes: emailAttributes })
            }
          })

          msg.on('error', function (err) {
            console.error('Message error:', err)
            rejectMsg(err)
          })
        })

        messagePromises.push(messagePromise)
      })

      f.on('error', function (err) {
        console.error('Fetch error:', err)
        reject(err)
      })

      f.on('end', async function () {
        console.log('Done fetching all message metadata!')
        // 等待所有邮件的解析Promise完成
        const parsedMessages = await Promise.all(messagePromises)
        console.log('Done downloading all messages!')
        resolve(parsedMessages)
      })
    })
  })
}

function parseMessage(stream) {
  return new Promise((resolve, reject) => {
    let buffer = ''
    stream.on('data', function (chunk) {
      buffer += chunk.toString('utf8')
    })
    stream.on('end', function () {
      resolve(buffer)
    })
    stream.on('error', function (err) {
      reject(err)
    })
  })
}

关键修改说明

  • 为每封邮件创建独立Promise:在message事件中,给每封邮件生成一个Promise,等待body和attributes都处理完成后再resolve,确保不会遗漏任何邮件的解析。
  • 存储Promise而非异步函数:将每封邮件的Promise直接存入messagePromises数组,Promise.all会正确等待所有Promise完成。
  • 处理邮件内部的错误:新增msg.on('error')捕获单封邮件的解析错误,避免单个邮件失败导致整个任务终止。

内容的提问来源于stack exchange,提问作者sanal ms

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 13:45:31