// 协议注册 wrapper —— 复用 get-rt.js 的无密码 OAuth 协议流程(步骤1~6), // 但 OTP 不再从 Outlook 读,而是经 Flask /api/reg/inbox 从「邮箱池」读取(IMAP / 取件API)。 // 输入(stdin JSON):{ email, settings, proxy, otpBase } // 输出: // - 过程日志:逐行写 stderr,每行 JSON { level, msg, account } // - 最终结果:stdout 一段 JSON(getRefreshToken 返回结构) // 成功 { ok:true, refreshToken, clientId, accessToken, idToken } // 失败 { ok:false, banned?, reason?, error } import { getRefreshToken } from './get-rt.js'; import { resolveRegPassword } from './reg_password.mjs'; // get-rt.js / plus-mailbox.js 里的 console.* 默认写 stdout,会污染结果 JSON,统一改到 stderr。 const _errWrite = (...a) => { try { process.stderr.write(a.map(String).join(' ') + '\n'); } catch { /* ignore */ } }; console.log = _errWrite; console.info = _errWrite; console.warn = _errWrite; function readStdin() { return new Promise((resolve) => { let buf = ''; process.stdin.setEncoding('utf8'); process.stdin.on('data', (c) => { buf += c; }); process.stdin.on('end', () => resolve(buf)); }); } function emitLog(level, msg, account) { try { process.stderr.write(JSON.stringify({ level, msg: String(msg), account: account || '' }) + '\n'); } catch { /* ignore */ } } (async () => { let email = ''; try { const input = JSON.parse((await readStdin()) || '{}'); email = input.email || ''; const settings = input.settings || {}; const proxy = input.proxy || null; const otpBase = String(input.otpBase || 'http://127.0.0.1:5088').replace(/\/$/, ''); if (!email) throw new Error('缺少邮箱'); // 从邮箱池(经 Flask)读取收件箱,形状与 plus-mailbox 一致: // { messages: [{ from_addr, subject, body, received_at, extracted_code }] } const fetchInbox = async (account /* , limit */) => { const addr = (account && account.email) || email; const url = `${otpBase}/api/reg/inbox?email=${encodeURIComponent(addr)}`; const res = await fetch(url, { method: 'GET' }); if (!res.ok) throw new Error('读取邮箱失败 HTTP ' + res.status); const data = await res.json().catch(() => ({})); return { messages: (data && data.messages) || [] }; }; const password = resolveRegPassword(input, settings); const result = await getRefreshToken({ email }, { settings, proxy, register: true, password, log: (level, msg, acc) => emitLog(level, msg, acc || email), fetchInbox, }); // getRefreshToken 成功仅返回 {refreshToken,...},补 ok:true 供上游判断,并回传密码用于落库/导出账密 if (result && result.refreshToken) { result.ok = true; result.password = password; } process.stdout.write(JSON.stringify(result)); } catch (e) { emitLog('error', (e && e.message) || String(e), email); process.stdout.write(JSON.stringify({ ok: false, banned: false, error: (e && e.message) || String(e) })); } })();