feat: integrate iCloud hide my email generation into OAuth flow

- 合并 PR #72 的核心改动:新增 iCloud Hide My Email 生成、alias 管理与成功后自动标记/删除流程
- 本地补充修复:解决与 Cloudflare Temp Email 分支差异的冲突,并补齐合并后的测试常量
- 影响范围:background 邮箱生成与 Step 9 收尾、sidepanel alias 管理 UI、manifest/rules 与新增 iCloud 测试
This commit is contained in:
Q3CC
2026-04-14 23:16:59 +08:00
parent d5a63f9e55
commit 14e3d6271d
11 changed files with 2007 additions and 11 deletions
+572 -4
View File
@@ -1,6 +1,6 @@
// background.js — Service Worker: orchestration, state, tab management, message routing
importScripts('data/names.js', 'hotmail-utils.js', 'cloudflare-temp-email-utils.js', 'content/activation-utils.js');
importScripts('data/names.js', 'hotmail-utils.js', 'cloudflare-temp-email-utils.js', 'icloud-utils.js', 'content/activation-utils.js');
const {
buildHotmailMailApiLatestUrl,
@@ -28,12 +28,32 @@ const {
normalizeCloudflareTempEmailDomains,
normalizeCloudflareTempEmailMailApiMessages,
} = self.CloudflareTempEmailUtils;
const {
findIcloudAliasByEmail,
getConfiguredIcloudHostPreference,
getIcloudHostHintFromMessage,
getIcloudLoginUrlForHost,
getIcloudSetupUrlForHost,
normalizeBooleanMap,
normalizeIcloudAliasList,
normalizeIcloudHost,
pickReusableIcloudAlias,
toNormalizedEmailSet,
} = self.IcloudUtils;
const {
isRecoverableStep9AuthFailure,
} = self.MultiPageActivationUtils;
const LOG_PREFIX = '[MultiPage:bg]';
const DUCK_AUTOFILL_URL = 'https://duckduckgo.com/email/settings/autofill';
const ICLOUD_SETUP_URLS = [
'https://setup.icloud.com.cn/setup/ws/1',
'https://setup.icloud.com/setup/ws/1',
];
const ICLOUD_LOGIN_URLS = [
'https://www.icloud.com.cn/',
'https://www.icloud.com/',
];
const HOTMAIL_PROVIDER = 'hotmail-api';
const CLOUDFLARE_TEMP_EMAIL_PROVIDER = 'cloudflare-temp-email';
const CLOUDFLARE_TEMP_EMAIL_GENERATOR = 'cloudflare-temp-email';
@@ -62,6 +82,7 @@ const DEFAULT_HOTMAIL_REMOTE_BASE_URL = '';
const DEFAULT_HOTMAIL_LOCAL_BASE_URL = 'http://127.0.0.1:17373';
const HOTMAIL_LOCAL_HELPER_TIMEOUT_MS = 45000;
const DISPLAY_TIMEZONE = 'Asia/Shanghai';
const PERSISTENT_ALIAS_STATE_KEYS = ['manualAliasUsage', 'preservedAliases'];
initializeSessionStorageAccess();
@@ -86,6 +107,8 @@ const PERSISTED_SETTING_DEFAULTS = {
autoStepDelaySeconds: null,
mailProvider: '163',
emailGenerator: 'duck',
autoDeleteUsedIcloudAlias: false,
icloudHostPreference: 'auto',
emailPrefix: '',
inbucketHost: '',
inbucketMailbox: '',
@@ -116,6 +139,8 @@ const DEFAULT_STATE = {
email: null, // 运行时邮箱,由程序自动获取并写入,不能手动预填。
password: null, // 运行时实际密码,由 customPassword 或程序自动生成后写入。
accounts: [], // 已生成账号记录:{ email, password, createdAt }。
manualAliasUsage: {},
preservedAliases: {},
lastEmailTimestamp: null, // 最近一次获取到邮箱数据的运行时时间戳。
lastSignupCode: null, // 注册验证码,运行时由程序自动读取并写入。
lastLoginCode: null, // 登录验证码,运行时由程序自动读取并写入。
@@ -143,6 +168,7 @@ const DEFAULT_STATE = {
signupVerificationRequestedAt: null,
loginVerificationRequestedAt: null,
currentHotmailAccountId: null,
preferredIcloudHost: '',
};
function normalizeAutoRunDelayMinutes(value) {
@@ -236,6 +262,9 @@ function normalizeEmailGenerator(value = '') {
if (normalized === 'custom' || normalized === 'manual') {
return 'custom';
}
if (normalized === 'icloud') {
return 'icloud';
}
if (normalized === 'cloudflare') return 'cloudflare';
if (normalized === CLOUDFLARE_TEMP_EMAIL_GENERATOR) return CLOUDFLARE_TEMP_EMAIL_GENERATOR;
return 'duck';
@@ -391,6 +420,10 @@ function normalizePersistentSettingValue(key, value) {
return normalizeMailProvider(value);
case 'emailGenerator':
return normalizeEmailGenerator(value);
case 'autoDeleteUsedIcloudAlias':
return Boolean(value);
case 'icloudHostPreference':
return normalizeIcloudHost(value) || 'auto';
case 'emailPrefix':
return String(value || '').trim();
case 'inbucketHost':
@@ -475,12 +508,29 @@ async function getPersistedSettings() {
return buildPersistentSettingsPayload(stored, { fillDefaults: true });
}
async function getPersistedAliasState() {
try {
const stored = await chrome.storage.local.get(PERSISTENT_ALIAS_STATE_KEYS);
return {
manualAliasUsage: normalizeBooleanMap(stored.manualAliasUsage),
preservedAliases: normalizeBooleanMap(stored.preservedAliases),
};
} catch (err) {
console.warn(LOG_PREFIX, 'Failed to read persisted iCloud alias state:', err?.message || err);
return {
manualAliasUsage: {},
preservedAliases: {},
};
}
}
async function getState() {
const [state, persistedSettings] = await Promise.all([
const [state, persistedSettings, persistedAliasState] = await Promise.all([
chrome.storage.session.get(null),
getPersistedSettings(),
getPersistedAliasState(),
]);
return { ...DEFAULT_STATE, ...persistedSettings, ...state };
return { ...DEFAULT_STATE, ...persistedSettings, ...persistedAliasState, ...state };
}
async function initializeSessionStorageAccess() {
@@ -500,6 +550,16 @@ async function setState(updates) {
console.log(LOG_PREFIX, 'storage.set:', JSON.stringify(updates).slice(0, 200));
if (Object.keys(updates || {}).length > 0) {
await chrome.storage.session.set(updates);
const persistentAliasUpdates = {};
if (Object.prototype.hasOwnProperty.call(updates, 'manualAliasUsage')) {
persistentAliasUpdates.manualAliasUsage = normalizeBooleanMap(updates.manualAliasUsage);
}
if (Object.prototype.hasOwnProperty.call(updates, 'preservedAliases')) {
persistentAliasUpdates.preservedAliases = normalizeBooleanMap(updates.preservedAliases);
}
if (Object.keys(persistentAliasUpdates).length > 0) {
await chrome.storage.local.set(persistentAliasUpdates);
}
}
}
@@ -578,6 +638,13 @@ function broadcastDataUpdate(payload) {
}).catch(() => { });
}
function broadcastIcloudAliasesChanged(payload = {}) {
chrome.runtime.sendMessage({
type: 'ICLOUD_ALIASES_CHANGED',
payload,
}).catch(() => { });
}
async function setEmailStateSilently(email) {
await setState({ email });
broadcastDataUpdate({ email });
@@ -595,28 +662,84 @@ async function setPasswordState(password) {
broadcastDataUpdate({ password });
}
function getManualAliasUsageMap(state) {
return normalizeBooleanMap(state?.manualAliasUsage);
}
function getPreservedAliasMap(state) {
return normalizeBooleanMap(state?.preservedAliases);
}
function isAliasPreserved(state, email) {
const normalizedEmail = String(email || '').trim().toLowerCase();
if (!normalizedEmail) return false;
return Boolean(getPreservedAliasMap(state)[normalizedEmail]);
}
function getEffectiveUsedEmails(state) {
return toNormalizedEmailSet(getManualAliasUsageMap(state));
}
async function setIcloudAliasUsedState(payload = {}, options = {}) {
const email = String(payload.email || '').trim().toLowerCase();
if (!email) {
throw new Error('未提供 iCloud 隐私邮箱地址。');
}
const used = Boolean(payload.used);
const state = await getState();
const manualAliasUsage = getManualAliasUsageMap(state);
manualAliasUsage[email] = used;
await setState({ manualAliasUsage });
if (!options.silentLog) {
await addLog(`iCloud:已将 ${email} 标记为${used ? '已用' : '未用'}`, 'ok');
}
broadcastIcloudAliasesChanged({ reason: 'used-updated', email, used });
return { email, used };
}
async function setIcloudAliasPreservedState(payload = {}) {
const email = String(payload.email || '').trim().toLowerCase();
if (!email) {
throw new Error('未提供 iCloud 隐私邮箱地址。');
}
const preserved = Boolean(payload.preserved);
const state = await getState();
const preservedAliases = getPreservedAliasMap(state);
preservedAliases[email] = preserved;
await setState({ preservedAliases });
await addLog(`iCloud:已将 ${email} ${preserved ? '设为保留' : '取消保留'}`, 'ok');
broadcastIcloudAliasesChanged({ reason: 'preserved-updated', email, preserved });
return { email, preserved };
}
async function resetState() {
console.log(LOG_PREFIX, 'Resetting all state');
// Preserve settings and persistent data across resets
const [prev, persistedSettings] = await Promise.all([
const [prev, persistedSettings, persistedAliasState] = await Promise.all([
chrome.storage.session.get([
'seenCodes',
'seenInbucketMailIds',
'accounts',
'tabRegistry',
'sourceLastUrls',
'preferredIcloudHost',
]),
getPersistedSettings(),
getPersistedAliasState(),
]);
await chrome.storage.session.clear();
await chrome.storage.session.set({
...DEFAULT_STATE,
...persistedSettings,
...persistedAliasState,
seenCodes: prev.seenCodes || [],
seenInbucketMailIds: prev.seenInbucketMailIds || [],
accounts: prev.accounts || [],
tabRegistry: prev.tabRegistry || {},
sourceLastUrls: prev.sourceLastUrls || {},
preferredIcloudHost: prev.preferredIcloudHost || '',
});
}
@@ -1460,6 +1583,408 @@ async function pollCloudflareTempEmailVerificationCode(step, state, pollPayload
throw lastError || new Error(`步骤 ${step}:未在 Cloudflare Temp Email 中找到新的匹配验证码。`);
}
async function getOpenIcloudHostPreference() {
try {
const tabs = await chrome.tabs.query({
url: [
'https://www.icloud.com/*',
'https://www.icloud.com.cn/*',
],
});
const activeTab = tabs.find((tab) => tab.active);
const candidates = activeTab ? [activeTab, ...tabs.filter((tab) => tab.id !== activeTab.id)] : tabs;
for (const tab of candidates) {
try {
const host = normalizeIcloudHost(new URL(tab.url).host);
if (host) return host;
} catch {}
}
} catch {}
return '';
}
async function getPreferredIcloudLoginUrl(error = null, state = null) {
const currentState = state || await getState();
const configuredHost = getConfiguredIcloudHostPreference(currentState);
if (configuredHost) {
return getIcloudLoginUrlForHost(configuredHost);
}
const messageHint = getIcloudHostHintFromMessage(getErrorMessage(error));
if (messageHint) {
return getIcloudLoginUrlForHost(messageHint);
}
const savedHost = normalizeIcloudHost(currentState?.preferredIcloudHost);
if (savedHost) {
return getIcloudLoginUrlForHost(savedHost);
}
const openHost = await getOpenIcloudHostPreference();
if (openHost) {
return getIcloudLoginUrlForHost(openHost);
}
return ICLOUD_LOGIN_URLS[0];
}
async function getPreferredIcloudSetupUrls(state = null, error = null) {
const preferredLoginUrl = await getPreferredIcloudLoginUrl(error, state);
const preferredHost = normalizeIcloudHost(new URL(preferredLoginUrl).host);
const preferredSetupUrl = getIcloudSetupUrlForHost(preferredHost);
if (!preferredSetupUrl) {
return [...ICLOUD_SETUP_URLS];
}
return [
preferredSetupUrl,
...ICLOUD_SETUP_URLS.filter((url) => url !== preferredSetupUrl),
];
}
function isIcloudLoginRequiredError(error) {
const message = getErrorMessage(error).toLowerCase();
return message.includes('could not validate icloud session')
|| message.includes('hide my email service was unavailable')
|| /\bstatus (401|403|409|421)\b/.test(message);
}
let lastIcloudLoginPromptAt = 0;
async function openIcloudLoginPage(preferredUrl) {
const tabs = await chrome.tabs.query({
url: [
'https://www.icloud.com/*',
'https://www.icloud.com.cn/*',
],
});
const preferredHost = new URL(preferredUrl).host;
const existing = tabs.find((tab) => {
try {
return new URL(tab.url).host === preferredHost;
} catch {
return false;
}
});
if (existing?.id) {
await chrome.tabs.update(existing.id, { active: true });
if (existing.url !== preferredUrl) {
await chrome.tabs.update(existing.id, { url: preferredUrl });
}
return existing.id;
}
const created = await chrome.tabs.create({ url: preferredUrl, active: true });
return created.id;
}
async function promptIcloudLogin(error, actionLabel = 'iCloud 操作') {
const now = Date.now();
const preferredUrl = await getPreferredIcloudLoginUrl(error);
const originalError = getErrorMessage(error);
chrome.runtime.sendMessage({
type: 'ICLOUD_LOGIN_REQUIRED',
payload: {
actionLabel,
loginUrl: preferredUrl,
message: '需要先登录 iCloud,我已经为你打开登录页。',
detail: originalError,
},
}).catch(() => { });
if (now - lastIcloudLoginPromptAt < 15000) {
return;
}
lastIcloudLoginPromptAt = now;
await addLog(`iCloud${actionLabel}时需要登录,正在打开 ${new URL(preferredUrl).host} ...`, 'warn');
try {
await openIcloudLoginPage(preferredUrl);
} catch (tabErr) {
await addLog(`iCloud:自动打开登录页失败:${getErrorMessage(tabErr)}`, 'warn');
}
}
async function withIcloudLoginHelp(actionLabel, action) {
try {
return await action();
} catch (err) {
if (isIcloudLoginRequiredError(err)) {
await promptIcloudLogin(err, actionLabel);
throw new Error('请先在新打开的 iCloud 页面中完成登录,再回来点击“我已登录”。');
}
throw err;
}
}
async function icloudRequest(method, url, options = {}) {
const { data } = options;
let response;
try {
response = await fetch(url, {
method,
credentials: 'include',
headers: data !== undefined ? { 'Content-Type': 'application/json' } : undefined,
body: data !== undefined ? JSON.stringify(data) : undefined,
});
} catch (err) {
throw new Error(`iCloud 请求失败:${method} ${url}${err.message}`);
}
if (!response.ok) {
throw new Error(`iCloud 请求失败:${method} ${url}status ${response.status}`);
}
try {
return await response.json();
} catch (err) {
throw new Error(`iCloud 返回的 JSON 无法解析:${method} ${url}${err.message}`);
}
}
async function validateIcloudSession(setupUrl) {
const data = await icloudRequest('POST', `${setupUrl}/validate`);
if (!data?.webservices?.premiummailsettings?.url) {
throw new Error('Could not validate iCloud session. Hide My Email service was unavailable.');
}
return data;
}
async function resolveIcloudPremiumMailService() {
const errors = [];
const state = await getState();
const setupUrls = await getPreferredIcloudSetupUrls(state);
for (const setupUrl of setupUrls) {
try {
const data = await validateIcloudSession(setupUrl);
const preferredIcloudHost = normalizeIcloudHost(new URL(setupUrl).host);
if (preferredIcloudHost && preferredIcloudHost !== normalizeIcloudHost(state.preferredIcloudHost)) {
await setState({ preferredIcloudHost });
}
return {
setupUrl,
serviceUrl: String(data.webservices.premiummailsettings.url || '').replace(/\/$/, ''),
};
} catch (err) {
errors.push(`${new URL(setupUrl).host}: ${getErrorMessage(err)}`);
}
}
throw new Error(errors.length
? `Could not validate iCloud session. ${errors.join(' | ')}`
: 'Could not validate iCloud session. 请先在当前浏览器登录 icloud.com.cn 或 icloud.com。');
}
function getIcloudAliasLabel() {
const now = new Date();
const dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
return `MultiPage ${dateStr}`;
}
async function checkIcloudSession() {
return withIcloudLoginHelp('检查 iCloud 会话', async () => {
const { setupUrl } = await resolveIcloudPremiumMailService();
await addLog(`iCloud:会话校验通过(${new URL(setupUrl).host}`, 'ok');
return { ok: true, setupUrl };
});
}
async function listIcloudAliases() {
return withIcloudLoginHelp('加载 iCloud 隐私邮箱列表', async () => {
const { serviceUrl } = await resolveIcloudPremiumMailService();
const response = await icloudRequest('GET', `${serviceUrl}/v2/hme/list`);
const state = await getState();
return normalizeIcloudAliasList(response, {
usedEmails: getEffectiveUsedEmails(state),
preservedEmails: getPreservedAliasMap(state),
});
});
}
async function deleteIcloudAlias(payload) {
return withIcloudLoginHelp('删除 iCloud 隐私邮箱', async () => {
const alias = typeof payload === 'string'
? { email: String(payload).trim().toLowerCase(), anonymousId: '' }
: {
email: String(payload?.email || '').trim().toLowerCase(),
anonymousId: String(payload?.anonymousId || '').trim(),
};
if (!alias.email) {
throw new Error('未提供需要删除的 iCloud 隐私邮箱。');
}
if (!alias.anonymousId) {
throw new Error(`缺少 ${alias.email} 的 anonymousId,请先刷新 iCloud 别名列表。`);
}
const { serviceUrl } = await resolveIcloudPremiumMailService();
try {
const directDelete = await icloudRequest('POST', `${serviceUrl}/v1/hme/delete`, {
data: { anonymousId: alias.anonymousId },
});
if (directDelete?.success === false) {
throw new Error(directDelete?.error?.errorMessage || 'delete failed');
}
} catch (err) {
await addLog(`iCloud:直接删除 ${alias.email} 失败,尝试先停用再删除...`, 'warn');
const deactivated = await icloudRequest('POST', `${serviceUrl}/v1/hme/deactivate`, {
data: { anonymousId: alias.anonymousId },
});
if (deactivated?.success === false) {
throw new Error(deactivated?.error?.errorMessage || `停用 ${alias.email} 失败`);
}
const deleted = await icloudRequest('POST', `${serviceUrl}/v1/hme/delete`, {
data: { anonymousId: alias.anonymousId },
});
if (deleted?.success === false) {
throw new Error(deleted?.error?.errorMessage || `删除 ${alias.email} 失败`);
}
}
const state = await getState();
const manualAliasUsage = getManualAliasUsageMap(state);
const preservedAliases = getPreservedAliasMap(state);
delete manualAliasUsage[alias.email];
delete preservedAliases[alias.email];
await setState({ manualAliasUsage, preservedAliases });
await addLog(`iCloud:已删除 ${alias.email}`, 'ok');
broadcastIcloudAliasesChanged({ reason: 'deleted', email: alias.email });
return { email: alias.email };
});
}
async function deleteUsedIcloudAliases() {
const aliases = await listIcloudAliases();
const usedAliases = aliases.filter((alias) => alias.used);
if (!usedAliases.length) {
return { deleted: [], skipped: [] };
}
const deleted = [];
const skipped = [];
for (const alias of usedAliases) {
if (alias.preserved) {
skipped.push({ email: alias.email, error: 'preserved' });
continue;
}
try {
await deleteIcloudAlias(alias);
deleted.push(alias.email);
} catch (err) {
skipped.push({ email: alias.email, error: getErrorMessage(err) });
}
}
return { deleted, skipped };
}
async function fetchIcloudHideMyEmail() {
return withIcloudLoginHelp('获取 iCloud 隐私邮箱', async () => {
throwIfStopped();
await addLog('iCloud:正在校验当前浏览器登录状态...', 'info');
const { serviceUrl, setupUrl } = await resolveIcloudPremiumMailService();
await addLog(`iCloud:已通过 ${new URL(setupUrl).host} 验证会话`, 'ok');
const existingAliasesResponse = await icloudRequest('GET', `${serviceUrl}/v2/hme/list`);
const state = await getState();
const existingAliases = normalizeIcloudAliasList(existingAliasesResponse, {
usedEmails: getEffectiveUsedEmails(state),
preservedEmails: getPreservedAliasMap(state),
});
const reusableAlias = pickReusableIcloudAlias(existingAliases);
if (reusableAlias) {
await setEmailState(reusableAlias.email);
await addLog(`iCloud:复用未使用别名 ${reusableAlias.email}`, 'ok');
broadcastIcloudAliasesChanged({ reason: 'selected', email: reusableAlias.email });
return reusableAlias.email;
}
await addLog('iCloud:没有可复用别名,开始生成新的 Hide My Email 地址...', 'warn');
const generated = await icloudRequest('POST', `${serviceUrl}/v1/hme/generate`);
if (!generated?.success || !generated?.result?.hme) {
throw new Error(generated?.error?.errorMessage || 'iCloud 隐私邮箱生成失败。');
}
const reserved = await icloudRequest('POST', `${serviceUrl}/v1/hme/reserve`, {
data: {
hme: generated.result.hme,
label: getIcloudAliasLabel(),
note: 'Generated through Multi-Page Automation',
},
});
if (!reserved?.success || !reserved?.result?.hme?.hme) {
throw new Error(reserved?.error?.errorMessage || 'iCloud 隐私邮箱保留失败。');
}
const alias = String(reserved.result.hme.hme || '').trim().toLowerCase();
await setEmailState(alias);
await addLog(`iCloud:已创建并保留新别名 ${alias}`, 'ok');
broadcastIcloudAliasesChanged({ reason: 'created', email: alias });
return alias;
});
}
async function finalizeIcloudAliasAfterSuccessfulFlow(state) {
const email = String(state?.email || '').trim().toLowerCase();
if (!email) {
return { handled: false, deleted: false };
}
const knownIcloudAlias = normalizeEmailGenerator(state?.emailGenerator) === 'icloud'
|| Object.prototype.hasOwnProperty.call(getManualAliasUsageMap(state), email)
|| Object.prototype.hasOwnProperty.call(getPreservedAliasMap(state), email);
if (!knownIcloudAlias) {
return { handled: false, deleted: false };
}
await setIcloudAliasUsedState({ email, used: true }, { silentLog: true });
await addLog(`iCloud:流程成功后已标记 ${email} 为已用。`, 'ok');
if (!state.autoDeleteUsedIcloudAlias) {
return { handled: true, deleted: false };
}
if (isAliasPreserved(state, email)) {
await addLog(`iCloud${email} 已被标记为保留,跳过自动删除。`, 'info');
return { handled: true, deleted: false };
}
try {
const aliases = await listIcloudAliases();
const alias = findIcloudAliasByEmail(aliases, email);
if (!alias) {
await addLog(`iCloud:自动删除跳过,列表中未找到 ${email}`, 'warn');
return { handled: true, deleted: false };
}
if (alias.preserved) {
await addLog(`iCloud${email} 在最新别名列表中已是保留状态,跳过自动删除。`, 'info');
return { handled: true, deleted: false };
}
if (!alias.anonymousId) {
await addLog(`iCloud:自动删除跳过,${email} 缺少 anonymousId,请先刷新列表后重试。`, 'warn');
return { handled: true, deleted: false };
}
await deleteIcloudAlias(alias);
await addLog(`iCloud:流程成功后已自动删除 ${email}`, 'ok');
return { handled: true, deleted: true };
} catch (err) {
await addLog(`iCloud:自动删除 ${email} 失败:${getErrorMessage(err)}`, 'warn');
return { handled: true, deleted: false };
}
}
// ============================================================
// Tab Registry
// ============================================================
@@ -1699,6 +2224,7 @@ async function closeTabsByUrlPrefix(prefix, options = {}) {
.filter((tab) => typeof tab.url === 'string' && !excludedUrls.has(tab.url))
.filter((tab) => !(excludeLocalhostCallbacks && isLocalhostOAuthCallbackUrl(tab.url)))
.filter((tab) => typeof tab.url === 'string' && tab.url.startsWith(prefix))
.filter((tab) => !isLocalhostOAuthCallbackUrl(tab.url))
.map((tab) => tab.id);
if (!matchedIds.length) return 0;
@@ -3222,6 +3748,41 @@ async function handleMessage(message, sender) {
return { ok: true, email };
}
case 'CHECK_ICLOUD_SESSION': {
clearStopRequest();
return await checkIcloudSession();
}
case 'LIST_ICLOUD_ALIASES': {
clearStopRequest();
const aliases = await listIcloudAliases();
return { ok: true, aliases };
}
case 'SET_ICLOUD_ALIAS_USED_STATE': {
clearStopRequest();
const result = await setIcloudAliasUsedState(message.payload || {});
return { ok: true, ...result };
}
case 'SET_ICLOUD_ALIAS_PRESERVED_STATE': {
clearStopRequest();
const result = await setIcloudAliasPreservedState(message.payload || {});
return { ok: true, ...result };
}
case 'DELETE_ICLOUD_ALIAS': {
clearStopRequest();
const result = await deleteIcloudAlias(message.payload || {});
return { ok: true, ...result };
}
case 'DELETE_USED_ICLOUD_ALIASES': {
clearStopRequest();
const result = await deleteUsedIcloudAliases();
return { ok: true, ...result };
}
case 'STOP_FLOW': {
await requestStop();
return { ok: true };
@@ -3308,6 +3869,7 @@ async function handleStepData(step, payload) {
excludeLocalhostCallbacks: true,
});
}
await finalizeIcloudAliasAfterSuccessfulFlow(latestState);
if (shouldUseCustomRegistrationEmail(latestState) && latestState.email) {
await setEmailStateSilently(null);
}
@@ -3599,6 +4161,9 @@ function getEmailGeneratorLabel(generator) {
if (generator === 'custom') {
return '自定义邮箱';
}
if (generator === 'icloud') {
return 'iCloud 隐私邮箱';
}
if (generator === 'cloudflare') return 'Cloudflare 邮箱';
if (generator === CLOUDFLARE_TEMP_EMAIL_GENERATOR) return 'Cloudflare Temp Email';
return 'Duck 邮箱';
@@ -3773,6 +4338,9 @@ async function fetchGeneratedEmail(state, options = {}) {
if (generator === 'custom') {
throw new Error('当前邮箱生成方式为自定义邮箱,请直接填写注册邮箱。');
}
if (generator === 'icloud') {
return fetchIcloudHideMyEmail();
}
if (generator === 'cloudflare') {
return fetchCloudflareEmail(currentState, options);
}