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”
发生这种情况是因为 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 保存在数组中,这样我们就知道要等待什么。然后我们等待他们,然后再解决主要的承诺。
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