(mail, message, options = {})
| 579 | } |
| 580 | |
| 581 | async function sendToMailContentScriptResilient(mail, message, options = {}) { |
| 582 | const { timeoutMs = 45000, maxRecoveryAttempts = 2 } = options; |
| 583 | const start = Date.now(); |
| 584 | let lastError = null; |
| 585 | let recoveries = 0; |
| 586 | let logged = false; |
| 587 | |
| 588 | while (Date.now() - start < timeoutMs) { |
| 589 | throwIfStopped(); |
| 590 | |
| 591 | try { |
| 592 | return await sendToContentScript(mail.source, message); |
| 593 | } catch (err) { |
| 594 | if (!isRetryableContentScriptTransportError(err)) { |
| 595 | throw err; |
| 596 | } |
| 597 | |
| 598 | lastError = err; |
| 599 | if (!logged) { |
| 600 | await addLog(`步骤 ${message.step}:${mail.label} 页面通信异常,正在尝试让邮箱页重新就绪...`, 'warn'); |
| 601 | logged = true; |
| 602 | } |
| 603 | |
| 604 | if (recoveries >= maxRecoveryAttempts) { |
| 605 | break; |
| 606 | } |
| 607 | |
| 608 | recoveries += 1; |
| 609 | await reuseOrCreateTab(mail.source, mail.url, { |
| 610 | inject: mail.inject, |
| 611 | injectSource: mail.injectSource, |
| 612 | reloadIfSameUrl: true, |
| 613 | }); |
| 614 | await new Promise((resolve) => setTimeout(resolve, 800)); |
| 615 | } |
| 616 | } |
| 617 | |
| 618 | throw lastError || new Error(`${mail.label} 页面未能重新就绪。`); |
| 619 | } |
| 620 | |
| 621 | return { |
| 622 | buildLocalhostCleanupPrefix, |
no test coverage detected