From b71bccaf8ad4c7477a616afffdc846df218ff27d Mon Sep 17 00:00:00 2001 From: Isulew <224964+netcookies@users.noreply.github.com> Date: Mon, 27 Apr 2026 13:57:51 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=202925=20=E6=94=B6?= =?UTF-8?q?=E4=BB=B6=E6=A8=A1=E5=BC=8F=E8=BD=AE=E8=AF=A2=E4=B8=8E=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E6=B3=A8=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - receive 模式下跳过 2925 邮箱页顶部账号校验 - 解析 bounce 转发地址与中文日期,避免误过滤验证码邮件 - 为内容脚本增加重复注入保护,避免重复声明导致轮询失效 --- background/steps/fetch-login-code.js | 4 ++ background/steps/fetch-signup-code.js | 4 ++ content/mail-2925.js | 60 ++++++++++++++++++++++++++- content/signup-page.js | 2 + content/utils.js | 10 ++--- tests/mail-2925-content.test.js | 1 + 6 files changed, 74 insertions(+), 7 deletions(-) diff --git a/background/steps/fetch-login-code.js b/background/steps/fetch-login-code.js index c25b2f4..41b0e3b 100644 --- a/background/steps/fetch-login-code.js +++ b/background/steps/fetch-login-code.js @@ -69,6 +69,10 @@ } function getExpectedMail2925MailboxEmail(state = {}) { + if (String(state?.mail2925Mode || '').trim().toLowerCase() === 'receive') { + return ''; + } + if (Boolean(state?.mail2925UseAccountPool)) { const currentAccountId = String(state?.currentMail2925AccountId || '').trim(); const accounts = Array.isArray(state?.mail2925Accounts) ? state.mail2925Accounts : []; diff --git a/background/steps/fetch-signup-code.js b/background/steps/fetch-signup-code.js index 88778a3..791d0c2 100644 --- a/background/steps/fetch-signup-code.js +++ b/background/steps/fetch-signup-code.js @@ -26,6 +26,10 @@ } = deps; function getExpectedMail2925MailboxEmail(state = {}) { + if (String(state?.mail2925Mode || '').trim().toLowerCase() === 'receive') { + return ''; + } + if (Boolean(state?.mail2925UseAccountPool)) { const currentAccountId = String(state?.currentMail2925AccountId || '').trim(); const accounts = Array.isArray(state?.mail2925Accounts) ? state.mail2925Accounts : []; diff --git a/content/mail-2925.js b/content/mail-2925.js index 1e698c4..4b723e2 100644 --- a/content/mail-2925.js +++ b/content/mail-2925.js @@ -1,6 +1,13 @@ // content/mail-2925.js - Content script for 2925 Mail (steps 4, 8) // Injected dynamically on: 2925.com +(function initMail2925ContentScript() { +if (window.__MULTIPAGE_MAIL2925_SCRIPT_LOADED__) { + console.log('[MultiPage:mail-2925] Duplicate injection skipped on', location.href); + return; +} +window.__MULTIPAGE_MAIL2925_SCRIPT_LOADED__ = true; + const MAIL2925_PREFIX = '[MultiPage:mail-2925]'; const isTopFrame = window === window.top; @@ -699,10 +706,29 @@ function extractEmails(text = '') { return [...new Set(matches.map((item) => item.toLowerCase()))]; } +function extractForwardedTargetEmails(text = '') { + const normalizedText = String(text || '').toLowerCase(); + const matches = normalizedText.match(/bounce\+[a-z0-9._%+-]*-([a-z0-9._%+-]+)=([a-z0-9.-]+\.[a-z]{2,})@(?:tm\d*\.openai\.com|em\d+\.tm\.openai\.com)/gi) || []; + const decoded = matches + .map((candidate) => { + const match = String(candidate || '').match(/bounce\+[a-z0-9._%+-]*-([a-z0-9._%+-]+)=([a-z0-9.-]+\.[a-z]{2,})@/i); + if (!match) { + return ''; + } + return `${match[1].toLowerCase()}@${match[2].toLowerCase()}`; + }) + .filter(Boolean); + return [...new Set(decoded)]; +} + function emailMatchesTarget(candidate, targetEmail) { const normalizedCandidate = String(candidate || '').trim().toLowerCase(); const normalizedTarget = String(targetEmail || '').trim().toLowerCase(); - return Boolean(normalizedCandidate && normalizedTarget && normalizedCandidate === normalizedTarget); + if (!normalizedCandidate || !normalizedTarget) { + return false; + } + + return normalizedCandidate === normalizedTarget; } function getTargetEmailMatchState(text, targetEmail) { @@ -717,12 +743,30 @@ function getTargetEmailMatchState(text, targetEmail) { } const extractedEmails = extractEmails(normalizedText); + const forwardedTargetEmails = extractForwardedTargetEmails(normalizedText); if (!extractedEmails.length) { + return forwardedTargetEmails.length + ? { + matches: forwardedTargetEmails.some((candidate) => emailMatchesTarget(candidate, normalizedTarget)), + hasExplicitEmail: true, + } + : { matches: true, hasExplicitEmail: false }; + } + + const targetDomain = normalizedTarget.includes('@') + ? normalizedTarget.split('@').pop() + : ''; + const comparableEmails = [...new Set( + (targetDomain + ? [...extractedEmails, ...forwardedTargetEmails].filter((candidate) => String(candidate || '').trim().toLowerCase().endsWith(`@${targetDomain}`)) + : [...extractedEmails, ...forwardedTargetEmails]) + )]; + if (!comparableEmails.length) { return { matches: true, hasExplicitEmail: false }; } return { - matches: extractedEmails.some((candidate) => emailMatchesTarget(candidate, normalizedTarget)), + matches: comparableEmails.some((candidate) => emailMatchesTarget(candidate, normalizedTarget)), hasExplicitEmail: true, }; } @@ -782,6 +826,17 @@ function parseMailItemTimestamp(item) { return date.getTime(); } + match = timeText.match(/(\d{1,2})月(\d{1,2})日(?:\s*(\d{1,2}):(\d{2}))?/); + if (match) { + date.setMonth(Number(match[1]) - 1, Number(match[2])); + if (match[3] && match[4]) { + date.setHours(Number(match[3]), Number(match[4]), 0, 0); + } else { + date.setHours(0, 0, 0, 0); + } + return date.getTime(); + } + match = timeText.match(/(\d{4})-(\d{1,2})-(\d{1,2})\s*(\d{1,2}):(\d{2})/); if (match) { return new Date( @@ -1168,3 +1223,4 @@ async function handlePollEmail(step, payload) { } } +})(); diff --git a/content/signup-page.js b/content/signup-page.js index f36207b..c742b51 100644 --- a/content/signup-page.js +++ b/content/signup-page.js @@ -2,6 +2,7 @@ // Injected on: auth0.openai.com, auth.openai.com, accounts.openai.com // Dynamically injected on: chatgpt.com +(function initSignupPageContentScript() { console.log('[MultiPage:signup-page] Content script loaded on', location.href); const SIGNUP_PAGE_LISTENER_SENTINEL = 'data-multipage-signup-page-listener'; @@ -3560,3 +3561,4 @@ async function step5_fillNameBirthday(payload) { log('步骤 5:已点击“完成帐户创建”,当前步骤直接完成,不再等待页面结果。'); return completionPayload; } +})(); diff --git a/content/utils.js b/content/utils.js index f208aca..71e711e 100644 --- a/content/utils.js +++ b/content/utils.js @@ -1,6 +1,6 @@ // content/utils.js — Shared utilities for all content scripts -const getActivationStrategy = self.MultiPageActivationUtils?.getActivationStrategy; +var getActivationStrategy = self.MultiPageActivationUtils?.getActivationStrategy; function detectScriptSource({ injectedSource, @@ -26,7 +26,7 @@ function detectScriptSource({ return 'vps-panel'; } -const SCRIPT_SOURCE = (() => { +var SCRIPT_SOURCE = (() => { return detectScriptSource({ injectedSource: window.__MULTIPAGE_SOURCE, url: location.href, @@ -38,9 +38,9 @@ function getRuntimeScriptSource() { return window.__MULTIPAGE_SOURCE || SCRIPT_SOURCE; } -const LOG_PREFIX = `[MultiPage:${SCRIPT_SOURCE}]`; -const STOP_ERROR_MESSAGE = '流程已被用户停止。'; -let flowStopped = false; +var LOG_PREFIX = `[MultiPage:${SCRIPT_SOURCE}]`; +var STOP_ERROR_MESSAGE = '流程已被用户停止。'; +var flowStopped = false; if (!window.__MULTIPAGE_UTILS_LISTENER_READY__) { window.__MULTIPAGE_UTILS_LISTENER_READY__ = true; diff --git a/tests/mail-2925-content.test.js b/tests/mail-2925-content.test.js index 29f5306..c824ee0 100644 --- a/tests/mail-2925-content.test.js +++ b/tests/mail-2925-content.test.js @@ -319,6 +319,7 @@ return { test('handlePollEmail skips explicit mismatched target emails when receive-mode matching is enabled', async () => { const bundle = [ extractFunction('extractEmails'), + extractFunction('extractForwardedTargetEmails'), extractFunction('emailMatchesTarget'), extractFunction('getTargetEmailMatchState'), extractFunction('normalizeMinuteTimestamp'),