为什么尝试使用 IMAP 获取某些电子邮件时会丢失?

问题描述 投票:0回答:2
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 messages = []

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

      f.on('message', async function (msg, seqno) {
        const messageData = {}

        msg.on('body', async function (stream, info) {
          try {
            //store the body parsing promise in the array, ASAP
            messages.push(async () => {
              const buffer = await parseMessage(stream)

              return simpleParser(buffer)
            })
          } catch (error) {
            console.error('Error parsing message:', error)
          }
        })

        msg.on('attributes', function (attrs) {
          console.log('Attributes:', inspect(attrs, false, 8))
        })

        msg.on('end', function () {
          // console.log('Finished');
        })
      })

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

      f.on('end', async function () {
        console.log('Done fetching all messages!')

        // Wait for all body parsing promises to return.
        const parsedMessages = await Promise.all(messages)
        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)
    })
  })
}

为什么在发出 IMAP 与 Next.js 集成的 API 请求时,电子邮件有时会丢失? 我尝试使用 async/await 方法,但它们没有有效地发挥作用。 这是我的代码,我试图检索所有电子邮件,包括标题和正文。 我在生产中丢失的电子邮件比本地主机还多。 我使用的node-imap版本是“^0.9.6”,我的Next.js版本是“13.2.4”

javascript node.js next.js imap node-imap
2个回答
0
投票

发生这种情况是因为 fetch 的结束事件在向您发送所有消息后被触发,但只有在完全读取消息正文后才将消息放入列表中,而这没有足够的时间。

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

        return
      }

      const messages = []

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

      f.on('message', async function (msg, seqno) {
        const messageData = {}

        msg.on('body', async function (stream, info) {
          try {
            //store the body parsing promise in the array, ASAP
            messages.push(async ()=>{
                const buffer = await parseMessage(stream);
                returnt simpleParser(buffer);
            })
          } catch (error) {
            console.error('Error parsing message:', error)
          }
        })

        msg.on('attributes', function (attrs) {
          console.log('Attributes:', inspect(attrs, false, 8))
        })

        msg.on('end', function () {
          // console.log('Finished');
        })
      })

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

      f.on('end', function () {
        console.log('Done fetching all messages!');
        // Wait for all body parsing promises to return.
        const parsedMessages = await Promise.all(messages);
        console.log('Done downloading all messages!');
        resolve(parsedMessages)
      })
    })
  })
}

这里我们所做的是将主体 Promise 保存在数组中,这样我们就知道要等待什么。然后我们等待他们,然后再解决主要的承诺。


0
投票
import { simpleParser } from 'mailparser'

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

 const client = new ImapFlow({
   host: cred.server,
   port: 993,
   secure: true,
   auth: {
     user: cred.email,
     pass: cred.password
   }
 })

 await client.connect()

 const mailbox = await client.getMailboxLock('INBOX')
 try {
   const messages = await fetchMessages(client)
   console.log('messages', messages)
   res.status(200).json(messages)
 } finally {
   mailbox.release()
 }

 await client.logout()
} catch (error) {
 console.error('Error:', error)
 res.status(500).json({ error: 'An unexpected error occurred' })
}
}

async function fetchMessages(client) {
const messages = []

for await (const message of client.fetch('1:*', { source: true })) {
 const parsedMessage = await simpleParser(message.source)
 messages.push(parsedMessage)
}

return messages
}

我已经通过替换库 node-imap == > imapflow 解决了这个问题 imapflow

© www.soinside.com 2019 - 2024. All rights reserved.