Jelajahi Sumber

Improve A4Sky IMAP verification polling

chendeben 4 bulan lalu
induk
melakukan
b058c4ddfa

+ 2 - 2
background.js

@@ -1850,7 +1850,7 @@ async function requestA4skyLocalImapCode(state, pollPayload = {}) {
       body: JSON.stringify({
         targetEmail: String(state?.email || '').trim().toLowerCase(),
         mailbox: 'INBOX',
-        top: 10,
+        top: 60,
         senderFilters: pollPayload.senderFilters || [],
         subjectFilters: pollPayload.subjectFilters || [],
         excludeCodes: pollPayload.excludeCodes || [],
@@ -6182,7 +6182,7 @@ function getMailConfig(state) {
       provider: A4SKY_PROVIDER,
       source: 'mail-phplife',
       url: 'https://mail.phplife.net/?_task=mail&_mbox=INBOX',
-      label: 'A4Sky 邮箱(mail.phplife.net)',
+      label: 'A4Sky 邮箱(IMAP 助手)',
       navigateOnReuse: false,
       inject: ['content/activation-utils.js', 'content/utils.js', 'content/phplife-mail.js'],
       injectSource: 'mail-phplife',

+ 63 - 11
scripts/hotmail_helper.py

@@ -65,6 +65,7 @@ IMAP_HOST = "outlook.office365.com"
 IMAP_PORT = 993
 REQUEST_TIMEOUT_SECONDS = 45
 FETCH_LIMIT_DEFAULT = 5
+FETCH_LIMIT_MAX = 120
 BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
 ACCOUNT_LOG_PATH = os.path.join(BASE_DIR, "data", "account-run-history.txt")
 ACCOUNT_RECORDS_SNAPSHOT_PATH = os.path.join(BASE_DIR, "data", "account-run-history.json")
@@ -507,18 +508,61 @@ def normalize_message(message_id, raw_bytes, mailbox):
     }
 
 
+def normalize_fetch_limit(top):
+    try:
+        numeric = int(top or FETCH_LIMIT_DEFAULT)
+    except Exception:
+        numeric = FETCH_LIMIT_DEFAULT
+    return max(1, min(numeric, FETCH_LIMIT_MAX))
+
+
+def search_imap_message_ids(client, target_email=""):
+    normalized_target = str(target_email or "").strip().lower()
+    if not normalized_target:
+        return []
+
+    matched_ids = []
+    seen_ids = set()
+    for header_name in ["To", "Delivered-To", "Envelope-To", "X-Original-To", "Cc"]:
+        try:
+            status, data = client.search(None, "HEADER", header_name, f'"{normalized_target}"')
+        except Exception:
+            continue
+        if status != "OK" or not data or not data[0]:
+            continue
+        for message_id in data[0].split():
+            if not message_id or message_id in seen_ids:
+                continue
+            seen_ids.add(message_id)
+            matched_ids.append(message_id)
+
+    matched_ids.sort(key=lambda item: int(item) if item.isdigit() else 0)
+    return matched_ids
+
+
+def load_selected_message_ids(client, top, target_email=""):
+    limit = normalize_fetch_limit(top)
+    target_ids = search_imap_message_ids(client, target_email)
+    if target_ids:
+        return list(reversed(target_ids[-limit:]))
+
+    status, data = client.search(None, "ALL")
+    if status != "OK" or not data or not data[0]:
+        return []
+    message_ids = data[0].split()
+    return list(reversed(message_ids[-limit:]))
+
+
 def fetch_messages(email_addr, access_token, mailbox="INBOX", top=FETCH_LIMIT_DEFAULT):
     client = None
     logical_mailbox = normalize_mailbox_label(mailbox)
     try:
         client = open_mailbox(email_addr, access_token)
         select_mailbox(client, mailbox)
-        status, data = client.search(None, "ALL")
-        if status != "OK" or not data or not data[0]:
+        selected_ids = load_selected_message_ids(client, top)
+        if not selected_ids:
             return {"mailbox": logical_mailbox, "messages": [], "count": 0}
 
-        message_ids = data[0].split()
-        selected_ids = list(reversed(message_ids[-max(1, min(int(top or FETCH_LIMIT_DEFAULT), 30)):]))
         messages = []
         for message_id in selected_ids:
             fetch_status, fetch_data = client.fetch(message_id, "(RFC822)")
@@ -552,18 +596,16 @@ def fetch_messages_for_mailboxes(email_addr, access_token, mailboxes, top):
     return {"mailboxResults": mailbox_results, "messages": all_messages}
 
 
-def fetch_basic_imap_messages(host, port, username, password, mailbox="INBOX", top=FETCH_LIMIT_DEFAULT):
+def fetch_basic_imap_messages(host, port, username, password, mailbox="INBOX", top=FETCH_LIMIT_DEFAULT, target_email=""):
     client = None
     logical_mailbox = normalize_mailbox_label(mailbox)
     try:
         client = open_basic_imap_mailbox(host, port, username, password)
         select_mailbox(client, mailbox)
-        status, data = client.search(None, "ALL")
-        if status != "OK" or not data or not data[0]:
+        selected_ids = load_selected_message_ids(client, top, target_email)
+        if not selected_ids:
             return {"mailbox": logical_mailbox, "messages": [], "count": 0}
 
-        message_ids = data[0].split()
-        selected_ids = list(reversed(message_ids[-max(1, min(int(top or FETCH_LIMIT_DEFAULT), 30)):]))
         messages = []
         for message_id in selected_ids:
             fetch_status, fetch_data = client.fetch(message_id, "(RFC822)")
@@ -586,11 +628,19 @@ def fetch_basic_imap_messages(host, port, username, password, mailbox="INBOX", t
                 pass
 
 
-def fetch_basic_imap_messages_for_mailboxes(host, port, username, password, mailboxes, top):
+def fetch_basic_imap_messages_for_mailboxes(host, port, username, password, mailboxes, top, target_email=""):
     mailbox_results = []
     all_messages = []
     for mailbox in mailboxes or ["INBOX"]:
-        result = fetch_basic_imap_messages(host, port, username, password, mailbox=mailbox, top=top)
+        result = fetch_basic_imap_messages(
+            host,
+            port,
+            username,
+            password,
+            mailbox=mailbox,
+            top=top,
+            target_email=target_email,
+        )
         mailbox_results.append(result)
         all_messages.extend(result["messages"])
     all_messages.sort(key=lambda item: int(item.get("receivedTimestamp") or 0), reverse=True)
@@ -599,6 +649,7 @@ def fetch_basic_imap_messages_for_mailboxes(host, port, username, password, mail
 
 def collect_basic_imap_messages(payload, mailboxes, top):
     settings = resolve_basic_imap_settings(payload)
+    target_email = str(payload.get("targetEmail") or payload.get("email") or "").strip().lower()
     result = fetch_basic_imap_messages_for_mailboxes(
         settings["host"],
         settings["port"],
@@ -606,6 +657,7 @@ def collect_basic_imap_messages(payload, mailboxes, top):
         settings["password"],
         mailboxes,
         top,
+        target_email=target_email,
     )
     result["transport"] = "imap-basic"
     result["settings"] = {

+ 13 - 4
sidepanel/sidepanel.js

@@ -122,6 +122,7 @@ const hotmailServiceModeButtons = Array.from(document.querySelectorAll('[data-ho
 const rowHotmailRemoteBaseUrl = document.getElementById('row-hotmail-remote-base-url');
 const inputHotmailRemoteBaseUrl = document.getElementById('input-hotmail-remote-base-url');
 const rowHotmailLocalBaseUrl = document.getElementById('row-hotmail-local-base-url');
+const labelHotmailLocalBaseUrl = rowHotmailLocalBaseUrl?.querySelector('.data-label');
 const inputHotmailLocalBaseUrl = document.getElementById('input-hotmail-local-base-url');
 const inputHotmailEmail = document.getElementById('input-hotmail-email');
 const inputHotmailClientId = document.getElementById('input-hotmail-client-id');
@@ -2372,6 +2373,14 @@ function updateMailProviderUI() {
   if (hotmailSectionLabel) {
     hotmailSectionLabel.textContent = useA4sky ? 'A4Sky IMAP 助手' : 'Hotmail 账号池';
   }
+  if (labelHotmailLocalBaseUrl) {
+    labelHotmailLocalBaseUrl.textContent = useA4sky ? '助手地址' : '本地助手';
+  }
+  if (inputHotmailLocalBaseUrl) {
+    inputHotmailLocalBaseUrl.placeholder = useA4sky
+      ? '例如 http://ali.97admin.com:17373'
+      : 'http://127.0.0.1:17373';
+  }
   if (btnHotmailUsageGuide) {
     btnHotmailUsageGuide.style.display = useHotmail ? '' : 'none';
   }
@@ -2445,11 +2454,11 @@ function updateMailProviderUI() {
   }
   if (autoHintText) {
     autoHintText.textContent = useHotmail
-      ? '请先校验并选择一个 Hotmail 账号'
-      : (useLuckmail
-        ? '步骤 3 会自动购买 LuckMail 邮箱并用于收码'
+        ? '请先校验并选择一个 Hotmail 账号'
+        : (useLuckmail
+          ? '步骤 3 会自动购买 LuckMail 邮箱并用于收码'
         : (useA4sky
-          ? '点击“生成”得到 n{Ymdhis}@a4sky.com;步骤 4/8 会打开 mail.phplife.net,若未登录则等待你登录后自动取码'
+          ? '点击“生成”得到 n{Ymdhis}@a4sky.com;步骤 4/8 会通过下方 IMAP 助手地址直接取码'
       : (useGeneratedAlias
         ? '步骤 3 会自动生成邮箱,无需手动获取'
         : (useCustomEmail ? '请先填写自定义注册邮箱,成功一轮后会自动清空' : `先自动获取${uiCopy.label},或手动粘贴邮箱后再继续`))));

+ 1 - 1
tests/background-icloud-mail-provider.test.js

@@ -177,7 +177,7 @@ return { getMailConfig };
     provider: 'a4sky',
     source: 'mail-phplife',
     url: 'https://mail.phplife.net/?_task=mail&_mbox=INBOX',
-    label: 'A4Sky 邮箱(mail.phplife.net)',
+    label: 'A4Sky 邮箱(IMAP 助手)',
     navigateOnReuse: false,
     inject: ['content/activation-utils.js', 'content/utils.js', 'content/phplife-mail.js'],
     injectSource: 'mail-phplife',