使用IMAP获取Gmail未读邮件时触发TypeError错误求助
问题:通过IMAP获取Gmail未读邮件时遇TypeError错误
尝试实现基础Google API功能,用IMAP获取Gmail未读邮件时触发TypeError: str.replace is not a function错误,怀疑是IMAP连接参数错误但无法定位,相关代码、错误信息如下:
相关代码
require('dotenv').config(); const nodemailer = require('nodemailer') const { google } = require('googleapis') const Imap = require('imap'); const CLIENT_ID = process.env.GOOGLE_CLIENT_ID const CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET const REDIRECT_URI = process.env.GOOGLE_REDIRECT_URL const REFRESH_TOKEN = process.env.GOOGLE_REFRESH_TOKEN const oauht2Client = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI) oauht2Client.setCredentials({refresh_token : REFRESH_TOKEN}) function newMessages(/*onNewEmailCallback*/) { const imap = new Imap({ user: "mymail@gmail.com", xoauth2: oauht2Client.getAccessToken(), host: 'imap.gmail.com', port: 993, tls: true, tlsOptions: { rejectUnauthorized: false } }); function showError(error) { console.error('Error:', error); } function showMessage(msg) { onNewEmailCallback(msg.subject); console.log(msg.subject); } imap.connect(); imap.once('ready', () => { imap.openBox('INBOX', true, (err, box) => { if (err) showError(err); imap.on('mail', (numNewMsgs) => { imap.search(['UNSEEN'], (err, results) => { if (err) showError(err); results.forEach((result) => { const f = imap.fetch(result, { bodies: '' }); f.on('message', (msg) => { msg.on('body', (stream, info) => { let buffer = ''; stream.on('data', (chunk) => { buffer += chunk.toString('utf8'); }); stream.on('end', () => { showMessage(Imap.parseHeader(buffer)); }); }); }); }); }); }); }); }); imap.once('error', showError); imap.once('end', () => { console.log('Connection terminée'); }); return imap; }
完整错误栈
/home/lerou/B-DEV-500-COT-5-2-area-segnon.gnonlonfoun/Back-End/node_modules/imap/lib/Connection.js:1804 return str.replace(RE_BACKSLASH, '\\\\').replace(RE_DBLQUOTE, '\\"'); ^ TypeError: str.replace is not a function at escape (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Connection.js:1804:14) at Connection.<anonymous> (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Connection.js:1672:24) at Connection._resTagged (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Connection.js:1535:22) at Parser.<anonymous> (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Connection.js:194:10) at Parser.emit (node:events:512:28) at Parser._resTagged (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Parser.js:175:10) at Parser._parse (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Parser.js:139:16) at Parser._tryread (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Parser.js:82:15) at Parser._cbReadable (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Parser.js:53:12) at TLSSocket.emit (node:events:512:28)
解决方案
错误根源是**xoauth2参数传入值类型错误**:oauht2Client.getAccessToken()返回的是Promise对象,而非IMAP库所需的字符串格式访问令牌。IMAP库尝试对Promise对象调用replace方法,因此触发TypeError。
修改步骤:
- 将
newMessages改为异步函数,用await获取实际访问令牌 - 提取令牌对象中的
token属性,传入IMAP配置
修改后的代码:
require('dotenv').config(); const nodemailer = require('nodemailer') const { google } = require('googleapis') const Imap = require('imap'); const CLIENT_ID = process.env.GOOGLE_CLIENT_ID const CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET const REDIRECT_URI = process.env.GOOGLE_REDIRECT_URL const REFRESH_TOKEN = process.env.GOOGLE_REFRESH_TOKEN const oauht2Client = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI) oauht2Client.setCredentials({refresh_token : REFRESH_TOKEN}) // 改为异步函数 async function newMessages(onNewEmailCallback) { // 异步获取访问令牌并提取token属性 const accessTokenObj = await oauht2Client.getAccessToken(); const accessToken = accessTokenObj.token; const imap = new Imap({ user: "mymail@gmail.com", xoauth2: accessToken, // 传入字符串格式令牌 host: 'imap.gmail.com', port: 993, tls: true, tlsOptions: { rejectUnauthorized: false } }); function showError(error) { console.error('Error:', error); } function showMessage(msg) { onNewEmailCallback(msg.subject); console.log(msg.subject); } imap.connect(); imap.once('ready', () => { imap.openBox('INBOX', true, (err, box) => { if (err) showError(err); imap.on('mail', (numNewMsgs) => { imap.search(['UNSEEN'], (err, results) => { if (err) showError(err); results.forEach((result) => { const f = imap.fetch(result, { bodies: '' }); f.on('message', (msg) => { msg.on('body', (stream, info) => { let buffer = ''; stream.on('data', (chunk) => { buffer += chunk.toString('utf8'); }); stream.on('end', () => { showMessage(Imap.parseHeader(buffer)); }); }); }); }); }); }); }); }); imap.once('error', showError); imap.once('end', () => { console.log('Connection terminée'); }); return imap; }
调用时需处理异步逻辑:
// index.js中调用示例 newMessages((subject) => { console.log('新邮件主题:', subject); }).catch(err => console.error(err));
内容的提问来源于stack exchange,提问作者El Risitas
相关产品推荐
相关产品推荐

