feat: 优化2925邮箱登录逻辑,增强账号池管理与错误处理
This commit is contained in:
@@ -86,10 +86,9 @@
|
|||||||
|
|
||||||
function isMail2925LimitReachedError(error) {
|
function isMail2925LimitReachedError(error) {
|
||||||
const message = getErrorMessage(error);
|
const message = getErrorMessage(error);
|
||||||
const normalized = message.toLowerCase();
|
|
||||||
return message.startsWith(MAIL2925_LIMIT_ERROR_PREFIX)
|
return message.startsWith(MAIL2925_LIMIT_ERROR_PREFIX)
|
||||||
|| normalized.includes('子邮箱已达上限')
|
|| message.includes('子邮箱已达上限')
|
||||||
|| normalized.includes('已达上限邮箱');
|
|| message.includes('已达上限邮箱');
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMail2925ThreadTerminatedError(error) {
|
function isMail2925ThreadTerminatedError(error) {
|
||||||
@@ -385,7 +384,7 @@
|
|||||||
origins: MAIL2925_COOKIE_ORIGINS,
|
origins: MAIL2925_COOKIE_ORIGINS,
|
||||||
});
|
});
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
// 这里只做尽力清理。
|
// Best effort cleanup only.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,10 +398,14 @@
|
|||||||
actionLabel = '确保 2925 邮箱登录态',
|
actionLabel = '确保 2925 邮箱登录态',
|
||||||
allowLoginWhenOnLoginPage = true,
|
allowLoginWhenOnLoginPage = true,
|
||||||
} = options;
|
} = options;
|
||||||
const account = await ensureMail2925AccountForFlow({
|
|
||||||
allowAllocate: true,
|
let account = null;
|
||||||
preferredAccountId: accountId,
|
if (forceRelogin) {
|
||||||
});
|
account = await ensureMail2925AccountForFlow({
|
||||||
|
allowAllocate: true,
|
||||||
|
preferredAccountId: accountId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const sendLoginMessage = typeof sendToContentScriptResilient === 'function'
|
const sendLoginMessage = typeof sendToContentScriptResilient === 'function'
|
||||||
? sendToContentScriptResilient
|
? sendToContentScriptResilient
|
||||||
@@ -416,13 +419,14 @@
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildSuccessPayload = async (result = {}) => ({
|
const buildSuccessPayload = () => ({
|
||||||
account: await ensureMail2925AccountForFlow({
|
account,
|
||||||
allowAllocate: false,
|
|
||||||
preferredAccountId: account.id,
|
|
||||||
}),
|
|
||||||
mail: getMail2925MailConfig(),
|
mail: getMail2925MailConfig(),
|
||||||
result,
|
result: {
|
||||||
|
loggedIn: true,
|
||||||
|
currentView: 'mailbox',
|
||||||
|
usedExistingSession: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const failMailboxSession = async (message) => {
|
const failMailboxSession = async (message) => {
|
||||||
@@ -471,31 +475,24 @@
|
|||||||
if (matchedLoginTab?.url) {
|
if (matchedLoginTab?.url) {
|
||||||
openedUrl = String(matchedLoginTab.url || '').trim();
|
openedUrl = String(matchedLoginTab.url || '').trim();
|
||||||
}
|
}
|
||||||
if (matchedLoginTab && typeof ensureContentScriptReadyOnTab === 'function') {
|
|
||||||
await ensureContentScriptReadyOnTab(MAIL2925_SOURCE, tabId, {
|
|
||||||
inject: MAIL2925_INJECT,
|
|
||||||
injectSource: MAIL2925_INJECT_SOURCE,
|
|
||||||
timeoutMs: 20000,
|
|
||||||
retryDelayMs: 800,
|
|
||||||
logMessage: '步骤 0:2925 登录页内容脚本未就绪,正在等待页面稳定后继续登录...',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!forceRelogin && !isMail2925LoginUrl(openedUrl)) {
|
if (!forceRelogin && !isMail2925LoginUrl(openedUrl)) {
|
||||||
await addLog('2925:当前邮箱页未跳转到登录页,将直接复用已登录会话。', 'info');
|
await addLog('2925:当前邮箱页未跳转到登录页,将直接复用已登录会话。', 'info');
|
||||||
return buildSuccessPayload({
|
return buildSuccessPayload();
|
||||||
loggedIn: true,
|
|
||||||
currentView: 'mailbox',
|
|
||||||
currentUrl: openedUrl,
|
|
||||||
usedExistingSession: true,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!forceRelogin && !allowLoginWhenOnLoginPage) {
|
if (!forceRelogin && !allowLoginWhenOnLoginPage) {
|
||||||
await failMailboxSession(`2925:${actionLabel}失败,当前页面已跳转到登录页,且当前未启用 2925 账号池,不执行自动登录。`);
|
await failMailboxSession(`2925:${actionLabel}失败,当前页面已跳转到登录页,且当前未启用 2925 账号池,不执行自动登录。`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!account) {
|
||||||
|
account = await ensureMail2925AccountForFlow({
|
||||||
|
allowAllocate: true,
|
||||||
|
preferredAccountId: accountId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof ensureContentScriptReadyOnTab === 'function') {
|
if (typeof ensureContentScriptReadyOnTab === 'function') {
|
||||||
await ensureContentScriptReadyOnTab(MAIL2925_SOURCE, tabId, {
|
await ensureContentScriptReadyOnTab(MAIL2925_SOURCE, tabId, {
|
||||||
inject: MAIL2925_INJECT,
|
inject: MAIL2925_INJECT,
|
||||||
@@ -531,7 +528,7 @@
|
|||||||
timeoutMs: forceRelogin ? 30000 : 25000,
|
timeoutMs: forceRelogin ? 30000 : 25000,
|
||||||
retryDelayMs: 800,
|
retryDelayMs: 800,
|
||||||
responseTimeoutMs: forceRelogin ? 30000 : 25000,
|
responseTimeoutMs: forceRelogin ? 30000 : 25000,
|
||||||
logMessage: '步骤 0:2925 登录页通信异常,正在等待当前页面重新就绪后继续确认登录态...',
|
logMessage: '步骤 0:2925 登录页通信异常,正在等待页面恢复...',
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -547,7 +544,7 @@
|
|||||||
await failMailboxSession(`2925:${actionLabel}失败(${result.error})。`);
|
await failMailboxSession(`2925:${actionLabel}失败(${result.error})。`);
|
||||||
}
|
}
|
||||||
if (result?.limitReached) {
|
if (result?.limitReached) {
|
||||||
throw new Error(`${MAIL2925_LIMIT_ERROR_PREFIX}${result.limitMessage || '2925 子邮箱已达上限邮箱'}`);
|
throw new Error(`${MAIL2925_LIMIT_ERROR_PREFIX}${result.limitMessage || '子邮箱已达上限邮箱'}`);
|
||||||
}
|
}
|
||||||
if (!result?.loggedIn) {
|
if (!result?.loggedIn) {
|
||||||
await failMailboxSession(`2925:${actionLabel}失败,登录后仍未进入收件箱。`);
|
await failMailboxSession(`2925:${actionLabel}失败,登录后仍未进入收件箱。`);
|
||||||
@@ -559,10 +556,18 @@
|
|||||||
});
|
});
|
||||||
await setState({ currentMail2925AccountId: account.id });
|
await setState({ currentMail2925AccountId: account.id });
|
||||||
broadcastDataUpdate({ currentMail2925AccountId: account.id });
|
broadcastDataUpdate({ currentMail2925AccountId: account.id });
|
||||||
|
|
||||||
const finalUrl = (await getMail2925TabUrlById(tabId)) || await getMail2925CurrentTabUrl();
|
const finalUrl = (await getMail2925TabUrlById(tabId)) || await getMail2925CurrentTabUrl();
|
||||||
await addLog(`2925:登录态确认成功,当前地址=${finalUrl || 'unknown'}`, 'ok');
|
await addLog(`2925:登录态确认成功,当前地址=${finalUrl || 'unknown'}`, 'ok');
|
||||||
|
|
||||||
return buildSuccessPayload(result);
|
return {
|
||||||
|
account: await ensureMail2925AccountForFlow({
|
||||||
|
allowAllocate: false,
|
||||||
|
preferredAccountId: account.id,
|
||||||
|
}),
|
||||||
|
mail: getMail2925MailConfig(),
|
||||||
|
result,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleMail2925LimitReachedError(step, error) {
|
async function handleMail2925LimitReachedError(step, error) {
|
||||||
@@ -570,10 +575,21 @@
|
|||||||
|| '子邮箱已达上限邮箱';
|
|| '子邮箱已达上限邮箱';
|
||||||
const state = await getState();
|
const state = await getState();
|
||||||
const currentAccount = getCurrentMail2925Account(state);
|
const currentAccount = getCurrentMail2925Account(state);
|
||||||
|
const poolEnabled = Boolean(state?.mail2925UseAccountPool);
|
||||||
|
|
||||||
|
if (!poolEnabled) {
|
||||||
|
if (typeof requestStop === 'function') {
|
||||||
|
await requestStop({
|
||||||
|
logMessage: `步骤 ${step}:2925 检测到“${reason}”,当前未启用账号池,已按手动停止逻辑暂停自动流程。`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new Error('流程已被用户停止。');
|
||||||
|
}
|
||||||
|
|
||||||
if (!currentAccount) {
|
if (!currentAccount) {
|
||||||
if (typeof requestStop === 'function') {
|
if (typeof requestStop === 'function') {
|
||||||
await requestStop({
|
await requestStop({
|
||||||
logMessage: `步骤 ${step}:2925 检测到“${reason}”,但当前没有可识别的账号可供处理。`,
|
logMessage: `步骤 ${step}:2925 检测到“${reason}”,但当前没有可识别的账号可供切换。`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return new Error('流程已被用户停止。');
|
return new Error('流程已被用户停止。');
|
||||||
@@ -601,7 +617,7 @@
|
|||||||
broadcastDataUpdate({ currentMail2925AccountId: null });
|
broadcastDataUpdate({ currentMail2925AccountId: null });
|
||||||
if (typeof requestStop === 'function') {
|
if (typeof requestStop === 'function') {
|
||||||
await requestStop({
|
await requestStop({
|
||||||
logMessage: `步骤 ${step}:2925 账号 ${currentAccount.email} 命中“${reason}”,且当前没有可切换的下一个账号。`,
|
logMessage: `步骤 ${step}:2925 账号 ${currentAccount.email} 命中“${reason}”,但当前没有可切换的下一个账号。`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return new Error('流程已被用户停止。');
|
return new Error('流程已被用户停止。');
|
||||||
@@ -616,7 +632,7 @@
|
|||||||
});
|
});
|
||||||
await addLog(`步骤 ${step}:2925 已切换到下一个账号 ${nextAccount.email}。`, 'warn');
|
await addLog(`步骤 ${step}:2925 已切换到下一个账号 ${nextAccount.email}。`, 'warn');
|
||||||
return buildMail2925ThreadTerminatedError(
|
return buildMail2925ThreadTerminatedError(
|
||||||
`步骤 ${step}:2925 账号 ${currentAccount.email} 命中“${reason}”,已切换到 ${nextAccount.email},当前尝试结束,等待下一次重试。`
|
`步骤 ${step}:2925 账号 ${currentAccount.email} 命中“${reason}”,已切换到 ${nextAccount.email},当前尝试结束,等待下一轮重试。`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -295,24 +295,24 @@ function getManagedAliasProviderUiCopy(provider = selectMailProvider.value) {
|
|||||||
}
|
}
|
||||||
if (String(provider || '').trim().toLowerCase() === GMAIL_PROVIDER) {
|
if (String(provider || '').trim().toLowerCase() === GMAIL_PROVIDER) {
|
||||||
return {
|
return {
|
||||||
baseLabel: 'Gmail 原邮箱',
|
baseLabel: '基邮箱',
|
||||||
basePlaceholder: '例如 yourname@gmail.com',
|
basePlaceholder: '例如 yourname@gmail.com',
|
||||||
buttonLabel: '生成',
|
buttonLabel: '生成',
|
||||||
successVerb: '生成',
|
successVerb: '生成',
|
||||||
label: 'Gmail +tag 邮箱',
|
label: 'Gmail +tag 邮箱',
|
||||||
placeholder: '点击生成 Gmail +tag 邮箱,或手动填写完整邮箱',
|
placeholder: '点击生成 Gmail +tag 邮箱,或手动填写完整邮箱',
|
||||||
hint: '先填写 Gmail 原邮箱后点“生成”,也可以直接手动填写完整的 Gmail 邮箱。',
|
hint: '先填写基邮箱后点“生成”,也可以直接手动填写完整的 Gmail 邮箱。',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (String(provider || '').trim().toLowerCase() === '2925') {
|
if (String(provider || '').trim().toLowerCase() === '2925') {
|
||||||
return {
|
return {
|
||||||
baseLabel: '2925 基邮箱',
|
baseLabel: '基邮箱',
|
||||||
basePlaceholder: '例如 yourname@2925.com',
|
basePlaceholder: '例如 yourname@2925.com',
|
||||||
buttonLabel: '生成',
|
buttonLabel: '生成',
|
||||||
successVerb: '生成',
|
successVerb: '生成',
|
||||||
label: '2925 邮箱',
|
label: '2925 邮箱',
|
||||||
placeholder: '点击生成 2925 邮箱,或手动填写完整邮箱',
|
placeholder: '点击生成 2925 邮箱,或手动填写完整邮箱',
|
||||||
hint: '先填写 2925 基邮箱后点“生成”,也可以直接手动填写完整的 2925 邮箱。',
|
hint: '先填写基邮箱后点“生成”,也可以直接手动填写完整的 2925 邮箱。',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -72,6 +72,67 @@ test('ensureMail2925MailboxSession reuses current mailbox page without sending l
|
|||||||
assert.equal(result.result.usedExistingSession, true);
|
assert.equal(result.result.usedExistingSession, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('ensureMail2925MailboxSession does not require account-pool accounts when pool is off and mailbox page stays on mailList', async () => {
|
||||||
|
let currentState = {
|
||||||
|
autoRunning: false,
|
||||||
|
mail2925UseAccountPool: false,
|
||||||
|
mail2925Accounts: [],
|
||||||
|
currentMail2925AccountId: null,
|
||||||
|
};
|
||||||
|
let sendCalls = 0;
|
||||||
|
|
||||||
|
const manager = api.createMail2925SessionManager({
|
||||||
|
addLog: async () => {},
|
||||||
|
broadcastDataUpdate: () => {},
|
||||||
|
chrome: {
|
||||||
|
tabs: {
|
||||||
|
get: async () => ({ id: 9, url: 'https://2925.com/#/mailList' }),
|
||||||
|
},
|
||||||
|
cookies: {
|
||||||
|
getAll: async () => [],
|
||||||
|
remove: async () => ({ ok: true }),
|
||||||
|
},
|
||||||
|
browsingData: {
|
||||||
|
removeCookies: async () => {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ensureContentScriptReadyOnTab: async () => {},
|
||||||
|
findMail2925Account: mail2925Utils.findMail2925Account,
|
||||||
|
getMail2925AccountStatus: mail2925Utils.getMail2925AccountStatus,
|
||||||
|
getState: async () => currentState,
|
||||||
|
isAutoRunLockedState: () => false,
|
||||||
|
isMail2925AccountAvailable: mail2925Utils.isMail2925AccountAvailable,
|
||||||
|
MAIL2925_LIMIT_COOLDOWN_MS: mail2925Utils.MAIL2925_LIMIT_COOLDOWN_MS,
|
||||||
|
normalizeMail2925Account: mail2925Utils.normalizeMail2925Account,
|
||||||
|
normalizeMail2925Accounts: mail2925Utils.normalizeMail2925Accounts,
|
||||||
|
pickMail2925AccountForRun: mail2925Utils.pickMail2925AccountForRun,
|
||||||
|
reuseOrCreateTab: async () => 9,
|
||||||
|
sendToMailContentScriptResilient: async () => {
|
||||||
|
sendCalls += 1;
|
||||||
|
return { loggedIn: true };
|
||||||
|
},
|
||||||
|
setPersistentSettings: async (payload) => {
|
||||||
|
currentState = { ...currentState, ...payload };
|
||||||
|
},
|
||||||
|
setState: async (updates) => {
|
||||||
|
currentState = { ...currentState, ...updates };
|
||||||
|
},
|
||||||
|
throwIfStopped: () => {},
|
||||||
|
upsertMail2925AccountInList: mail2925Utils.upsertMail2925AccountInList,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await manager.ensureMail2925MailboxSession({
|
||||||
|
accountId: null,
|
||||||
|
forceRelogin: false,
|
||||||
|
allowLoginWhenOnLoginPage: false,
|
||||||
|
actionLabel: '步骤 4:确认 2925 邮箱登录态',
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(sendCalls, 0);
|
||||||
|
assert.equal(result.result.usedExistingSession, true);
|
||||||
|
assert.equal(result.account, null);
|
||||||
|
});
|
||||||
|
|
||||||
test('ensureMail2925MailboxSession stops immediately when login page is detected and account pool is off', async () => {
|
test('ensureMail2925MailboxSession stops immediately when login page is detected and account pool is off', async () => {
|
||||||
let currentState = {
|
let currentState = {
|
||||||
autoRunning: true,
|
autoRunning: true,
|
||||||
|
|||||||
@@ -78,5 +78,5 @@ test('ensureMail2925MailboxSession waits 3 seconds before and after opening logi
|
|||||||
|
|
||||||
assert.deepStrictEqual(events.openedUrls, ['https://2925.com/login/']);
|
assert.deepStrictEqual(events.openedUrls, ['https://2925.com/login/']);
|
||||||
assert.deepStrictEqual(events.sleeps, [3000, 3000]);
|
assert.deepStrictEqual(events.sleeps, [3000, 3000]);
|
||||||
assert.equal(events.readyCalls, 2);
|
assert.equal(events.readyCalls, 1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ test('handleMail2925LimitReachedError disables current account and switches to t
|
|||||||
const api = new Function('self', `${source}; return self.MultiPageBackgroundMail2925Session;`)(globalScope);
|
const api = new Function('self', `${source}; return self.MultiPageBackgroundMail2925Session;`)(globalScope);
|
||||||
|
|
||||||
let currentState = {
|
let currentState = {
|
||||||
|
mail2925UseAccountPool: true,
|
||||||
mail2925Accounts: mail2925Utils.normalizeMail2925Accounts([
|
mail2925Accounts: mail2925Utils.normalizeMail2925Accounts([
|
||||||
{ id: 'current', email: 'current@2925.com', password: 'p1', enabled: true, lastUsedAt: 10 },
|
{ id: 'current', email: 'current@2925.com', password: 'p1', enabled: true, lastUsedAt: 10 },
|
||||||
{ id: 'next', email: 'next@2925.com', password: 'p2', enabled: true, lastUsedAt: 20 },
|
{ id: 'next', email: 'next@2925.com', password: 'p2', enabled: true, lastUsedAt: 20 },
|
||||||
@@ -99,6 +100,7 @@ test('handleMail2925LimitReachedError requests stop when no next mail2925 accoun
|
|||||||
const api = new Function('self', `${source}; return self.MultiPageBackgroundMail2925Session;`)(globalScope);
|
const api = new Function('self', `${source}; return self.MultiPageBackgroundMail2925Session;`)(globalScope);
|
||||||
|
|
||||||
let currentState = {
|
let currentState = {
|
||||||
|
mail2925UseAccountPool: true,
|
||||||
mail2925Accounts: mail2925Utils.normalizeMail2925Accounts([
|
mail2925Accounts: mail2925Utils.normalizeMail2925Accounts([
|
||||||
{ id: 'only', email: 'only@2925.com', password: 'p1', enabled: true, lastUsedAt: 10 },
|
{ id: 'only', email: 'only@2925.com', password: 'p1', enabled: true, lastUsedAt: 10 },
|
||||||
]),
|
]),
|
||||||
@@ -225,3 +227,70 @@ test('ensureMail2925MailboxSession requests stop when auto run is active and log
|
|||||||
assert.equal(events.stopCalls.length, 1);
|
assert.equal(events.stopCalls.length, 1);
|
||||||
assert.match(events.stopCalls[0].logMessage, /登录后仍未进入收件箱/);
|
assert.match(events.stopCalls[0].logMessage, /登录后仍未进入收件箱/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('handleMail2925LimitReachedError stops immediately when account pool is off even if another account exists', async () => {
|
||||||
|
const source = fs.readFileSync('background/mail-2925-session.js', 'utf8');
|
||||||
|
const globalScope = {};
|
||||||
|
const api = new Function('self', `${source}; return self.MultiPageBackgroundMail2925Session;`)(globalScope);
|
||||||
|
|
||||||
|
let currentState = {
|
||||||
|
mail2925UseAccountPool: false,
|
||||||
|
mail2925Accounts: mail2925Utils.normalizeMail2925Accounts([
|
||||||
|
{ id: 'current', email: 'current@2925.com', password: 'p1', enabled: true, lastUsedAt: 10 },
|
||||||
|
{ id: 'next', email: 'next@2925.com', password: 'p2', enabled: true, lastUsedAt: 20 },
|
||||||
|
]),
|
||||||
|
currentMail2925AccountId: 'current',
|
||||||
|
};
|
||||||
|
const events = {
|
||||||
|
stopCalls: [],
|
||||||
|
sessionChecks: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const manager = api.createMail2925SessionManager({
|
||||||
|
addLog: async () => {},
|
||||||
|
broadcastDataUpdate: () => {},
|
||||||
|
chrome: {
|
||||||
|
cookies: {
|
||||||
|
getAll: async () => [],
|
||||||
|
remove: async () => ({ ok: true }),
|
||||||
|
},
|
||||||
|
browsingData: {
|
||||||
|
removeCookies: async () => {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
findMail2925Account: mail2925Utils.findMail2925Account,
|
||||||
|
getMail2925AccountStatus: mail2925Utils.getMail2925AccountStatus,
|
||||||
|
getState: async () => currentState,
|
||||||
|
isMail2925AccountAvailable: mail2925Utils.isMail2925AccountAvailable,
|
||||||
|
MAIL2925_LIMIT_COOLDOWN_MS: mail2925Utils.MAIL2925_LIMIT_COOLDOWN_MS,
|
||||||
|
normalizeMail2925Account: mail2925Utils.normalizeMail2925Account,
|
||||||
|
normalizeMail2925Accounts: mail2925Utils.normalizeMail2925Accounts,
|
||||||
|
pickMail2925AccountForRun: mail2925Utils.pickMail2925AccountForRun,
|
||||||
|
requestStop: async (options = {}) => {
|
||||||
|
events.stopCalls.push(options);
|
||||||
|
},
|
||||||
|
reuseOrCreateTab: async () => 1,
|
||||||
|
sendToMailContentScriptResilient: async () => {
|
||||||
|
events.sessionChecks += 1;
|
||||||
|
return { loggedIn: true };
|
||||||
|
},
|
||||||
|
setPersistentSettings: async (payload) => {
|
||||||
|
currentState = { ...currentState, ...payload };
|
||||||
|
},
|
||||||
|
setState: async (updates) => {
|
||||||
|
currentState = { ...currentState, ...updates };
|
||||||
|
},
|
||||||
|
throwIfStopped: () => {},
|
||||||
|
upsertMail2925AccountInList: mail2925Utils.upsertMail2925AccountInList,
|
||||||
|
});
|
||||||
|
|
||||||
|
const error = await manager.handleMail2925LimitReachedError(
|
||||||
|
4,
|
||||||
|
new Error('MAIL2925_LIMIT_REACHED::子邮箱已达上限邮箱')
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(error.message, '流程已被用户停止。');
|
||||||
|
assert.equal(events.sessionChecks, 0);
|
||||||
|
assert.equal(events.stopCalls.length, 1);
|
||||||
|
assert.equal(currentState.currentMail2925AccountId, 'current');
|
||||||
|
});
|
||||||
|
|||||||
+3
-3
@@ -331,7 +331,7 @@
|
|||||||
补充行为:
|
补充行为:
|
||||||
|
|
||||||
- `2925` provider 会关闭 Step 4 / 8 的自动重发间隔 25 秒节流;每次“重新发送验证码”之间,会在邮箱页内部执行一轮固定 15 次的刷新轮询,不再因 OAuth 剩余时间预算而缩短。
|
- `2925` provider 会关闭 Step 4 / 8 的自动重发间隔 25 秒节流;每次“重新发送验证码”之间,会在邮箱页内部执行一轮固定 15 次的刷新轮询,不再因 OAuth 剩余时间预算而缩短。
|
||||||
- 当 provider 为 `2925` 时,Step 4 会优先直接打开当前 2925 邮箱页:如果页面仍停留在收件箱,就直接复用当前已登录页面;如果页面已经跳到登录页,则只有在启用了 2925 账号池时才会自动登录,未启用账号池时会直接报错停止。Step 8 不再额外承接这套登录态处理。
|
- 当 provider 为 `2925` 时,Step 4 会优先直接打开当前 2925 邮箱页:如果页面仍停留在收件箱,就直接复用当前已登录页面;如果页面已经跳到登录页,则只有在启用了 2925 账号池时才会自动登录,未启用账号池时会直接复用现有停止逻辑结束流程。Step 8 不再额外承接这套登录态处理。
|
||||||
- 普通邮箱仍会携带 `filterAfterTimestamp` 做时间窗筛选;`2925` 当前既不依赖时间窗,也不再做“新旧邮件快照差集”比较,而是每次刷新后直接遍历当前列表中的匹配邮件。
|
- 普通邮箱仍会携带 `filterAfterTimestamp` 做时间窗筛选;`2925` 当前既不依赖时间窗,也不再做“新旧邮件快照差集”比较,而是每次刷新后直接遍历当前列表中的匹配邮件。
|
||||||
- 自动重新发送验证码次数现在使用 sidepanel 里的单一“验证码重发”配置;普通邮箱仍按 25 秒间隔节流,Hotmail / 2925 不走这个 25 秒间隔。Step 4 若启用先请求新验证码,会先消耗一次当前步骤的自动重发次数。
|
- 自动重新发送验证码次数现在使用 sidepanel 里的单一“验证码重发”配置;普通邮箱仍按 25 秒间隔节流,Hotmail / 2925 不走这个 25 秒间隔。Step 4 若启用先请求新验证码,会先消耗一次当前步骤的自动重发次数。
|
||||||
- 验证码提交重试上限当前为 15 次;页面明确拒绝验证码时,会在上限内继续拉取新验证码并重提。
|
- 验证码提交重试上限当前为 15 次;页面明确拒绝验证码时,会在上限内继续拉取新验证码并重提。
|
||||||
@@ -555,8 +555,8 @@
|
|||||||
|
|
||||||
1. 用户在 sidepanel 的 2925 账号池中保存 `email / password`
|
1. 用户在 sidepanel 的 2925 账号池中保存 `email / password`
|
||||||
2. 只有当 sidepanel 中的 `mail2925UseAccountPool` 开关开启时,别名基邮箱才会优先取当前账号池选中的 2925 账号邮箱;关闭时会回退到原来的手填 `mail2925BaseEmail`
|
2. 只有当 sidepanel 中的 `mail2925UseAccountPool` 开关开启时,别名基邮箱才会优先取当前账号池选中的 2925 账号邮箱;关闭时会回退到原来的手填 `mail2925BaseEmail`
|
||||||
3. 手动点击 `登录` 或自动流程进入 Step 4 前,后台会先打开当前 2925 邮箱页:如果仍停留在收件箱则直接复用;如果跳到登录页,则仅在号池模式开启时才自动登录,关闭号池时直接停止
|
3. 手动点击 `登录` 或自动流程进入 Step 4 前,后台会先打开当前 2925 邮箱页:如果仍停留在收件箱则直接复用;如果跳到登录页,则仅在号池模式开启时才自动登录,关闭号池时直接调用现有停止逻辑结束流程
|
||||||
4. 一旦轮询期间出现“子邮箱已达上限邮箱”,后台会先记录当前时间;若当前处于号池模式且还有下一个可用账号,则把当前账号禁用 24 小时并自动切到下一个账号重新登录
|
4. 一旦轮询期间出现“子邮箱已达上限邮箱”,后台会先判断是否启用了号池模式:若已启用且还有下一个可用账号,则把当前账号禁用 24 小时并自动切到下一个账号重新登录;若未启用,则直接调用现有停止逻辑结束流程
|
||||||
5. 如果登录提交后 20 秒内仍未进入收件箱,且当前正处于自动运行中,则后台会直接复用现有 `requestStop()` 停止链路,把整个自动流程停成和用户手动点击“停止”一致的状态;这类情况常见于图片验证、行为验证或其他阻断登录的中间页
|
5. 如果登录提交后 20 秒内仍未进入收件箱,且当前正处于自动运行中,则后台会直接复用现有 `requestStop()` 停止链路,把整个自动流程停成和用户手动点击“停止”一致的状态;这类情况常见于图片验证、行为验证或其他阻断登录的中间页
|
||||||
6. 如果没有下一个可用账号,或当前未启用号池模式,则不会继续消耗自动重试次数,而是直接复用现有 `requestStop()` 停止链路,把整个自动流程停成和用户手动点击“停止”一致的状态
|
6. 如果没有下一个可用账号,或当前未启用号池模式,则不会继续消耗自动重试次数,而是直接复用现有 `requestStop()` 停止链路,把整个自动流程停成和用户手动点击“停止”一致的状态
|
||||||
7. sidepanel 中 2925 账号池的新增表单也走与 Hotmail 相同的共享交互:默认收起,头部按钮切换“添加账号 / 取消添加”,操作行右侧提供“批量导入”,保存成功后自动收起并清空。
|
7. sidepanel 中 2925 账号池的新增表单也走与 Hotmail 相同的共享交互:默认收起,头部按钮切换“添加账号 / 取消添加”,操作行右侧提供“批量导入”,保存成功后自动收起并清空。
|
||||||
|
|||||||
Reference in New Issue
Block a user