fix: clean up iCloud forward mailbox provider tech debt

This commit is contained in:
Q3CC
2026-04-26 14:21:52 +08:00
parent 46ceb482c4
commit 98e7653360
15 changed files with 512 additions and 241 deletions
+3 -1
View File
@@ -75,6 +75,7 @@
- 至少准备一种验证码接收方式:
- DuckDuckGo `@duck.com` + QQ / 163 / Inbucket 转发
- Cloudflare 自定义域邮箱前缀 + QQ / 163 / Inbucket 转发
- iCloud Hide My Email,可选择直接从 iCloud 收件箱收码,或转发到 QQ / 163 / 163 VIP / 126 / Gmail 后收码
- 手动填写一个可收信邮箱
- 如果使用 `QQ` / `163` / `163 VIP` / `126` / `Inbucket`,对应页面需要提前能正常打开
@@ -592,6 +593,7 @@ Cloudflare 模式下,插件不会再调用 Cloudflare API 创建路由。
支持:
- `Hotmail`(远程服务 / 本地助手)
- `iCloud` 收件箱,或 iCloud Hide My Email 转发到 QQ / 163 / 163 VIP / 126 / Gmail 后收码
- `content/qq-mail.js`
- `content/mail-163.js`163 / 163 VIP / 126
- `content/inbucket-mail.js`
@@ -773,7 +775,7 @@ content/utils.js 通用工具:等待元素、点击、日志、停
content/vps-panel.js CPA 面板步骤:内部 OAuth 刷新 / Step 10
content/signup-page.js ChatGPT 官网 + OpenAI 注册/登录页步骤:Step 1 / 2 / 3 / 5 / 7 / 9
hotmail-utils.js Hotmail 收信相关通用辅助
mail-provider-utils.js 网页邮箱 provider 配置辅助
mail-provider-utils.js 网页邮箱 provider 与 iCloud 转发收码配置辅助
content/duck-mail.js Duck 邮箱自动获取
content/qq-mail.js QQ 邮箱验证码轮询
content/mail-163.js 163 / 163 VIP / 126 邮箱验证码轮询
+7 -37
View File
@@ -34,6 +34,7 @@ importScripts(
'luckmail-utils.js',
'cloudflare-temp-email-utils.js',
'icloud-utils.js',
'mail-provider-utils.js',
'content/activation-utils.js'
);
@@ -124,6 +125,11 @@ const {
pickReusableIcloudAlias,
toNormalizedEmailSet,
} = self.IcloudUtils;
const {
getIcloudForwardMailConfig: getSharedIcloudForwardMailConfig,
normalizeIcloudForwardMailProvider,
normalizeIcloudTargetMailboxType,
} = self.MailProviderUtils;
const {
isRecoverableStep9AuthFailure,
} = self.MultiPageActivationUtils;
@@ -694,19 +700,6 @@ function normalizeIcloudFetchMode(value = '') {
return normalized === 'always_new' ? 'always_new' : 'reuse_existing';
}
function normalizeIcloudTargetMailboxType(value = '') {
return String(value || '').trim().toLowerCase() === 'forward-mailbox'
? 'forward-mailbox'
: 'icloud-inbox';
}
function normalizeIcloudForwardMailProvider(value = '') {
const normalized = String(value || '').trim().toLowerCase();
return ['qq', '163', '163-vip', '126', 'gmail'].includes(normalized)
? normalized
: 'qq';
}
function normalizeCustomEmailPool(value = []) {
const source = Array.isArray(value)
? value
@@ -6894,29 +6887,6 @@ async function executeStep3(state) {
// Step 4: Get Signup Verification Code (qq-mail.js polls, then fills in signup-page.js)
// ============================================================
function getIcloudForwardMailConfig(state = {}, provider = 'qq') {
const normalizedProvider = normalizeIcloudForwardMailProvider(provider);
if (normalizedProvider === GMAIL_PROVIDER) {
return {
source: 'gmail-mail',
url: 'https://mail.google.com/mail/u/0/#inbox',
label: 'Gmail 邮箱',
inject: ['content/activation-utils.js', 'content/utils.js', 'content/gmail-mail.js'],
injectSource: 'gmail-mail',
};
}
if (normalizedProvider === '163') {
return { source: 'mail-163', url: 'https://mail.163.com/js6/main.jsp?df=mail163_letter#module=mbox.ListModule%7C%7B%22fid%22%3A1%2C%22order%22%3A%22date%22%2C%22desc%22%3Atrue%7D', label: '163 邮箱' };
}
if (normalizedProvider === '163-vip') {
return { source: 'mail-163', url: 'https://webmail.vip.163.com/js6/main.jsp?df=mail163_letter#module=mbox.ListModule%7C%7B%22fid%22%3A1%2C%22order%22%3A%22date%22%2C%22desc%22%3Atrue%7D', label: '163 VIP 邮箱' };
}
if (normalizedProvider === '126') {
return { source: 'mail-163', url: 'https://mail.126.com/js6/main.jsp?df=mail163_letter#module=mbox.ListModule%7C%7B%22fid%22%3A1%2C%22order%22%3A%22date%22%2C%22desc%22%3Atrue%7D', label: '126 邮箱' };
}
return { source: 'qq-mail', url: 'https://wx.mail.qq.com/', label: 'QQ 邮箱' };
}
function getMailConfig(state) {
const provider = state.mailProvider || 'qq';
if (provider === 'custom') {
@@ -6933,7 +6903,7 @@ function getMailConfig(state) {
const useForwardMailbox = targetMailboxType === 'forward-mailbox';
if (useForwardMailbox) {
const forwardProvider = normalizeIcloudForwardMailProvider(state?.icloudForwardMailProvider);
const forwardConfig = getIcloudForwardMailConfig(state, forwardProvider);
const forwardConfig = getSharedIcloudForwardMailConfig(forwardProvider);
return {
...forwardConfig,
label: `iCloud 转发(${forwardConfig.label}`,
+47
View File
@@ -1,5 +1,15 @@
const HOTMAIL_PROVIDER = 'hotmail-api';
const GMAIL_PROVIDER = 'gmail';
const NETEASE_LIST_PATH = '/js6/main.jsp?df=mail163_letter#module=mbox.ListModule%7C%7B%22fid%22%3A1%2C%22order%22%3A%22date%22%2C%22desc%22%3Atrue%7D';
const ICLOUD_TARGET_MAILBOX_TYPE_INBOX = 'icloud-inbox';
const ICLOUD_TARGET_MAILBOX_TYPE_FORWARD = 'forward-mailbox';
const ICLOUD_FORWARD_MAIL_PROVIDER_OPTIONS = [
{ value: 'qq', label: 'QQ 邮箱' },
{ value: '163', label: '163 邮箱' },
{ value: '163-vip', label: '163 VIP 邮箱' },
{ value: '126', label: '126 邮箱' },
{ value: GMAIL_PROVIDER, label: 'Gmail 邮箱' },
];
function normalizeMailProvider(value = '') {
const normalized = String(value || '').trim().toLowerCase();
@@ -16,6 +26,38 @@ function normalizeMailProvider(value = '') {
}
}
function normalizeIcloudTargetMailboxType(value = '') {
return String(value || '').trim().toLowerCase() === ICLOUD_TARGET_MAILBOX_TYPE_FORWARD
? ICLOUD_TARGET_MAILBOX_TYPE_FORWARD
: ICLOUD_TARGET_MAILBOX_TYPE_INBOX;
}
function normalizeIcloudForwardMailProvider(value = '') {
const normalized = String(value || '').trim().toLowerCase();
return ICLOUD_FORWARD_MAIL_PROVIDER_OPTIONS.some((option) => option.value === normalized)
? normalized
: 'qq';
}
function getIcloudForwardMailProviderOptions() {
return ICLOUD_FORWARD_MAIL_PROVIDER_OPTIONS.map((option) => ({ ...option }));
}
function getIcloudForwardMailConfig(provider = 'qq') {
const normalizedProvider = normalizeIcloudForwardMailProvider(provider);
if (normalizedProvider === GMAIL_PROVIDER) {
return {
source: 'gmail-mail',
url: 'https://mail.google.com/mail/u/0/#inbox',
label: 'Gmail 邮箱',
inject: ['content/activation-utils.js', 'content/utils.js', 'content/gmail-mail.js'],
injectSource: 'gmail-mail',
};
}
return getMailProviderConfig({ mailProvider: normalizedProvider });
}
function getMailProviderConfig(state = {}, options = {}) {
const provider = normalizeMailProvider(state.mailProvider);
const normalizeInbucketOrigin = options.normalizeInbucketOrigin || (() => '');
@@ -66,8 +108,13 @@ function getMailProviderConfig(state = {}, options = {}) {
}
const api = {
GMAIL_PROVIDER,
HOTMAIL_PROVIDER,
getIcloudForwardMailConfig,
getIcloudForwardMailProviderOptions,
getMailProviderConfig,
normalizeIcloudForwardMailProvider,
normalizeIcloudTargetMailboxType,
normalizeMailProvider,
};
+1
View File
@@ -834,6 +834,7 @@
<script src="../managed-alias-utils.js"></script>
<script src="../mail2925-utils.js"></script>
<script src="../icloud-utils.js"></script>
<script src="../mail-provider-utils.js"></script>
<script src="../hotmail-utils.js"></script>
<script src="../luckmail-utils.js"></script>
<script src="../data/step-definitions.js"></script>
+29 -36
View File
@@ -582,17 +582,28 @@ const normalizeIcloudFetchMode = (value) => {
const normalized = String(value || '').trim().toLowerCase();
return normalized === 'always_new' ? 'always_new' : 'reuse_existing';
};
const normalizeIcloudTargetMailboxType = (value) => {
return String(value || '').trim().toLowerCase() === 'forward-mailbox'
const normalizeIcloudTargetMailboxType = window.MailProviderUtils?.normalizeIcloudTargetMailboxType
|| ((value) => String(value || '').trim().toLowerCase() === 'forward-mailbox'
? 'forward-mailbox'
: 'icloud-inbox';
};
const normalizeIcloudForwardMailProvider = (value) => {
const normalized = String(value || '').trim().toLowerCase();
return ['qq', '163', '163-vip', '126', 'gmail'].includes(normalized)
? normalized
: 'qq';
};
: 'icloud-inbox');
const getIcloudForwardMailProviderOptions = window.MailProviderUtils?.getIcloudForwardMailProviderOptions
|| (() => Array.from(selectIcloudForwardMailProvider?.options || [])
.map((option) => ({
value: String(option?.value || '').trim().toLowerCase(),
label: String(option?.textContent || option?.label || option?.value || '').trim(),
}))
.filter((option) => option.value));
const normalizeIcloudForwardMailProvider = window.MailProviderUtils?.normalizeIcloudForwardMailProvider
|| ((value) => {
const normalized = String(value || '').trim().toLowerCase();
const options = getIcloudForwardMailProviderOptions();
return options.some((option) => option.value === normalized)
? normalized
: (options[0]?.value || 'qq');
});
const ICLOUD_FORWARD_MAIL_PROVIDER_LABELS = Object.fromEntries(
getIcloudForwardMailProviderOptions().map((option) => [option.value, option.label])
);
const getIcloudLoginUrlForHost = window.IcloudUtils?.getIcloudLoginUrlForHost
|| ((host) => host === 'icloud.com.cn' ? 'https://www.icloud.com.cn/' : (host === 'icloud.com' ? 'https://www.icloud.com/' : ''));
@@ -1687,16 +1698,8 @@ function collectSettingsPayload() {
const icloudForwardMailProviderValue = typeof selectIcloudForwardMailProvider !== 'undefined'
? selectIcloudForwardMailProvider?.value
: '';
const normalizedIcloudTargetMailboxType = typeof normalizeIcloudTargetMailboxType === 'function'
? normalizeIcloudTargetMailboxType(icloudTargetMailboxTypeValue)
: (String(icloudTargetMailboxTypeValue || '').trim().toLowerCase() === 'forward-mailbox'
? 'forward-mailbox'
: 'icloud-inbox');
const normalizedIcloudForwardMailProvider = typeof normalizeIcloudForwardMailProvider === 'function'
? normalizeIcloudForwardMailProvider(icloudForwardMailProviderValue)
: (['qq', '163', '163-vip', '126', 'gmail'].includes(String(icloudForwardMailProviderValue || '').trim().toLowerCase())
? String(icloudForwardMailProviderValue || '').trim().toLowerCase()
: 'qq');
const normalizedIcloudTargetMailboxType = normalizeIcloudTargetMailboxType(icloudTargetMailboxTypeValue);
const normalizedIcloudForwardMailProvider = normalizeIcloudForwardMailProvider(icloudForwardMailProviderValue);
const mail2925UseAccountPool = typeof inputMail2925UseAccountPool !== 'undefined'
? Boolean(inputMail2925UseAccountPool?.checked)
: Boolean(latestState?.mail2925UseAccountPool);
@@ -3229,11 +3232,7 @@ function updateMailProviderUI() {
: (normalizeIcloudHostValue(icloudHostPreferenceValue || latestState?.icloudHostPreference || '')
|| normalizeIcloudHostValue(latestState?.preferredIcloudHost)
|| 'icloud.com');
const icloudTargetMailboxType = typeof normalizeIcloudTargetMailboxType === 'function'
? normalizeIcloudTargetMailboxType(icloudTargetMailboxTypeValue)
: (String(icloudTargetMailboxTypeValue || '').trim().toLowerCase() === 'forward-mailbox'
? 'forward-mailbox'
: 'icloud-inbox');
const icloudTargetMailboxType = normalizeIcloudTargetMailboxType(icloudTargetMailboxTypeValue);
const isIcloudComCnHost = selectedIcloudHost === 'icloud.com.cn';
const showIcloudTargetMailboxType = useIcloudProvider;
const showIcloudForwardMailProvider = useIcloudProvider && icloudTargetMailboxType === 'forward-mailbox';
@@ -3380,12 +3379,10 @@ function updateMailProviderUI() {
autoHintText.textContent = '已启用随机子域名:扩展会按当前选中的 Temp 域名提交,并额外携带 enableRandomSubdomain;是否生效取决于后端 RANDOM_SUBDOMAIN_DOMAINS 配置。';
}
if (autoHintText && useIcloudProvider && showIcloudForwardMailProvider) {
const forwardProvider = typeof normalizeIcloudForwardMailProvider === 'function'
? normalizeIcloudForwardMailProvider(icloudForwardMailProviderValue)
: (['qq', '163', '163-vip', '126', 'gmail'].includes(String(icloudForwardMailProviderValue || '').trim().toLowerCase())
? String(icloudForwardMailProviderValue || '').trim().toLowerCase()
: 'qq');
const forwardProviderLabel = MAIL_PROVIDER_LOGIN_CONFIGS[forwardProvider]?.label || '目标邮箱';
const forwardProvider = normalizeIcloudForwardMailProvider(icloudForwardMailProviderValue);
const forwardProviderLabel = ICLOUD_FORWARD_MAIL_PROVIDER_LABELS[forwardProvider]
|| MAIL_PROVIDER_LOGIN_CONFIGS[forwardProvider]?.label
|| '目标邮箱';
autoHintText.textContent = `iCloud ${isIcloudComCnHost ? 'com.cn' : ''} 当前使用转发收码:第 4/8 步会从 ${forwardProviderLabel} 轮询验证码。`;
}
if (useHotmail) {
@@ -3589,11 +3586,7 @@ function updateButtonStates() {
selectIcloudTargetMailboxType.disabled = disableIcloudControls;
}
if (typeof selectIcloudForwardMailProvider !== 'undefined' && selectIcloudForwardMailProvider) {
const normalizedIcloudTargetMailboxType = typeof normalizeIcloudTargetMailboxType === 'function'
? normalizeIcloudTargetMailboxType(icloudTargetMailboxTypeValue)
: (String(icloudTargetMailboxTypeValue || '').trim().toLowerCase() === 'forward-mailbox'
? 'forward-mailbox'
: 'icloud-inbox');
const normalizedIcloudTargetMailboxType = normalizeIcloudTargetMailboxType(icloudTargetMailboxTypeValue);
const allowIcloudForwardMailProvider = isIcloudMailProvider()
&& normalizedIcloudTargetMailboxType === 'forward-mailbox';
selectIcloudForwardMailProvider.disabled = disableIcloudControls || !allowIcloudForwardMailProvider;
+45 -149
View File
@@ -1,6 +1,11 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const {
getIcloudForwardMailConfig,
normalizeIcloudForwardMailProvider,
normalizeIcloudTargetMailboxType,
} = require('../mail-provider-utils.js');
const source = fs.readFileSync('background.js', 'utf8');
@@ -51,6 +56,41 @@ function extractFunction(name) {
return source.slice(start, end);
}
function createGetMailConfigApi() {
const bundle = extractFunction('getMailConfig');
return new Function('shared', `
const ICLOUD_PROVIDER = 'icloud';
const GMAIL_PROVIDER = 'gmail';
const HOTMAIL_PROVIDER = 'hotmail-api';
const LUCKMAIL_PROVIDER = 'luckmail-api';
const CLOUDFLARE_TEMP_EMAIL_PROVIDER = 'cloudflare-temp-email';
const getSharedIcloudForwardMailConfig = shared.getIcloudForwardMailConfig;
const normalizeIcloudTargetMailboxType = shared.normalizeIcloudTargetMailboxType;
const normalizeIcloudForwardMailProvider = shared.normalizeIcloudForwardMailProvider;
function normalizeIcloudHost(value = '') {
const normalized = String(value || '').trim().toLowerCase();
return normalized === 'icloud.com' || normalized === 'icloud.com.cn' ? normalized : '';
}
function normalizeInbucketOrigin(value) { return String(value || '').trim(); }
function getConfiguredIcloudHostPreference(state) {
const normalized = String(state?.icloudHostPreference || '').trim().toLowerCase();
return normalized === 'icloud.com' || normalized === 'icloud.com.cn' ? normalized : '';
}
function getIcloudLoginUrlForHost(host) {
return host === 'icloud.com.cn' ? 'https://www.icloud.com.cn/' : 'https://www.icloud.com/';
}
function getIcloudMailUrlForHost(host) {
return host === 'icloud.com.cn' ? 'https://www.icloud.com.cn/mail/' : 'https://www.icloud.com/mail/';
}
${bundle}
return { getMailConfig };
`)({
getIcloudForwardMailConfig,
normalizeIcloudForwardMailProvider,
normalizeIcloudTargetMailboxType,
});
}
test('normalizeMailProvider keeps icloud provider', () => {
const bundle = extractFunction('normalizeMailProvider');
const api = new Function(`
@@ -69,38 +109,7 @@ return { normalizeMailProvider };
});
test('getMailConfig returns icloud mail tab config with host preference', () => {
const bundle = `${extractFunction('getIcloudForwardMailConfig')}\n${extractFunction('getMailConfig')}`;
const api = new Function(`
const ICLOUD_PROVIDER = 'icloud';
const GMAIL_PROVIDER = 'gmail';
const HOTMAIL_PROVIDER = 'hotmail-api';
const LUCKMAIL_PROVIDER = 'luckmail-api';
const CLOUDFLARE_TEMP_EMAIL_PROVIDER = 'cloudflare-temp-email';
function normalizeIcloudHost(value = '') {
const normalized = String(value || '').trim().toLowerCase();
return normalized === 'icloud.com' || normalized === 'icloud.com.cn' ? normalized : '';
}
function normalizeInbucketOrigin(value) { return String(value || '').trim(); }
function getConfiguredIcloudHostPreference(state) {
const normalized = String(state?.icloudHostPreference || '').trim().toLowerCase();
return normalized === 'icloud.com' || normalized === 'icloud.com.cn' ? normalized : '';
}
function getIcloudLoginUrlForHost(host) {
return host === 'icloud.com.cn' ? 'https://www.icloud.com.cn/' : 'https://www.icloud.com/';
}
function getIcloudMailUrlForHost(host) {
return host === 'icloud.com.cn' ? 'https://www.icloud.com.cn/mail/' : 'https://www.icloud.com/mail/';
}
function normalizeIcloudTargetMailboxType(value = '') {
return String(value || '').trim().toLowerCase() === 'forward-mailbox' ? 'forward-mailbox' : 'icloud-inbox';
}
function normalizeIcloudForwardMailProvider(value = '') {
const normalized = String(value || '').trim().toLowerCase();
return ['qq', '163', '163-vip', '126', 'gmail'].includes(normalized) ? normalized : 'qq';
}
${bundle}
return { getMailConfig };
`)();
const api = createGetMailConfigApi();
assert.deepEqual(api.getMailConfig({
mailProvider: 'icloud',
@@ -114,37 +123,7 @@ return { getMailConfig };
});
test('getMailConfig reuses preferred icloud host when preference is auto', () => {
const bundle = `${extractFunction('getIcloudForwardMailConfig')}\n${extractFunction('getMailConfig')}`;
const api = new Function(`
const ICLOUD_PROVIDER = 'icloud';
const GMAIL_PROVIDER = 'gmail';
const HOTMAIL_PROVIDER = 'hotmail-api';
const LUCKMAIL_PROVIDER = 'luckmail-api';
const CLOUDFLARE_TEMP_EMAIL_PROVIDER = 'cloudflare-temp-email';
function normalizeIcloudHost(value = '') {
const normalized = String(value || '').trim().toLowerCase();
return normalized === 'icloud.com' || normalized === 'icloud.com.cn' ? normalized : '';
}
function normalizeInbucketOrigin(value) { return String(value || '').trim(); }
function getConfiguredIcloudHostPreference() {
return '';
}
function getIcloudLoginUrlForHost(host) {
return host === 'icloud.com.cn' ? 'https://www.icloud.com.cn/' : 'https://www.icloud.com/';
}
function getIcloudMailUrlForHost(host) {
return host === 'icloud.com.cn' ? 'https://www.icloud.com.cn/mail/' : 'https://www.icloud.com/mail/';
}
function normalizeIcloudTargetMailboxType(value = '') {
return String(value || '').trim().toLowerCase() === 'forward-mailbox' ? 'forward-mailbox' : 'icloud-inbox';
}
function normalizeIcloudForwardMailProvider(value = '') {
const normalized = String(value || '').trim().toLowerCase();
return ['qq', '163', '163-vip', '126', 'gmail'].includes(normalized) ? normalized : 'qq';
}
${bundle}
return { getMailConfig };
`)();
const api = createGetMailConfigApi();
assert.deepEqual(api.getMailConfig({
mailProvider: 'icloud',
@@ -159,28 +138,7 @@ return { getMailConfig };
});
test('getMailConfig keeps provider metadata for 2925 mailboxes', () => {
const bundle = `${extractFunction('getIcloudForwardMailConfig')}\n${extractFunction('getMailConfig')}`;
const api = new Function(`
const ICLOUD_PROVIDER = 'icloud';
const GMAIL_PROVIDER = 'gmail';
const HOTMAIL_PROVIDER = 'hotmail-api';
const LUCKMAIL_PROVIDER = 'luckmail-api';
const CLOUDFLARE_TEMP_EMAIL_PROVIDER = 'cloudflare-temp-email';
function normalizeIcloudHost(value = '') { return String(value || '').trim().toLowerCase(); }
function normalizeInbucketOrigin(value) { return String(value || '').trim(); }
function getConfiguredIcloudHostPreference() { return ''; }
function getIcloudLoginUrlForHost(host) { return host; }
function getIcloudMailUrlForHost(host) { return host; }
function normalizeIcloudTargetMailboxType(value = '') {
return String(value || '').trim().toLowerCase() === 'forward-mailbox' ? 'forward-mailbox' : 'icloud-inbox';
}
function normalizeIcloudForwardMailProvider(value = '') {
const normalized = String(value || '').trim().toLowerCase();
return ['qq', '163', '163-vip', '126', 'gmail'].includes(normalized) ? normalized : 'qq';
}
${bundle}
return { getMailConfig };
`)();
const api = createGetMailConfigApi();
assert.deepEqual(api.getMailConfig({
mailProvider: '2925',
@@ -195,38 +153,7 @@ return { getMailConfig };
});
test('getMailConfig uses icloud inbox config when host is com.cn and target mailbox is icloud inbox', () => {
const bundle = `${extractFunction('getIcloudForwardMailConfig')}\n${extractFunction('getMailConfig')}`;
const api = new Function(`
const ICLOUD_PROVIDER = 'icloud';
const GMAIL_PROVIDER = 'gmail';
const HOTMAIL_PROVIDER = 'hotmail-api';
const LUCKMAIL_PROVIDER = 'luckmail-api';
const CLOUDFLARE_TEMP_EMAIL_PROVIDER = 'cloudflare-temp-email';
function normalizeIcloudHost(value = '') {
const normalized = String(value || '').trim().toLowerCase();
return normalized === 'icloud.com' || normalized === 'icloud.com.cn' ? normalized : '';
}
function normalizeInbucketOrigin(value) { return String(value || '').trim(); }
function getConfiguredIcloudHostPreference(state) {
const normalized = String(state?.icloudHostPreference || '').trim().toLowerCase();
return normalized === 'icloud.com' || normalized === 'icloud.com.cn' ? normalized : '';
}
function getIcloudLoginUrlForHost(host) {
return host === 'icloud.com.cn' ? 'https://www.icloud.com.cn/' : 'https://www.icloud.com/';
}
function getIcloudMailUrlForHost(host) {
return host === 'icloud.com.cn' ? 'https://www.icloud.com.cn/mail/' : 'https://www.icloud.com/mail/';
}
function normalizeIcloudTargetMailboxType(value = '') {
return String(value || '').trim().toLowerCase() === 'forward-mailbox' ? 'forward-mailbox' : 'icloud-inbox';
}
function normalizeIcloudForwardMailProvider(value = '') {
const normalized = String(value || '').trim().toLowerCase();
return ['qq', '163', '163-vip', '126', 'gmail'].includes(normalized) ? normalized : 'qq';
}
${bundle}
return { getMailConfig };
`)();
const api = createGetMailConfigApi();
assert.deepEqual(api.getMailConfig({
mailProvider: 'icloud',
@@ -242,38 +169,7 @@ return { getMailConfig };
});
test('getMailConfig uses forward mailbox config when target mailbox type is forward', () => {
const bundle = `${extractFunction('getIcloudForwardMailConfig')}\n${extractFunction('getMailConfig')}`;
const api = new Function(`
const ICLOUD_PROVIDER = 'icloud';
const GMAIL_PROVIDER = 'gmail';
const HOTMAIL_PROVIDER = 'hotmail-api';
const LUCKMAIL_PROVIDER = 'luckmail-api';
const CLOUDFLARE_TEMP_EMAIL_PROVIDER = 'cloudflare-temp-email';
function normalizeIcloudHost(value = '') {
const normalized = String(value || '').trim().toLowerCase();
return normalized === 'icloud.com' || normalized === 'icloud.com.cn' ? normalized : '';
}
function normalizeInbucketOrigin(value) { return String(value || '').trim(); }
function getConfiguredIcloudHostPreference(state) {
const normalized = String(state?.icloudHostPreference || '').trim().toLowerCase();
return normalized === 'icloud.com' || normalized === 'icloud.com.cn' ? normalized : '';
}
function getIcloudLoginUrlForHost(host) {
return host === 'icloud.com.cn' ? 'https://www.icloud.com.cn/' : 'https://www.icloud.com/';
}
function getIcloudMailUrlForHost(host) {
return host === 'icloud.com.cn' ? 'https://www.icloud.com.cn/mail/' : 'https://www.icloud.com/mail/';
}
function normalizeIcloudTargetMailboxType(value = '') {
return String(value || '').trim().toLowerCase() === 'forward-mailbox' ? 'forward-mailbox' : 'icloud-inbox';
}
function normalizeIcloudForwardMailProvider(value = '') {
const normalized = String(value || '').trim().toLowerCase();
return ['qq', '163', '163-vip', '126', 'gmail'].includes(normalized) ? normalized : 'qq';
}
${bundle}
return { getMailConfig };
`)();
const api = createGetMailConfigApi();
assert.deepEqual(api.getMailConfig({
mailProvider: 'icloud',
+10 -3
View File
@@ -1,6 +1,10 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('fs');
const {
normalizeIcloudForwardMailProvider,
normalizeIcloudTargetMailboxType,
} = require('../mail-provider-utils.js');
const source = fs.readFileSync('background.js', 'utf8');
@@ -55,8 +59,6 @@ const bundle = [
extractFunction('normalizeEmailGenerator'),
extractFunction('getEmailGeneratorLabel'),
extractFunction('normalizeVerificationResendCount'),
extractFunction('normalizeIcloudTargetMailboxType'),
extractFunction('normalizeIcloudForwardMailProvider'),
extractFunction('normalizePersistentSettingValue'),
extractFunction('finalizeIcloudAliasAfterSuccessfulFlow'),
].join('\n');
@@ -157,6 +159,8 @@ function findIcloudAliasByEmail(aliases, email) {
function getErrorMessage(error) {
return String(typeof error === 'string' ? error : error?.message || '');
}
const normalizeIcloudTargetMailboxType = overrides.normalizeIcloudTargetMailboxType;
const normalizeIcloudForwardMailProvider = overrides.normalizeIcloudForwardMailProvider;
${bundle}
@@ -177,7 +181,10 @@ test('normalizeEmailGenerator and label support icloud', () => {
});
test('normalizePersistentSettingValue handles icloud settings', () => {
const api = createApi();
const api = createApi({
normalizeIcloudTargetMailboxType,
normalizeIcloudForwardMailProvider,
});
assert.equal(api.normalizePersistentSettingValue('icloudHostPreference', 'icloud.com'), 'icloud.com');
assert.equal(api.normalizePersistentSettingValue('icloudHostPreference', 'bad-host'), 'auto');
assert.equal(api.normalizePersistentSettingValue('icloudTargetMailboxType', 'forward-mailbox'), 'forward-mailbox');
+30
View File
@@ -3,7 +3,11 @@ const assert = require('node:assert/strict');
const {
HOTMAIL_PROVIDER,
getIcloudForwardMailConfig,
getIcloudForwardMailProviderOptions,
getMailProviderConfig,
normalizeIcloudForwardMailProvider,
normalizeIcloudTargetMailboxType,
normalizeMailProvider,
} = require('../mail-provider-utils.js');
@@ -33,3 +37,29 @@ test('getMailProviderConfig preserves the hotmail provider sentinel', () => {
}
);
});
test('iCloud forward mailbox helpers normalize and expose supported providers', () => {
assert.equal(normalizeIcloudTargetMailboxType('forward-mailbox'), 'forward-mailbox');
assert.equal(normalizeIcloudTargetMailboxType('unknown'), 'icloud-inbox');
assert.equal(normalizeIcloudForwardMailProvider('GMAIL'), 'gmail');
assert.equal(normalizeIcloudForwardMailProvider('unknown'), 'qq');
assert.deepEqual(
getIcloudForwardMailProviderOptions().map((option) => option.value),
['qq', '163', '163-vip', '126', 'gmail']
);
});
test('getIcloudForwardMailConfig reuses shared mailbox provider configs', () => {
assert.deepEqual(getIcloudForwardMailConfig('126'), {
source: 'mail-163',
url: 'https://mail.126.com/js6/main.jsp?df=mail163_letter#module=mbox.ListModule%7C%7B%22fid%22%3A1%2C%22order%22%3A%22date%22%2C%22desc%22%3Atrue%7D',
label: '126 邮箱',
});
assert.deepEqual(getIcloudForwardMailConfig('gmail'), {
source: 'gmail-mail',
url: 'https://mail.google.com/mail/u/0/#inbox',
label: 'Gmail 邮箱',
inject: ['content/activation-utils.js', 'content/utils.js', 'content/gmail-mail.js'],
injectSource: 'gmail-mail',
});
});
@@ -1,6 +1,10 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const {
normalizeIcloudForwardMailProvider,
normalizeIcloudTargetMailboxType,
} = require('../mail-provider-utils');
const source = fs.readFileSync('sidepanel/sidepanel.js', 'utf8');
@@ -172,7 +176,7 @@ return {
test('updateMailProviderUI keeps the temp domain selector visible and updates the hint when random subdomain is enabled', () => {
const bundle = extractFunction('updateMailProviderUI');
const api = new Function(`
const api = new Function('normalizeIcloudTargetMailboxType', 'normalizeIcloudForwardMailProvider', `
let latestState = {
cloudflareTempEmailDomains: ['mail.example.com'],
};
@@ -254,7 +258,7 @@ return {
autoHintText,
calls,
};
`)();
`)(normalizeIcloudTargetMailboxType, normalizeIcloudForwardMailProvider);
api.updateMailProviderUI();
assert.equal(api.cloudflareTempEmailSection.style.display, '');
+6 -2
View File
@@ -1,6 +1,10 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const {
normalizeIcloudForwardMailProvider,
normalizeIcloudTargetMailboxType,
} = require('../mail-provider-utils');
const sidepanelSource = fs.readFileSync('sidepanel/sidepanel.js', 'utf8');
@@ -121,7 +125,7 @@ test('sidepanel html contains contribution mode runtime UI and loads the module
test('collectSettingsPayload omits custom password and local sync settings in contribution mode', () => {
const bundle = extractFunction('collectSettingsPayload');
const api = new Function(`
const api = new Function('normalizeIcloudTargetMailboxType', 'normalizeIcloudForwardMailProvider', `
let latestState = { contributionMode: true };
let cloudflareDomainEditMode = false;
let cloudflareTempEmailDomainEditMode = false;
@@ -188,7 +192,7 @@ return {
collectSettingsPayload,
setLatestState(nextState) { latestState = nextState; },
};
`)();
`)(normalizeIcloudTargetMailboxType, normalizeIcloudForwardMailProvider);
const contributionPayload = api.collectSettingsPayload();
assert.equal('customPassword' in contributionPayload, false);
+294
View File
@@ -79,3 +79,297 @@ return { getSelectedIcloudHostPreference, getMailProviderLoginUrl };
assert.equal(api.getSelectedIcloudHostPreference(), 'icloud.com.cn');
assert.equal(api.getMailProviderLoginUrl(), 'https://www.icloud.com.cn/');
});
test('collectSettingsPayload persists icloud target mailbox settings', () => {
const bundle = extractFunction('collectSettingsPayload');
const api = new Function(`
let latestState = { contributionMode: false };
let cloudflareDomainEditMode = false;
let cloudflareTempEmailDomainEditMode = false;
const selectCfDomain = { value: '' };
const selectTempEmailDomain = { value: '' };
const selectPanelMode = { value: 'cpa' };
const inputVpsUrl = { value: '' };
const inputVpsPassword = { value: '' };
const inputSub2ApiUrl = { value: '' };
const inputSub2ApiEmail = { value: '' };
const inputSub2ApiPassword = { value: '' };
const inputSub2ApiGroup = { value: '' };
const inputSub2ApiDefaultProxy = { value: '' };
const inputCodex2ApiUrl = { value: '' };
const inputCodex2ApiAdminKey = { value: '' };
const inputPassword = { value: '' };
const selectMailProvider = { value: 'icloud' };
const selectEmailGenerator = { value: 'duck' };
const checkboxAutoDeleteIcloud = { checked: false };
const selectIcloudHostPreference = { value: 'auto' };
const selectIcloudFetchMode = { value: 'reuse_existing' };
const selectIcloudTargetMailboxType = { value: 'forward-mailbox' };
const selectIcloudForwardMailProvider = { value: 'gmail' };
const inputPhoneVerificationEnabled = { checked: false };
const inputAccountRunHistoryTextEnabled = { checked: false };
const inputAccountRunHistoryHelperBaseUrl = { value: '' };
const inputInbucketHost = { value: '' };
const inputInbucketMailbox = { value: '' };
const inputHotmailRemoteBaseUrl = { value: '' };
const inputHotmailLocalBaseUrl = { value: '' };
const inputLuckmailApiKey = { value: '' };
const inputLuckmailBaseUrl = { value: '' };
const selectLuckmailEmailType = { value: 'ms_graph' };
const inputLuckmailDomain = { value: '' };
const inputTempEmailBaseUrl = { value: '' };
const inputTempEmailAdminAuth = { value: '' };
const inputTempEmailCustomAuth = { value: '' };
const inputTempEmailReceiveMailbox = { value: '' };
const inputTempEmailUseRandomSubdomain = { checked: false };
const inputAutoSkipFailures = { checked: false };
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '0' };
const inputAutoDelayEnabled = { checked: false };
const inputAutoDelayMinutes = { value: '30' };
const inputAutoStepDelaySeconds = { value: '' };
const inputVerificationResendCount = { value: '4' };
const DEFAULT_VERIFICATION_RESEND_COUNT = 4;
function getCloudflareDomainsFromState() { return { domains: [], activeDomain: '' }; }
function normalizeCloudflareDomainValue(value) { return String(value || '').trim(); }
function getCloudflareTempEmailDomainsFromState() { return { domains: [], activeDomain: '' }; }
function normalizeCloudflareTempEmailDomainValue(value) { return String(value || '').trim(); }
function getSelectedLocalCpaStep9Mode() { return 'submit'; }
function getSelectedMail2925Mode() { return 'provide'; }
function buildManagedAliasBaseEmailPayload() { return { gmailBaseEmail: '', mail2925BaseEmail: '', emailPrefix: '' }; }
function getSelectedHotmailServiceMode() { return 'local'; }
function normalizeLuckmailBaseUrl(value) { return String(value || '').trim(); }
function normalizeLuckmailEmailType(value) { return String(value || '').trim() || 'ms_graph'; }
function normalizeCloudflareTempEmailBaseUrlValue(value) { return String(value || '').trim(); }
function normalizeCloudflareTempEmailReceiveMailboxValue(value) { return String(value || '').trim(); }
function normalizeAccountRunHistoryHelperBaseUrlValue(value) { return String(value || '').trim(); }
function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) || 0; }
function normalizeAutoDelayMinutes(value) { return Number(value) || 30; }
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
function normalizeVerificationResendCount(value, fallback) { return Number(value) || fallback; }
function normalizeIcloudTargetMailboxType(value) { return String(value || '').trim().toLowerCase() === 'forward-mailbox' ? 'forward-mailbox' : 'icloud-inbox'; }
function normalizeIcloudForwardMailProvider(value) { return String(value || '').trim().toLowerCase() === 'gmail' ? 'gmail' : 'qq'; }
${bundle}
return { collectSettingsPayload };
`)();
const payload = api.collectSettingsPayload();
assert.equal(payload.icloudTargetMailboxType, 'forward-mailbox');
assert.equal(payload.icloudForwardMailProvider, 'gmail');
});
test('updateMailProviderUI toggles icloud forward mailbox controls and hint', () => {
const bundle = extractFunction('updateMailProviderUI');
const createRow = (display = 'none') => ({ style: { display } });
const api = new Function('createRow', `
let latestState = { icloudHostPreference: 'icloud.com.cn' };
let cloudflareDomainEditMode = false;
let cloudflareTempEmailDomainEditMode = false;
const ICLOUD_PROVIDER = 'icloud';
const GMAIL_PROVIDER = 'gmail';
const GMAIL_ALIAS_GENERATOR = 'gmail-alias';
const LUCKMAIL_PROVIDER = 'luckmail-api';
const CUSTOM_EMAIL_POOL_GENERATOR = 'custom-pool';
const HOTMAIL_SERVICE_MODE_REMOTE = 'remote';
const HOTMAIL_SERVICE_MODE_LOCAL = 'local';
const rowMail2925Mode = createRow();
const rowMail2925PoolSettings = createRow();
const rowEmailPrefix = createRow();
const rowCustomMailProviderPool = createRow();
const rowInbucketHost = createRow();
const rowInbucketMailbox = createRow();
const rowEmailGenerator = createRow();
const rowCfDomain = createRow();
const rowTempEmailBaseUrl = createRow();
const rowTempEmailAdminAuth = createRow();
const rowTempEmailCustomAuth = createRow();
const rowTempEmailReceiveMailbox = createRow();
const rowTempEmailRandomSubdomainToggle = createRow();
const rowTempEmailDomain = createRow();
const cloudflareTempEmailSection = createRow();
const hotmailSection = createRow();
const mail2925Section = createRow();
const luckmailSection = createRow();
const icloudSection = createRow();
const rowIcloudTargetMailboxType = createRow();
const rowIcloudForwardMailProvider = createRow();
const labelEmailPrefix = { textContent: '' };
const inputEmailPrefix = { placeholder: '', style: { display: '' }, readOnly: false };
const labelMail2925UseAccountPool = createRow();
const selectMail2925PoolAccount = { style: { display: 'none' }, disabled: false };
const btnFetchEmail = { hidden: false, disabled: false, textContent: '' };
const btnMailLogin = { disabled: false, textContent: '', title: '' };
const inputEmail = { readOnly: false, placeholder: '', value: '' };
const autoHintText = { textContent: '' };
const rowHotmailServiceMode = createRow();
const rowHotmailRemoteBaseUrl = createRow();
const rowHotmailLocalBaseUrl = createRow();
const inputMail2925UseAccountPool = { checked: false };
const selectMailProvider = { value: 'icloud' };
const selectEmailGenerator = { value: 'duck', disabled: false, options: [] };
const selectIcloudTargetMailboxType = { value: 'icloud-inbox' };
const selectIcloudForwardMailProvider = { value: 'gmail' };
const selectIcloudHostPreference = { value: 'icloud.com.cn' };
const inputTempEmailUseRandomSubdomain = { checked: false };
const inputRunCount = { disabled: false };
const currentAutoRun = { autoRunning: false };
const MAIL_PROVIDER_LOGIN_CONFIGS = { gmail: { label: 'Gmail 邮箱' } };
const ICLOUD_FORWARD_MAIL_PROVIDER_LABELS = { gmail: 'Gmail 邮箱' };
function normalizeIcloudHost(value) { return String(value || '').trim().toLowerCase(); }
function normalizeIcloudTargetMailboxType(value) { return String(value || '').trim().toLowerCase() === 'forward-mailbox' ? 'forward-mailbox' : 'icloud-inbox'; }
function normalizeIcloudForwardMailProvider(value) { return String(value || '').trim().toLowerCase() === 'gmail' ? 'gmail' : 'qq'; }
function getSelectedIcloudHostPreference() { return selectIcloudHostPreference.value; }
function isLuckmailProvider() { return false; }
function isCustomMailProvider() { return false; }
function isIcloudMailProvider() { return selectMailProvider.value === ICLOUD_PROVIDER; }
function usesCustomMailProviderPool() { return false; }
function usesGeneratedAliasMailProvider() { return false; }
function getSelectedMail2925Mode() { return 'provide'; }
function getManagedAliasProviderUiCopy() { return null; }
function getCurrentRegistrationEmailUiCopy() { return { buttonLabel: '获取邮箱', placeholder: '邮箱', label: '邮箱' }; }
function updateMailLoginButtonState() {}
function getSelectedHotmailServiceMode() { return 'local'; }
function getCloudflareDomainsFromState() { return { domains: [], activeDomain: '' }; }
function setCloudflareDomainEditMode() {}
function getCloudflareTempEmailDomainsFromState() { return { domains: [], activeDomain: '' }; }
function setCloudflareTempEmailDomainEditMode() {}
function queueIcloudAliasRefresh() {}
function hideIcloudLoginHelp() {}
function syncMail2925PoolAccountOptions() {}
function getMail2925Accounts() { return []; }
function renderHotmailAccounts() {}
function renderMail2925Accounts() {}
function renderLuckmailPurchases() {}
function getSelectedEmailGenerator() { return selectEmailGenerator.value; }
function isAutoRunLockedPhase() { return false; }
function getCurrentHotmailEmail() { return ''; }
function getCurrentLuckmailEmail() { return ''; }
function getCustomEmailPoolSize() { return 0; }
function getCustomMailProviderPoolSize() { return 0; }
function syncRunCountFromCustomEmailPool() {}
function syncRunCountFromCustomMailProviderPool() {}
function shouldLockRunCountToEmailPool() { return false; }
${bundle}
return {
updateMailProviderUI,
rowIcloudTargetMailboxType,
rowIcloudForwardMailProvider,
selectIcloudTargetMailboxType,
autoHintText,
};
`)(createRow);
api.updateMailProviderUI();
assert.equal(api.rowIcloudTargetMailboxType.style.display, '');
assert.equal(api.rowIcloudForwardMailProvider.style.display, 'none');
api.selectIcloudTargetMailboxType.value = 'forward-mailbox';
api.updateMailProviderUI();
assert.equal(api.rowIcloudForwardMailProvider.style.display, '');
assert.match(api.autoHintText.textContent, /Gmail 邮箱/);
});
test('applySettingsState restores icloud forward mailbox settings before UI refresh', () => {
const bundle = extractFunction('applySettingsState');
const calls = [];
const api = new Function('calls', `
let latestState = {};
const inputEmail = { value: '' };
const inputVpsUrl = { value: '' };
const inputVpsPassword = { value: '' };
const selectPanelMode = { value: 'cpa' };
const inputSub2ApiUrl = { value: '' };
const inputSub2ApiEmail = { value: '' };
const inputSub2ApiPassword = { value: '' };
const inputSub2ApiGroup = { value: '' };
const inputSub2ApiDefaultProxy = { value: '' };
const inputCodex2ApiUrl = { value: '' };
const inputCodex2ApiAdminKey = { value: '' };
const ICLOUD_PROVIDER = 'icloud';
const GMAIL_PROVIDER = 'gmail';
const GMAIL_ALIAS_GENERATOR = 'gmail-alias';
const CUSTOM_EMAIL_POOL_GENERATOR = 'custom-pool';
const selectMailProvider = { value: '163' };
const selectEmailGenerator = { value: 'duck' };
const selectIcloudHostPreference = { value: 'auto' };
const selectIcloudFetchMode = { value: 'reuse_existing' };
const selectIcloudTargetMailboxType = { value: 'icloud-inbox' };
const selectIcloudForwardMailProvider = { value: 'qq' };
const checkboxAutoDeleteIcloud = { checked: false };
const inputAccountRunHistoryHelperBaseUrl = { value: '' };
const inputContributionNickname = { value: '' };
const inputContributionQq = { value: '' };
const inputMail2925UseAccountPool = { checked: false };
const inputInbucketHost = { value: '' };
const inputInbucketMailbox = { value: '' };
const inputCustomMailProviderPool = { value: '' };
const inputCustomEmailPool = { value: '' };
const inputHotmailRemoteBaseUrl = { value: '' };
const inputHotmailLocalBaseUrl = { value: '' };
const inputLuckmailApiKey = { value: '' };
const inputLuckmailBaseUrl = { value: '' };
const selectLuckmailEmailType = { value: 'ms_graph' };
const inputLuckmailDomain = { value: '' };
const inputAutoSkipFailures = { checked: false };
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '' };
const inputAutoDelayEnabled = { checked: false };
const inputAutoDelayMinutes = { value: '' };
const inputAutoStepDelaySeconds = { value: '' };
const inputVerificationResendCount = { value: '' };
const inputPhoneVerificationEnabled = { checked: false };
const DEFAULT_PHONE_VERIFICATION_ENABLED = false;
const inputHeroSmsApiKey = { value: '' };
const selectHeroSmsCountry = { value: '52', options: [{ value: '52' }] };
const inputRunCount = { value: '' };
const DEFAULT_VERIFICATION_RESEND_COUNT = 4;
function syncLatestState(state) { latestState = { ...latestState, ...state }; }
function syncAutoRunState() {}
function syncPasswordField() {}
function setLocalCpaStep9Mode() {}
function isCustomMailProvider() { return false; }
function setMail2925Mode() {}
function normalizeIcloudFetchMode(value) { return String(value || '') === 'always_new' ? 'always_new' : 'reuse_existing'; }
function normalizeIcloudTargetMailboxType(value) { return String(value || '').trim().toLowerCase() === 'forward-mailbox' ? 'forward-mailbox' : 'icloud-inbox'; }
function normalizeIcloudForwardMailProvider(value) { return String(value || '').trim().toLowerCase() === 'gmail' ? 'gmail' : 'qq'; }
function normalizeAccountRunHistoryHelperBaseUrlValue(value) { return String(value || '').trim(); }
function setManagedAliasBaseEmailInputForProvider() {}
function normalizeCustomEmailPoolEntries(value) { return Array.isArray(value) ? value : []; }
function setHotmailServiceMode() {}
function normalizeLuckmailBaseUrl(value) { return String(value || '').trim(); }
function normalizeLuckmailEmailType(value) { return String(value || '').trim() || 'ms_graph'; }
function applyCloudflareTempEmailSettingsState() {}
function renderCloudflareDomainOptions() {}
function setCloudflareDomainEditMode() {}
function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) || 0; }
function normalizeAutoDelayMinutes(value) { return Number(value) || 30; }
function formatAutoStepDelayInputValue(value) { return value == null ? '' : String(value); }
function normalizeVerificationResendCount(value, fallback) { return Number(value) || fallback; }
function normalizeHeroSmsCountryId() { return 52; }
function getSelectedHeroSmsCountryOption() { return { label: 'Thailand' }; }
function updateHeroSmsPlatformDisplay() {}
function applyAutoRunStatus() {}
function markSettingsDirty() {}
function updateAutoDelayInputState() {}
function updateFallbackThreadIntervalInputState() {}
function updateAccountRunHistorySettingsUI() {}
function updatePhoneVerificationSettingsUI() {}
function updatePanelModeUI() {}
function updateMailProviderUI() { calls.push({ target: selectIcloudTargetMailboxType.value, provider: selectIcloudForwardMailProvider.value }); }
function isLuckmailProvider() { return false; }
function updateButtonStates() {}
${bundle}
return { applySettingsState, selectIcloudTargetMailboxType, selectIcloudForwardMailProvider };
`)(calls);
api.applySettingsState({
mailProvider: 'icloud',
icloudTargetMailboxType: 'forward-mailbox',
icloudForwardMailProvider: 'gmail',
});
assert.equal(api.selectIcloudTargetMailboxType.value, 'forward-mailbox');
assert.equal(api.selectIcloudForwardMailProvider.value, 'gmail');
assert.deepEqual(calls.at(-1), { target: 'forward-mailbox', provider: 'gmail' });
});
+6 -2
View File
@@ -1,6 +1,10 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const {
normalizeIcloudForwardMailProvider,
normalizeIcloudTargetMailboxType,
} = require('../mail-provider-utils');
const sidepanelSource = fs.readFileSync('sidepanel/sidepanel.js', 'utf8');
@@ -148,7 +152,7 @@ test('collectSettingsPayload persists currentMail2925AccountId for 2925 account
extractFunction('collectSettingsPayload'),
].join('\n');
const api = new Function(`
const api = new Function('normalizeIcloudTargetMailboxType', 'normalizeIcloudForwardMailProvider', `
let latestState = {
contributionMode: false,
mail2925UseAccountPool: true,
@@ -222,7 +226,7 @@ function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Num
function normalizeVerificationResendCount(value, fallback) { return Number(value) || fallback; }
${bundle}
return { collectSettingsPayload };
`)();
`)(normalizeIcloudTargetMailboxType, normalizeIcloudForwardMailProvider);
const payload = api.collectSettingsPayload();
@@ -1,6 +1,10 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const {
normalizeIcloudForwardMailProvider,
normalizeIcloudTargetMailboxType,
} = require('../mail-provider-utils');
const sidepanelSource = fs.readFileSync('sidepanel/sidepanel.js', 'utf8');
@@ -90,7 +94,7 @@ return {
});
test('collectSettingsPayload keeps local helper sync enabled while persisting sms toggle state', () => {
const api = new Function(`
const api = new Function('normalizeIcloudTargetMailboxType', 'normalizeIcloudForwardMailProvider', `
let latestState = {
contributionMode: false,
mail2925UseAccountPool: false,
@@ -168,7 +172,7 @@ ${extractFunction('normalizeHeroSmsCountryLabel')}
${extractFunction('getSelectedHeroSmsCountryOption')}
${extractFunction('collectSettingsPayload')}
return { collectSettingsPayload };
`)();
`)(normalizeIcloudTargetMailboxType, normalizeIcloudForwardMailProvider);
const payload = api.collectSettingsPayload();
+16 -1
View File
@@ -163,7 +163,7 @@
- 2925 当前选中的号池账号 ID `currentMail2925AccountId`
- Cloudflare / Temp Email 设置
- 接码开关,以及 HeroSMS 的 API Key 与默认国家设置
- iCloud 相关偏好
- iCloud 相关偏好:Host、获取策略、成功后自动删除、目标邮箱类型与转发收码邮箱 provider
- LuckMail API 配置
- 自动运行默认配置
- 账号运行历史 `accountRunHistory`(以邮箱为主键,保存该邮箱最近一次状态:成功/失败/停止)
@@ -605,6 +605,7 @@ Codex2API 补充:
- `163``163 VIP``126` 都走同一条“网易网页邮箱”验证码链路。
- sidepanel 只负责切换 provider 与展示登录入口;后台根据 provider 选择对应网页邮箱首页。
- 内容脚本来源统一归类到 `mail-163`,这样 Step 4 / Step 8 继续复用同一套验证码读取与邮件清理逻辑。
- `mail-provider-utils.js` 同时承接 iCloud 转发收码可选 provider 的归一化与入口配置,避免 background / sidepanel 重新复制 QQ、网易和 Gmail 的收码地址、label 与注入脚本。
- `manifest.json` 需要同时覆盖:
- `https://mail.163.com/*`
- `https://webmail.vip.163.com/*`
@@ -699,8 +700,22 @@ Codex2API 补充:
组成:
- [icloud-utils.js](c:/Users/projectf/Downloads/codex注册扩展/icloud-utils.js)
- [mail-provider-utils.js](c:/Users/projectf/Downloads/codex注册扩展/mail-provider-utils.js)
- [content/icloud-mail.js](c:/Users/projectf/Downloads/codex注册扩展/content/icloud-mail.js)
配置:
- `icloudHostPreference` 只决定 iCloud 登录、别名管理和 iCloud Mail 收件箱 Host。
- `icloudFetchMode` 决定生成注册邮箱时复用已有 Hide My Email 别名,还是始终创建新别名。
- `icloudTargetMailboxType = icloud-inbox` 时,Step 4 / Step 8 直接打开 iCloud Mail 收件箱轮询验证码。
- `icloudTargetMailboxType = forward-mailbox` 时,注册邮箱仍由 iCloud Hide My Email 生成,但 Step 4 / Step 8 改为打开 `icloudForwardMailProvider` 指定的转发目标邮箱收码;当前支持 `qq / 163 / 163-vip / 126 / gmail`
维护约定:
- iCloud 转发目标邮箱 provider 的 label、URL、source、inject 配置统一由 `mail-provider-utils.js` 输出。
- `background.js` 只根据 `icloudTargetMailboxType` 选择 iCloud Mail 收件箱或共享转发邮箱配置,不再在主文件内硬编码各 provider 地址。
- `sidepanel/sidepanel.js` 只负责展示、保存和回显目标邮箱类型 / 转发邮箱 provider,不重复定义 provider 业务清单。
## 8. 自动运行完整链路
文件:
+6 -6
View File
@@ -26,7 +26,7 @@
- `hotmail-utils.js`:Hotmail 账号与验证码提取相关的纯工具函数,负责账号筛选、验证码匹配、第三方接口数据归一化。
- `icloud-utils.js`:iCloud 隐私邮箱相关的纯工具函数,负责 host、别名列表、保留状态、已用状态等归一化。
- `luckmail-utils.js`:LuckMail 相关的纯工具函数,负责邮箱购买记录、标签、邮件 cursor、验证码匹配等归一化。
- `mail-provider-utils.js`:网页邮箱 provider 配置纯工具,负责 `163 / 163 VIP / 126 / QQ / Inbucket / Hotmail` 的基础归一化与页面入口配置。
- `mail-provider-utils.js`:网页邮箱 provider 配置纯工具,负责 `163 / 163 VIP / 126 / QQ / Inbucket / Hotmail` 的基础归一化与页面入口配置,并统一承接 iCloud 转发收码目标邮箱 provider 的归一化、选项列表和收码入口配置
- `mail2925-utils.js`:2925 账号池相关的纯工具函数,负责账号归一化、冷却期判断、可用账号挑选、批量导入解析与列表更新。
- `managed-alias-utils.js`:共享 Gmail / 2925 的别名邮箱规则,负责解析基邮箱、校验“当前完整注册邮箱”是否仍与基邮箱兼容、生成 Gmail `+tag` 与 2925 随机后缀邮箱,并输出 sidepanel 可复用的 UI 文案;当前还统一承接 `mail2925Mode` 的归一化与“2925 仅在 provide 模式下参与别名生成”的共享判定。
- `manifest.json`:Chrome 扩展清单,声明权限、背景脚本、侧边栏、内容脚本与规则集。
@@ -125,8 +125,8 @@
- `sidepanel/contribution-content-update-service.js`:侧边栏贡献内容更新服务,负责拉取 `https://apikey.qzz.io/api/content-summary`、缓存公开公告/教程摘要,并输出可用于提示展示的 `promptVersion` 与最新更新时间。
- `sidepanel/contribution-mode.js`:侧边栏贡献模式管理器,负责顶部“贡献”按钮、确认弹窗、贡献模式显隐、复用主自动流程启动、侧栏内贡献状态轮询、上传页跳转,以及贡献模式下对来源选择、配置入口、记录入口和敏感配置行(包括 Codex2API 配置)的禁用与隐藏。
- `sidepanel/sidepanel.css`:侧边栏样式文件;当前额外提供 Hotmail / 2925 共用的号池表单容器、操作按钮行与统一的收起态列表高度样式。
- `sidepanel/sidepanel.html`:侧边栏页面结构;当前步骤列表已改为动态容器,日志区提供“记录”按钮并挂接邮箱记录覆盖层,顶部新增“贡献”按钮并在设置卡片中新增贡献模式主面板;贡献按钮下方额外挂接一个可关闭的轻提示气泡,用于提示公开公告 / 使用教程有更新;贡献面板内展示 `OAUTH / 回调 / 总状态` 三块真实运行态信息,同时把“接码”开关与“验证码重发”拆成同一行展示;只有开启接码后,下面的 HeroSMS 平台、国家与 API Key 行才会显示;页面继续加载 `managed-alias-utils.js`,并把旧的“邮箱前缀”字段语义改为“别名基邮箱”;当 provider 为 2925 时,会额外显示 `提供邮箱 / 接收邮箱` 模式切换,并把“2925 号池”从别名基邮箱行拆成独立配置行,避免 receive 模式把账号池开关一起隐藏;当前在 `邮箱生成` 区域新增 `自定义邮箱池` 选项和多行邮箱池输入框,并在 `邮箱服务 = 自定义邮箱` 时额外显示 `自定义号池` 文本框;来源下拉框当前支持 `CPA / SUB2API / Codex2API`,其中 Codex2API 额外提供后台地址和管理密钥配置行;Hotmail / 2925 两个账号池当前都使用统一的头部“添加账号/取消添加”按钮和共享表单容器。
- `sidepanel/sidepanel.js`:侧边栏主入口脚本,负责 UI 状态同步、动态步骤渲染、按钮交互、共享验证码自动重发次数配置与广播接收,并装配 Hotmail / 2925 / iCloud / LuckMail / 贡献模式 / 邮箱记录面板 / 贡献内容更新服务;当前贡献模式的“开始贡献”会直接复用主自动流程启动逻辑,而独立 manager 负责贡献运行态展示与轮询,同时把 Gmail / 2925 的基邮箱输入、完整注册邮箱输入、自动生成按钮与兼容性校验统一接到共享别名逻辑上;当 provider 为 2925 时,会根据 `mail2925Mode` 决定是否启用别名基邮箱链路,而 2925 号池开关与当前账号选择则独立显示并同时服务于 provide / receive 两种模式;`自定义邮箱池` 模式会按邮箱池长度锁定自动轮数,并把当前输入的邮箱池配置参与自动启动前保存;`邮箱服务 = 自定义邮箱` 时,如果配置了 `customMailProviderPool`,也会按号池长度锁定自动轮数并在 Auto 中按轮次分配注册邮箱,同时在普通失败时继续复用当前邮箱,只有成功或出现手机号验证时才切换下一个邮箱;Step 8 的自定义邮箱确认弹窗当前额外提供“出现手机号验证”按钮,用于直接走与真实 add-phone 一致的 fatal 分支;HeroSMS 国家列表会在 sidepanel 初始化时拉取并恢复到本地保存的国家/API 设置,接码开关关闭时会直接隐藏相关配置;账号记录快照同步改为默认自动模式,只要本地 helper 可用就会自动落盘;新来源 Codex2API 在这里仅补充来源配置接线、表单显隐和 Step 10 按钮文案,不承接协议业务逻辑;Hotmail / 2925 的新增表单显隐统一接到 `sidepanel/account-pool-ui.js` 这一层共享 helper;侧边栏初始化与点击“自动”前会刷新一次贡献站公开内容摘要,并按本地关闭版本决定是否展示轻提示,同时在首次初始化后按现有规则决定是否弹出新手引导提示。
- `sidepanel/sidepanel.html`:侧边栏页面结构;当前步骤列表已改为动态容器,日志区提供“记录”按钮并挂接邮箱记录覆盖层,顶部新增“贡献”按钮并在设置卡片中新增贡献模式主面板;贡献按钮下方额外挂接一个可关闭的轻提示气泡,用于提示公开公告 / 使用教程有更新;贡献面板内展示 `OAUTH / 回调 / 总状态` 三块真实运行态信息,同时把“接码”开关与“验证码重发”拆成同一行展示;只有开启接码后,下面的 HeroSMS 平台、国家与 API Key 行才会显示;页面继续加载 `managed-alias-utils.js``mail-provider-utils.js`,并把旧的“邮箱前缀”字段语义改为“别名基邮箱”;当 provider 为 2925 时,会额外显示 `提供邮箱 / 接收邮箱` 模式切换,并把“2925 号池”从别名基邮箱行拆成独立配置行,避免 receive 模式把账号池开关一起隐藏;当前在 `邮箱生成` 区域新增 `自定义邮箱池` 选项和多行邮箱池输入框,并在 `邮箱服务 = 自定义邮箱` 时额外显示 `自定义号池` 文本框;当邮箱服务为 iCloud 时,额外提供目标邮箱类型与转发邮箱 provider 配置,用于选择直接从 iCloud 收件箱收码或从 QQ / 网易 / Gmail 转发目标邮箱收码;来源下拉框当前支持 `CPA / SUB2API / Codex2API`,其中 Codex2API 额外提供后台地址和管理密钥配置行;Hotmail / 2925 两个账号池当前都使用统一的头部“添加账号/取消添加”按钮和共享表单容器。
- `sidepanel/sidepanel.js`:侧边栏主入口脚本,负责 UI 状态同步、动态步骤渲染、按钮交互、共享验证码自动重发次数配置与广播接收,并装配 Hotmail / 2925 / iCloud / LuckMail / 贡献模式 / 邮箱记录面板 / 贡献内容更新服务;当前贡献模式的“开始贡献”会直接复用主自动流程启动逻辑,而独立 manager 负责贡献运行态展示与轮询,同时把 Gmail / 2925 的基邮箱输入、完整注册邮箱输入、自动生成按钮与兼容性校验统一接到共享别名逻辑上;当 provider 为 2925 时,会根据 `mail2925Mode` 决定是否启用别名基邮箱链路,而 2925 号池开关与当前账号选择则独立显示并同时服务于 provide / receive 两种模式;当 provider 为 iCloud 时,会保存并回显目标邮箱类型与转发邮箱 provider,相关 provider 选项和 label 复用 `mail-provider-utils.js``自定义邮箱池` 模式会按邮箱池长度锁定自动轮数,并把当前输入的邮箱池配置参与自动启动前保存;`邮箱服务 = 自定义邮箱` 时,如果配置了 `customMailProviderPool`,也会按号池长度锁定自动轮数并在 Auto 中按轮次分配注册邮箱,同时在普通失败时继续复用当前邮箱,只有成功或出现手机号验证时才切换下一个邮箱;Step 8 的自定义邮箱确认弹窗当前额外提供“出现手机号验证”按钮,用于直接走与真实 add-phone 一致的 fatal 分支;HeroSMS 国家列表会在 sidepanel 初始化时拉取并恢复到本地保存的国家/API 设置,接码开关关闭时会直接隐藏相关配置;账号记录快照同步改为默认自动模式,只要本地 helper 可用就会自动落盘;新来源 Codex2API 在这里仅补充来源配置接线、表单显隐和 Step 10 按钮文案,不承接协议业务逻辑;Hotmail / 2925 的新增表单显隐统一接到 `sidepanel/account-pool-ui.js` 这一层共享 helper;侧边栏初始化与点击“自动”前会刷新一次贡献站公开内容摘要,并按本地关闭版本决定是否展示轻提示,同时在首次初始化后按现有规则决定是否弹出新手引导提示。
- `sidepanel/update-service.js`:侧边栏更新检查服务,负责 GitHub Releases 查询、`Pro` / `v` 双版本族排序、缓存读取与版本展示。
## `tests/`
@@ -146,7 +146,7 @@
- `tests/background-custom-email-pool.test.js`:测试后台对自定义邮箱池生成方式,以及自定义邮箱服务号池的归一化、标签文案和按轮次取邮箱逻辑。
- `tests/background-generated-email-module.test.js`:测试生成邮箱辅助模块已接入且导出工厂,并覆盖 2925 receive 模式回退普通邮箱生成、自定义邮箱池按轮次取值、2925 provide 模式账号池预热,以及 iCloud `always_new` 传参。
- `tests/background-icloud.test.js`:测试 iCloud 相关后台纯函数与别名收尾逻辑。
- `tests/background-icloud-mail-provider.test.js`:测试 iCloud 邮箱 provider 配置解析。
- `tests/background-icloud-mail-provider.test.js`:测试 iCloud 邮箱 provider 配置解析,并覆盖转发收码模式复用共享 provider 配置
- `tests/background-logging-status-module.test.js`:测试日志 / 状态模块已接入且导出工厂。
- `tests/background-luckmail.test.js`:测试 LuckMail 相关后台逻辑,如购买、复用、标记已用与重置。
- `tests/background-mail2925-session-module.test.js`:测试 2925 会话模块已接入且导出工厂,并覆盖命中上限后“禁用 24 小时 + 切下一个号 + 自动登录”的核心链路。
@@ -176,7 +176,7 @@
- `tests/icloud-mail-content.test.js`:测试 iCloud Mail 内容脚本读取邮件正文和选中状态逻辑。
- `tests/icloud-utils.test.js`:测试 iCloud 工具层的 host、别名列表、保留状态与筛选逻辑。
- `tests/luckmail-utils.test.js`:测试 LuckMail 工具层的购买记录、邮件、游标和验证码匹配逻辑。
- `tests/mail-provider-utils.test.js`:测试网页邮箱 provider 配置工具对 `126` 等 provider 的归一化与入口配置解析。
- `tests/mail-provider-utils.test.js`:测试网页邮箱 provider 配置工具对 `126` 等 provider 的归一化与入口配置解析,以及 iCloud 转发收码 provider 选项、归一化和配置复用
- `tests/mail-2925-content.test.js`:测试 2925 邮箱内容脚本的轮询快照、忽略邮箱对比、按步骤会话隔离已试验证码、单封邮件删除与整箱删除逻辑。
- `tests/mail2925-utils.test.js`:测试 2925 账号池工具层的账号归一化、冷却期判断、可用账号挑选与批量导入解析。
- `tests/managed-alias-utils.test.js`:覆盖 Gmail / 2925 共享别名工具的解析、生成、兼容性判断。
@@ -189,7 +189,7 @@
- `tests/sidepanel-contribution-mode.test.js`:测试侧边栏贡献模式的 HTML 接线、runtime-only 设置保护,以及贡献模式 manager 复用主自动流启动、状态轮询和退出清理逻辑。
- `tests/sidepanel-auto-run-content-refresh.test.js`:测试点击“自动”时会先刷新贡献内容更新摘要,且刷新失败不会阻塞自动流程启动。
- `tests/sidepanel-icloud-manager.test.js`:测试侧边栏 iCloud 管理器模块接线与空态渲染。
- `tests/sidepanel-icloud-provider.test.js`:测试侧边栏 iCloud 登录地址解析逻辑
- `tests/sidepanel-icloud-provider.test.js`:测试侧边栏 iCloud 登录地址解析、目标邮箱类型 / 转发邮箱 provider 保存、回显和显隐联动
- `tests/sidepanel-luckmail-manager.test.js`:测试侧边栏 LuckMail 管理器模块接线与空态渲染。
- `tests/sidepanel-mail2925-manager.test.js`:测试侧边栏 2925 管理器模块接线、共享号池表单脚本加载顺序、显隐交互与空态渲染。
- `tests/sidepanel-mail2925-mode.test.js`:测试侧边栏保留 `2925 provide / receive` 模式行与独立的号池配置行,并验证 sidepanel 只在 provide 模式下把 2925 视为别名邮箱 provider。