Преглед изворни кода

Refine A4Sky mailbox refresh and detail reading

chendeben пре 4 месеци
родитељ
комит
9766ae45e6
2 измењених фајлова са 146 додато и 4 уклоњено
  1. 36 4
      content/phplife-mail.js
  2. 110 0
      tests/phplife-mail-content.test.js

+ 36 - 4
content/phplife-mail.js

@@ -338,6 +338,15 @@ function scoreRowCandidate(details, payload = {}) {
   return score;
 }
 
+function shouldOpenRowForCodeDetection(details = {}) {
+  const subject = normalizeText(details?.subject || '');
+  if (!subject) {
+    return false;
+  }
+
+  return /your\s+temporary\s+chatgpt\s+login\s+code/i.test(subject);
+}
+
 function getCurrentMessageUid() {
   const envUid = getRcmailEnv()?.uid;
   if (envUid) return String(envUid);
@@ -397,11 +406,12 @@ function findInboxLink() {
   return document.querySelector('#mailboxlist .mailbox.inbox a[rel="INBOX"], #mailboxlist a[rel="INBOX"]');
 }
 
-async function ensureInboxActive() {
+async function ensureInboxActive(options = {}) {
+  const { forceRefresh = false } = options;
   const inboxLink = findInboxLink();
   if (!inboxLink) return;
   const inboxItem = inboxLink.closest('.mailbox');
-  if (inboxItem?.classList?.contains('selected')) {
+  if (!forceRefresh && inboxItem?.classList?.contains('selected')) {
     return;
   }
   inboxLink.click();
@@ -409,8 +419,9 @@ async function ensureInboxActive() {
 }
 
 async function refreshMessageList() {
+  await ensureInboxActive({ forceRefresh: true });
   const refreshButton = findRefreshButton();
-  if (!refreshButton) return false;
+  if (!refreshButton) return true;
   refreshButton.click();
   await sleep(1200);
   return true;
@@ -478,10 +489,31 @@ async function tryOpenRowsAndRead(step, payload, excludedCodeSet, filterAfterMin
     }
 
     const directResult = matchesCurrentMessage(details, payload, excludedCodeSet, filterAfterMinute);
-    if (directResult.matched) {
+    const shouldOpenDetail = shouldOpenRowForCodeDetection(details);
+    if (directResult.matched && !shouldOpenDetail) {
       log(`步骤 ${step}:已直接从 mail.phplife.net 列表命中验证码邮件。`, 'ok');
       return directResult;
     }
+
+    if (!shouldOpenDetail) {
+      continue;
+    }
+
+    log(`步骤 ${step}:检测到临时登录验证码邮件标题,正在打开详情读取验证码...`, 'info');
+    const previousUid = getCurrentMessageUid();
+    openMessageRow(details.row);
+    await sleep(500);
+    const openedDetails = await waitForPreviewLoaded(previousUid);
+    const detailResult = matchesCurrentMessage(openedDetails, payload, excludedCodeSet, filterAfterMinute);
+    if (detailResult.matched) {
+      log(`步骤 ${step}:已在 mail.phplife.net 邮件详情中命中验证码。`, 'ok');
+      return detailResult;
+    }
+
+    if (directResult.matched) {
+      log(`步骤 ${step}:邮件详情未提取到验证码,已回退使用列表中的匹配结果。`, 'warn');
+      return directResult;
+    }
   }
 
   return null;

+ 110 - 0
tests/phplife-mail-content.test.js

@@ -132,3 +132,113 @@ return { getRowDetails };
   assert.equal(details.subject, 'Your ChatGPT code is 866785');
   assert.equal(details.codes[0], '866785');
 });
+
+test('phplife refreshMessageList clicks inbox before refresh button', async () => {
+  const bundle = [
+    extractFunction('ensureInboxActive'),
+    extractFunction('refreshMessageList'),
+  ].join('\n');
+
+  const api = new Function(`${bundle}
+const clickOrder = [];
+const inboxLink = {
+  closest() {
+    return { classList: { contains() { return true; } } };
+  },
+  click() {
+    clickOrder.push('inbox');
+  },
+};
+const refreshButton = {
+  click() {
+    clickOrder.push('refresh');
+  },
+};
+function findInboxLink() {
+  return inboxLink;
+}
+function findRefreshButton() {
+  return refreshButton;
+}
+async function sleep() {}
+return {
+  refreshMessageList,
+  getClickOrder() {
+    return clickOrder.slice();
+  },
+};
+`)();
+
+  await api.refreshMessageList();
+  assert.deepEqual(api.getClickOrder(), ['inbox', 'refresh']);
+});
+
+test('phplife temporary login title opens detail to extract verification code', async () => {
+  const bundle = [
+    extractFunction('normalizeText'),
+    extractFunction('normalizeMinuteTimestamp'),
+    extractFunction('shouldOpenRowForCodeDetection'),
+    extractFunction('selectCandidateCode'),
+    extractFunction('matchesCurrentMessage'),
+    extractFunction('scoreRowCandidate'),
+    extractFunction('tryOpenRowsAndRead'),
+  ].join('\n');
+
+  const api = new Function(`${bundle}
+let opened = 0;
+const seenCodes = new Set();
+function throwIfStopped() {}
+function getMessageListRows() {
+  return [{ id: 'row-1' }];
+}
+function getRowDetails() {
+  return {
+    row: { id: 'row-1' },
+    subject: 'Your temporary ChatGPT login code',
+    from: 'noreply@tm.openai.com',
+    to: 'n2026041807@a4sky.com',
+    dateText: '今天 12:30',
+    emailTimestamp: Date.now(),
+    codes: [],
+    combinedText: 'Your temporary ChatGPT login code noreply@tm.openai.com n2026041807@a4sky.com',
+  };
+}
+function matchesMailFilters() {
+  return true;
+}
+function getTargetEmailMatchState() {
+  return { matches: true, hasExplicitEmail: true };
+}
+function log() {}
+function getCurrentMessageUid() {
+  return '';
+}
+function openMessageRow() {
+  opened += 1;
+}
+async function sleep() {}
+async function waitForPreviewLoaded() {
+  return {
+    subject: 'Your temporary ChatGPT login code',
+    combinedText: 'Your temporary ChatGPT login code 998877 noreply@tm.openai.com n2026041807@a4sky.com',
+    emailTimestamp: Date.now(),
+    codes: ['998877'],
+  };
+}
+return {
+  tryOpenRowsAndRead,
+  getOpenedCount() {
+    return opened;
+  },
+};
+`)();
+
+  const result = await api.tryOpenRowsAndRead(4, {
+    senderFilters: ['openai'],
+    subjectFilters: ['login', 'code'],
+    targetEmail: 'n2026041807@a4sky.com',
+  }, new Set(), 0);
+
+  assert.equal(result.code, '998877');
+  assert.equal(api.getOpenedCount(), 1);
+});