From 70f3ffb266fe415df2e2838dce7a082ea8621a58 Mon Sep 17 00:00:00 2001 From: Ryan Liu Date: Fri, 24 Apr 2026 18:06:13 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=94=AF=E6=8C=81=E6=96=B0=E7=89=88=20C?= =?UTF-8?q?hatGPT=20=E7=99=BB=E5=BD=95=E9=AA=8C=E8=AF=81=E7=A0=81=E9=82=AE?= =?UTF-8?q?=E4=BB=B6=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/gmail-mail.js | 3 +++ content/icloud-mail.js | 3 +++ content/inbucket-mail.js | 5 ++++- content/mail-163.js | 7 +++++-- content/mail-2925.js | 5 ++++- content/qq-mail.js | 3 +++ hotmail-utils.js | 3 +++ luckmail-utils.js | 3 +++ tests/hotmail-utils.test.js | 10 ++++++++++ tests/icloud-mail-content.test.js | 14 ++++++++++++++ tests/luckmail-utils.test.js | 14 ++++++++++++++ tests/mail-163-content.test.js | 14 ++++++++++++++ tests/mail-2925-content.test.js | 15 +++++++++++++++ 13 files changed, 95 insertions(+), 4 deletions(-) diff --git a/content/gmail-mail.js b/content/gmail-mail.js index 54d43ac..3444d6e 100644 --- a/content/gmail-mail.js +++ b/content/gmail-mail.js @@ -171,6 +171,9 @@ function extractVerificationCode(text) { const cnMatch = normalized.match(/(?:验证码|代码)[^0-9]{0,16}(\d{6})/i); if (cnMatch) return cnMatch[1]; + const openAiLoginMatch = normalized.match(/(?:chatgpt\s+log-?in\s+code|enter\s+this\s+code)[^0-9]{0,24}(\d{6})/i); + if (openAiLoginMatch) return openAiLoginMatch[1]; + const enMatch = normalized.match(/(?:verification\s+code|temporary\s+verification\s+code|your\s+chatgpt\s+code|code(?:\s+is)?)[^0-9]{0,16}(\d{6})/i); if (enMatch) return enMatch[1]; diff --git a/content/icloud-mail.js b/content/icloud-mail.js index 35c6d44..adc402f 100644 --- a/content/icloud-mail.js +++ b/content/icloud-mail.js @@ -82,6 +82,9 @@ if (isTopFrame) { const matchCn = text.match(/(?:代码为|验证码[^0-9]*?)[\s::]*(\d{6})/); if (matchCn) return matchCn[1]; + const matchOpenAiLogin = text.match(/(?:chatgpt\s+log-?in\s+code|enter\s+this\s+code)[^0-9]{0,24}(\d{6})/i); + if (matchOpenAiLogin) return matchOpenAiLogin[1]; + const matchEn = text.match(/code[:\s]+is[:\s]+(\d{6})|code[:\s]+(\d{6})/i); if (matchEn) return matchEn[1] || matchEn[2]; diff --git a/content/inbucket-mail.js b/content/inbucket-mail.js index 1de5949..ade97f4 100644 --- a/content/inbucket-mail.js +++ b/content/inbucket-mail.js @@ -64,6 +64,9 @@ function extractVerificationCode(text) { const matchCn = text.match(/(?:代码为|验证码[^0-9]*?)[\s::]*(\d{6})/); if (matchCn) return matchCn[1]; + const matchOpenAiLogin = text.match(/(?:chatgpt\s+log-?in\s+code|enter\s+this\s+code)[^0-9]{0,24}(\d{6})/i); + if (matchOpenAiLogin) return matchOpenAiLogin[1]; + const matchEn = text.match(/code[:\s]+is[:\s]+(\d{6})|code[:\s]+(\d{6})/i); if (matchEn) return matchEn[1] || matchEn[2]; @@ -85,7 +88,7 @@ function rowMatchesFilters(mail, senderFilters, subjectFilters, targetEmail) { const mailboxMatch = Boolean(targetLocal) && mailbox.includes(targetLocal); const forwardedDuck = /duckduckgo|forward(?:ed)?\s*by/i.test(mail.combinedText); const code = extractVerificationCode(mail.combinedText); - const keywordMatch = /openai|chatgpt|verify|verification|confirm|login|验证码|代码/.test(combined); + const keywordMatch = /openai|chatgpt|verify|verification|confirm|log-?in|验证码|代码/.test(combined); if (mailboxMatch) return { matched: true, mailboxMatch, code }; if (senderMatch || subjectMatch) return { matched: true, mailboxMatch: false, code }; diff --git a/content/mail-163.js b/content/mail-163.js index edab71b..f31608a 100644 --- a/content/mail-163.js +++ b/content/mail-163.js @@ -114,7 +114,7 @@ function isLikelyMailItemNode(node) { return false; } - return /发件人|验证码|verification|chatgpt|openai|code/i.test(summaryText); + return /发件人|验证码|verification|chatgpt|openai|code|log-?in/i.test(summaryText); } function findMailItems() { @@ -391,7 +391,7 @@ function selectOpenedMailTextCandidate(item, candidates = [], options = {}) { if (sender && lower.includes(sender)) { return true; } - return Boolean(extractVerificationCode(candidate) && /chatgpt|openai|verification|验证码|login code/i.test(lower)); + return Boolean(extractVerificationCode(candidate) && /chatgpt|openai|verification|验证码|log-?in\s+code/i.test(lower)); }) || source[0] || ''; const filteredCandidates = candidates.filter((candidate) => !excludedSet.has(normalizeText(candidate))); @@ -704,6 +704,9 @@ function extractVerificationCode(text) { const matchCn = text.match(/(?:代码为|验证码[^0-9]*?)[\s::]*(\d{6})/); if (matchCn) return matchCn[1]; + const matchOpenAiLogin = text.match(/(?:chatgpt\s+log-?in\s+code|enter\s+this\s+code)[^0-9]{0,24}(\d{6})/i); + if (matchOpenAiLogin) return matchOpenAiLogin[1]; + const matchEn = text.match(/code[:\s]+is[:\s]+(\d{6})|code[:\s]+(\d{6})/i); if (matchEn) return matchEn[1] || matchEn[2]; diff --git a/content/mail-2925.js b/content/mail-2925.js index 4263f87..1e698c4 100644 --- a/content/mail-2925.js +++ b/content/mail-2925.js @@ -670,7 +670,7 @@ function matchesMailFilters(text, senderFilters, subjectFilters) { function extractVerificationCode(text, strictChatGPTCodeOnly = false) { if (strictChatGPTCodeOnly) { - const strictMatch = String(text || '').match(/your\s+chatgpt\s+code\s+is\s+(\d{6})/i); + const strictMatch = String(text || '').match(/(?:your\s+chatgpt\s+code\s+is|(?:chatgpt\s+log-?in\s+code|suspicious\s+log-?in)[\s\S]{0,120}enter\s+this\s+code)[^0-9]{0,24}(\d{6})/i); return strictMatch ? strictMatch[1] : null; } @@ -679,6 +679,9 @@ function extractVerificationCode(text, strictChatGPTCodeOnly = false) { const matchCn = normalized.match(/(?:代码为|验证码[^0-9]*?)[\s::]*(\d{6})/); if (matchCn) return matchCn[1]; + const matchOpenAiLogin = normalized.match(/(?:chatgpt\s+log-?in\s+code|enter\s+this\s+code)[^0-9]{0,24}(\d{6})/i); + if (matchOpenAiLogin) return matchOpenAiLogin[1]; + const matchChatGPT = normalized.match(/your\s+chatgpt\s+code\s+is\s+(\d{6})/i); if (matchChatGPT) return matchChatGPT[1]; diff --git a/content/qq-mail.js b/content/qq-mail.js index fe21bb5..dc72ca1 100644 --- a/content/qq-mail.js +++ b/content/qq-mail.js @@ -174,6 +174,9 @@ function extractVerificationCode(text) { const matchCn = text.match(/(?:代码为|验证码[^0-9]*?)[\s::]*(\d{6})/); if (matchCn) return matchCn[1]; + const matchOpenAiLogin = text.match(/(?:chatgpt\s+log-?in\s+code|enter\s+this\s+code)[^0-9]{0,24}(\d{6})/i); + if (matchOpenAiLogin) return matchOpenAiLogin[1]; + // Pattern 2: English format "code is 370794" or "code: 370794" const matchEn = text.match(/code[:\s]+is[:\s]+(\d{6})|code[:\s]+(\d{6})/i); if (matchEn) return matchEn[1] || matchEn[2]; diff --git a/hotmail-utils.js b/hotmail-utils.js index 5d736ca..14103c6 100644 --- a/hotmail-utils.js +++ b/hotmail-utils.js @@ -38,6 +38,9 @@ const matchCn = source.match(/(?:代码为|验证码[^0-9]*?)[\s::]*(\d{6})/i); if (matchCn) return matchCn[1]; + const matchOpenAiLogin = source.match(/(?:chatgpt\s+log-?in\s+code|enter\s+this\s+code)[^0-9]{0,24}(\d{6})/i); + if (matchOpenAiLogin) return matchOpenAiLogin[1]; + const matchEn = source.match(/code(?:\s+is|[\s:])+(\d{6})/i); if (matchEn) return matchEn[1]; diff --git a/luckmail-utils.js b/luckmail-utils.js index e4b404d..34f9af2 100644 --- a/luckmail-utils.js +++ b/luckmail-utils.js @@ -89,6 +89,9 @@ const matchCn = source.match(/(?:代码为|验证码[^0-9]*?)[\s::]*(\d{6})/i); if (matchCn) return matchCn[1]; + const matchOpenAiLogin = source.match(/(?:chatgpt\s+log-?in\s+code|enter\s+this\s+code)[^0-9]{0,24}(\d{6})/i); + if (matchOpenAiLogin) return matchOpenAiLogin[1]; + const matchChatGPT = source.match(/your\s+chatgpt\s+code\s+is\s+(\d{6})/i); if (matchChatGPT) return matchChatGPT[1]; diff --git a/tests/hotmail-utils.test.js b/tests/hotmail-utils.test.js index 0a31ba6..5518ff2 100644 --- a/tests/hotmail-utils.test.js +++ b/tests/hotmail-utils.test.js @@ -181,6 +181,7 @@ test('shouldClearHotmailCurrentSelection returns true only when account becomes test('extractVerificationCode returns first six-digit code from multilingual mail text', () => { assert.equal(extractVerificationCode('你的 ChatGPT 验证码为 370794,请勿泄露。'), '370794'); assert.equal(extractVerificationCode('Your verification code is 654321.'), '654321'); + assert.equal(extractVerificationCode('ChatGPT Log-in Code\nIf that was you, enter this code:\n\n982219'), '982219'); assert.equal(extractVerificationCode('No code here'), null); }); @@ -202,6 +203,15 @@ test('extractVerificationCodeFromMessage reads code from the latest message subj }), '654321' ); + + assert.equal( + extractVerificationCodeFromMessage({ + subject: 'ChatGPT Log-in Code', + bodyPreview: 'We noticed a suspicious log-in on your account. If that was you, enter this code:\n\n982219', + from: { emailAddress: { address: 'noreply@openai.com' } }, + }), + '982219' + ); }); test('getHotmailListToggleLabel reflects expanded state and account count', () => { diff --git a/tests/icloud-mail-content.test.js b/tests/icloud-mail-content.test.js index 42a7cac..269776b 100644 --- a/tests/icloud-mail-content.test.js +++ b/tests/icloud-mail-content.test.js @@ -81,6 +81,20 @@ return { readOpenedMailBody, extractVerificationCode }; assert.equal(api.extractVerificationCode(bodyText), '731091'); }); +test('extractVerificationCode matches the new suspicious log-in mail body', () => { + const bundle = [ + extractFunction('extractVerificationCode'), + ].join('\n'); + + const api = new Function(` +${bundle} +return { extractVerificationCode }; +`)(); + + const bodyText = 'ChatGPT Log-in Code\nWe noticed a suspicious log-in on your account. If that was you, enter this code:\n\n982219'; + assert.equal(api.extractVerificationCode(bodyText), '982219'); +}); + test('readOpenedMailBody ignores conversation list rows when no detail pane is open', () => { const bundle = [ extractFunction('normalizeText'), diff --git a/tests/luckmail-utils.test.js b/tests/luckmail-utils.test.js index 1d9acbc..ccf4ecd 100644 --- a/tests/luckmail-utils.test.js +++ b/tests/luckmail-utils.test.js @@ -68,6 +68,20 @@ test('normalizeLuckmailTokenCode and normalizeLuckmailTokenMail extract verifica assert.equal(normalizedMail.verification_code, '654321'); assert.equal(extractLuckmailVerificationCode('你的验证码为 778899'), '778899'); + assert.equal( + extractLuckmailVerificationCode('ChatGPT Log-in Code\nIf that was you, enter this code:\n\n982219'), + '982219' + ); + + const suspiciousLoginMail = normalizeLuckmailTokenMail({ + message_id: 'mail-3', + from: 'noreply@openai.com', + subject: 'ChatGPT Log-in Code', + body: 'We noticed a suspicious log-in on your account. If that was you, enter this code:\n\n982219', + received_at: '2026-04-14T10:02:00Z', + }); + + assert.equal(suspiciousLoginMail.verification_code, '982219'); }); test('normalizeLuckmailProjectName and isLuckmailPurchaseForProject match openai case-insensitively', () => { diff --git a/tests/mail-163-content.test.js b/tests/mail-163-content.test.js index 72f7bd6..e3be17d 100644 --- a/tests/mail-163-content.test.js +++ b/tests/mail-163-content.test.js @@ -340,6 +340,20 @@ return { openMailAndGetMessageText, mailItem }; assert.doesNotMatch(text, /111111/); }); +test('extractVerificationCode matches the new suspicious log-in mail body', () => { + const bundle = [ + extractFunction('extractVerificationCode'), + ].join('\n'); + + const api = new Function(` +${bundle} +return { extractVerificationCode }; +`)(); + + const bodyText = 'ChatGPT Log-in Code\nWe noticed a suspicious log-in on your account. If that was you, enter this code:\n\n982219'; + assert.equal(api.extractVerificationCode(bodyText), '982219'); +}); + test('handlePollEmail ignores same-minute old snapshot mail before fallback', async () => { const bundle = [ extractFunction('normalizeText'), diff --git a/tests/mail-2925-content.test.js b/tests/mail-2925-content.test.js index f923d7f..29f5306 100644 --- a/tests/mail-2925-content.test.js +++ b/tests/mail-2925-content.test.js @@ -546,6 +546,21 @@ return { ]); }); +test('extractVerificationCode strict mode matches the new suspicious log-in mail body', () => { + const bundle = [ + extractFunction('extractVerificationCode'), + ].join('\n'); + + const api = new Function(` +${bundle} +return { extractVerificationCode }; +`)(); + + const bodyText = 'ChatGPT Log-in Code\nWe noticed a suspicious log-in on your account. If that was you, enter this code:\n\n982219'; + assert.equal(api.extractVerificationCode(bodyText, true), '982219'); + assert.equal(api.extractVerificationCode(bodyText, false), '982219'); +}); + test('openMailAndGetMessageText always returns to inbox after opening a 2925 message', async () => { const bundle = [ extractFunction('returnToInbox'),