feat: add custom email pool mail compatibility
This commit is contained in:
+121
-1
@@ -139,10 +139,12 @@ const ICLOUD_LOGIN_URLS = [
|
||||
];
|
||||
const ICLOUD_PROVIDER = 'icloud';
|
||||
const GMAIL_PROVIDER = 'gmail';
|
||||
const GMAIL_ALIAS_GENERATOR = 'gmail-alias';
|
||||
const HOTMAIL_PROVIDER = 'hotmail-api';
|
||||
const LUCKMAIL_PROVIDER = 'luckmail-api';
|
||||
const CLOUDFLARE_TEMP_EMAIL_PROVIDER = 'cloudflare-temp-email';
|
||||
const CLOUDFLARE_TEMP_EMAIL_GENERATOR = 'cloudflare-temp-email';
|
||||
const CUSTOM_EMAIL_POOL_GENERATOR = 'custom-pool';
|
||||
const HOTMAIL_MAILBOXES = ['INBOX', 'Junk'];
|
||||
const STOP_ERROR_MESSAGE = '流程已被用户停止。';
|
||||
const CLOUDFLARE_SECURITY_BLOCK_ERROR_PREFIX = 'CF_SECURITY_BLOCKED::';
|
||||
@@ -263,6 +265,7 @@ const PERSISTED_SETTING_DEFAULTS = {
|
||||
mail2925Mode: DEFAULT_MAIL_2925_MODE,
|
||||
mail2925UseAccountPool: false,
|
||||
emailGenerator: 'duck',
|
||||
customEmailPool: [],
|
||||
autoDeleteUsedIcloudAlias: false,
|
||||
icloudHostPreference: 'auto',
|
||||
accountRunHistoryTextEnabled: false,
|
||||
@@ -640,9 +643,21 @@ function getAutoRunTimerStatusPayload(plan) {
|
||||
|
||||
function normalizeEmailGenerator(value = '') {
|
||||
const normalized = String(value || '').trim().toLowerCase();
|
||||
const customEmailPoolGenerator = typeof CUSTOM_EMAIL_POOL_GENERATOR === 'string'
|
||||
? CUSTOM_EMAIL_POOL_GENERATOR
|
||||
: 'custom-pool';
|
||||
const gmailAliasGenerator = typeof GMAIL_ALIAS_GENERATOR === 'string'
|
||||
? GMAIL_ALIAS_GENERATOR
|
||||
: 'gmail-alias';
|
||||
if (normalized === 'custom' || normalized === 'manual') {
|
||||
return 'custom';
|
||||
}
|
||||
if (normalized === gmailAliasGenerator) {
|
||||
return gmailAliasGenerator;
|
||||
}
|
||||
if (normalized === customEmailPoolGenerator) {
|
||||
return customEmailPoolGenerator;
|
||||
}
|
||||
if (normalized === 'icloud') {
|
||||
return 'icloud';
|
||||
}
|
||||
@@ -651,6 +666,36 @@ function normalizeEmailGenerator(value = '') {
|
||||
return 'duck';
|
||||
}
|
||||
|
||||
function normalizeCustomEmailPool(value = []) {
|
||||
const source = Array.isArray(value)
|
||||
? value
|
||||
: String(value || '').split(/[\r\n,,;;]+/);
|
||||
|
||||
return source
|
||||
.map((item) => String(item || '').trim().toLowerCase())
|
||||
.filter((item) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(item));
|
||||
}
|
||||
|
||||
function isCustomEmailPoolGenerator(stateOrValue = {}) {
|
||||
const generator = typeof stateOrValue === 'string'
|
||||
? stateOrValue
|
||||
: stateOrValue?.emailGenerator;
|
||||
const customEmailPoolGenerator = typeof CUSTOM_EMAIL_POOL_GENERATOR === 'string'
|
||||
? CUSTOM_EMAIL_POOL_GENERATOR
|
||||
: 'custom-pool';
|
||||
return normalizeEmailGenerator(generator) === customEmailPoolGenerator;
|
||||
}
|
||||
|
||||
function getCustomEmailPool(state = {}) {
|
||||
return normalizeCustomEmailPool(state?.customEmailPool);
|
||||
}
|
||||
|
||||
function getCustomEmailPoolEmailForRun(state = {}, targetRun = 1) {
|
||||
const entries = getCustomEmailPool(state);
|
||||
const numericRun = Math.max(1, Math.floor(Number(targetRun) || 1));
|
||||
return entries[numericRun - 1] || '';
|
||||
}
|
||||
|
||||
function normalizePanelMode(value = '') {
|
||||
return String(value || '').trim().toLowerCase() === 'sub2api' ? 'sub2api' : 'cpa';
|
||||
}
|
||||
@@ -894,6 +939,8 @@ function normalizePersistentSettingValue(key, value) {
|
||||
return Boolean(value);
|
||||
case 'emailGenerator':
|
||||
return normalizeEmailGenerator(value);
|
||||
case 'customEmailPool':
|
||||
return normalizeCustomEmailPool(value);
|
||||
case 'autoDeleteUsedIcloudAlias':
|
||||
case 'accountRunHistoryTextEnabled':
|
||||
return Boolean(value);
|
||||
@@ -2130,6 +2177,18 @@ function parseGmailBaseEmail(rawValue) {
|
||||
}
|
||||
|
||||
function isGeneratedAliasProvider(stateOrProvider, mail2925Mode = undefined) {
|
||||
if (
|
||||
stateOrProvider
|
||||
&& typeof stateOrProvider === 'object'
|
||||
&& !Array.isArray(stateOrProvider)
|
||||
&& normalizeEmailGenerator(stateOrProvider.emailGenerator) === (
|
||||
typeof CUSTOM_EMAIL_POOL_GENERATOR === 'string'
|
||||
? CUSTOM_EMAIL_POOL_GENERATOR
|
||||
: 'custom-pool'
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
const provider = typeof stateOrProvider === 'string'
|
||||
? stateOrProvider
|
||||
: stateOrProvider?.mailProvider;
|
||||
@@ -2287,6 +2346,18 @@ function getManagedAliasBaseEmail(state = {}, provider = state?.mailProvider) {
|
||||
}
|
||||
|
||||
function isGeneratedAliasProvider(stateOrProvider, mail2925Mode = undefined) {
|
||||
if (
|
||||
stateOrProvider
|
||||
&& typeof stateOrProvider === 'object'
|
||||
&& !Array.isArray(stateOrProvider)
|
||||
&& normalizeEmailGenerator(stateOrProvider.emailGenerator) === (
|
||||
typeof CUSTOM_EMAIL_POOL_GENERATOR === 'string'
|
||||
? CUSTOM_EMAIL_POOL_GENERATOR
|
||||
: 'custom-pool'
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
const provider = typeof stateOrProvider === 'string'
|
||||
? stateOrProvider
|
||||
: stateOrProvider?.mailProvider;
|
||||
@@ -4999,7 +5070,12 @@ async function handleStepData(step, payload) {
|
||||
});
|
||||
}
|
||||
await finalizeIcloudAliasAfterSuccessfulFlow(latestState);
|
||||
if (shouldUseCustomRegistrationEmail(latestState) && latestState.email) {
|
||||
const shouldClearCustomPoolEmail = String(latestState?.emailGenerator || '').trim().toLowerCase() === (
|
||||
typeof CUSTOM_EMAIL_POOL_GENERATOR === 'string'
|
||||
? CUSTOM_EMAIL_POOL_GENERATOR
|
||||
: 'custom-pool'
|
||||
);
|
||||
if ((shouldUseCustomRegistrationEmail(latestState) || shouldClearCustomPoolEmail) && latestState.email) {
|
||||
await setEmailStateSilently(null);
|
||||
}
|
||||
break;
|
||||
@@ -5413,9 +5489,21 @@ async function executeStepAndWait(step, delayAfter = 2000) {
|
||||
}
|
||||
|
||||
function getEmailGeneratorLabel(generator) {
|
||||
const customEmailPoolGenerator = typeof CUSTOM_EMAIL_POOL_GENERATOR === 'string'
|
||||
? CUSTOM_EMAIL_POOL_GENERATOR
|
||||
: 'custom-pool';
|
||||
const gmailAliasGenerator = typeof GMAIL_ALIAS_GENERATOR === 'string'
|
||||
? GMAIL_ALIAS_GENERATOR
|
||||
: 'gmail-alias';
|
||||
if (generator === 'custom') {
|
||||
return '自定义邮箱';
|
||||
}
|
||||
if (generator === gmailAliasGenerator) {
|
||||
return 'Gmail +tag 邮箱';
|
||||
}
|
||||
if (generator === customEmailPoolGenerator) {
|
||||
return '自定义邮箱池';
|
||||
}
|
||||
if (generator === 'icloud') {
|
||||
return 'iCloud 隐私邮箱';
|
||||
}
|
||||
@@ -5515,11 +5603,13 @@ const generatedEmailHelpers = self.MultiPageGeneratedEmailHelpers?.createGenerat
|
||||
buildGeneratedAliasEmail,
|
||||
buildCloudflareTempEmailHeaders,
|
||||
CLOUDFLARE_TEMP_EMAIL_GENERATOR,
|
||||
CUSTOM_EMAIL_POOL_GENERATOR,
|
||||
DUCK_AUTOFILL_URL,
|
||||
fetch,
|
||||
fetchIcloudHideMyEmail,
|
||||
getCloudflareTempEmailAddressFromResponse,
|
||||
getCloudflareTempEmailConfig,
|
||||
getCustomEmailPoolEmail: getCustomEmailPoolEmailForRun,
|
||||
getState,
|
||||
ensureMail2925AccountForFlow,
|
||||
joinCloudflareTempEmailUrl,
|
||||
@@ -5762,6 +5852,21 @@ async function ensureAutoEmailReady(targetRun, totalRuns, attemptRuns) {
|
||||
return currentState.email;
|
||||
}
|
||||
|
||||
if (isCustomEmailPoolGenerator(currentState)) {
|
||||
const queuedEmail = getCustomEmailPoolEmailForRun(currentState, targetRun);
|
||||
if (!queuedEmail) {
|
||||
const poolSize = getCustomEmailPool(currentState).length;
|
||||
throw new Error(
|
||||
poolSize > 0
|
||||
? `自定义邮箱池第 ${targetRun} 个邮箱不存在,请检查邮箱池数量是否与自动轮数一致。`
|
||||
: '自定义邮箱池为空,请先至少填写 1 个邮箱。'
|
||||
);
|
||||
}
|
||||
await setEmailState(queuedEmail);
|
||||
await addLog(`=== 目标 ${targetRun}/${totalRuns} 轮:自定义邮箱池已就绪:${queuedEmail}(第 ${attemptRuns} 次尝试)===`, 'ok');
|
||||
return queuedEmail;
|
||||
}
|
||||
|
||||
if (shouldUseCustomRegistrationEmail(currentState)) {
|
||||
await addLog(`=== 目标 ${targetRun}/${totalRuns} 轮已暂停:请先填写自定义注册邮箱,然后继续 ===`, 'warn');
|
||||
await broadcastAutoRunStatus('waiting_email', {
|
||||
@@ -5880,6 +5985,21 @@ async function ensureAutoEmailReady(targetRun, totalRuns, attemptRuns) {
|
||||
return currentState.email;
|
||||
}
|
||||
|
||||
if (isCustomEmailPoolGenerator(currentState)) {
|
||||
const queuedEmail = getCustomEmailPoolEmailForRun(currentState, targetRun);
|
||||
if (!queuedEmail) {
|
||||
const poolSize = getCustomEmailPool(currentState).length;
|
||||
throw new Error(
|
||||
poolSize > 0
|
||||
? `自定义邮箱池第 ${targetRun} 个邮箱不存在,请检查邮箱池数量是否与自动轮数一致。`
|
||||
: '自定义邮箱池为空,请先至少填写 1 个邮箱。'
|
||||
);
|
||||
}
|
||||
await setEmailState(queuedEmail);
|
||||
await addLog(`=== 目标 ${targetRun}/${totalRuns} 轮:自定义邮箱池已就绪:${queuedEmail}(第 ${attemptRuns} 次尝试)===`, 'ok');
|
||||
return queuedEmail;
|
||||
}
|
||||
|
||||
if (shouldUseCustomRegistrationEmail(currentState)) {
|
||||
await addLog(`=== 目标 ${targetRun}/${totalRuns} 轮已暂停:请先填写自定义注册邮箱,然后继续 ===`, 'warn');
|
||||
await broadcastAutoRunStatus('waiting_email', {
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
buildGeneratedAliasEmail,
|
||||
buildCloudflareTempEmailHeaders,
|
||||
CLOUDFLARE_TEMP_EMAIL_GENERATOR,
|
||||
CUSTOM_EMAIL_POOL_GENERATOR,
|
||||
DUCK_AUTOFILL_URL,
|
||||
fetch,
|
||||
fetchIcloudHideMyEmail,
|
||||
getCloudflareTempEmailAddressFromResponse,
|
||||
getCloudflareTempEmailConfig,
|
||||
getCustomEmailPoolEmail,
|
||||
getState,
|
||||
ensureMail2925AccountForFlow,
|
||||
joinCloudflareTempEmailUrl,
|
||||
@@ -188,6 +190,24 @@
|
||||
return result.email;
|
||||
}
|
||||
|
||||
async function fetchCustomEmailPoolEmail(state, options = {}) {
|
||||
throwIfStopped();
|
||||
const latestState = state || await getState();
|
||||
const requestedIndex = Math.max(0, Math.floor(Number(options.poolIndex) || 0));
|
||||
const email = String(getCustomEmailPoolEmail?.(latestState, requestedIndex + 1) || '').trim().toLowerCase();
|
||||
if (!email) {
|
||||
throw new Error(
|
||||
requestedIndex > 0
|
||||
? `自定义邮箱池第 ${requestedIndex + 1} 个邮箱不存在,请检查邮箱池配置。`
|
||||
: '自定义邮箱池为空,请先至少填写 1 个邮箱。'
|
||||
);
|
||||
}
|
||||
|
||||
await setEmailState(email);
|
||||
await addLog(`自定义邮箱池:已取用 ${email}`, 'ok');
|
||||
return email;
|
||||
}
|
||||
|
||||
async function fetchManagedAliasEmail(state, options = {}) {
|
||||
throwIfStopped();
|
||||
const provider = String(options.mailProvider || state?.mailProvider || '').trim().toLowerCase();
|
||||
@@ -233,13 +253,19 @@
|
||||
const mail2925Mode = options.mail2925Mode !== undefined
|
||||
? options.mail2925Mode
|
||||
: currentState.mail2925Mode;
|
||||
if (isGeneratedAliasProvider?.(provider, mail2925Mode)) {
|
||||
return fetchManagedAliasEmail(currentState, options);
|
||||
}
|
||||
const generator = normalizeEmailGenerator(options.generator ?? currentState.emailGenerator);
|
||||
if (generator === 'custom') {
|
||||
throw new Error('当前邮箱生成方式为自定义邮箱,请直接填写注册邮箱。');
|
||||
}
|
||||
if (generator === CUSTOM_EMAIL_POOL_GENERATOR) {
|
||||
return fetchCustomEmailPoolEmail(currentState, options);
|
||||
}
|
||||
const shouldUseManagedAlias = typeof isGeneratedAliasProvider === 'function'
|
||||
? isGeneratedAliasProvider(currentState, mail2925Mode)
|
||||
: false;
|
||||
if (shouldUseManagedAlias) {
|
||||
return fetchManagedAliasEmail(currentState, options);
|
||||
}
|
||||
if (generator === 'icloud') {
|
||||
return fetchIcloudHideMyEmail();
|
||||
}
|
||||
@@ -255,6 +281,7 @@
|
||||
return {
|
||||
ensureCloudflareTempEmailConfig,
|
||||
fetchCloudflareEmail,
|
||||
fetchCustomEmailPoolEmail,
|
||||
fetchCloudflareTempEmailAddress,
|
||||
fetchDuckEmail,
|
||||
fetchGeneratedEmail,
|
||||
|
||||
@@ -229,12 +229,19 @@
|
||||
<div class="data-row" id="row-email-generator">
|
||||
<span class="data-label">邮箱生成</span>
|
||||
<select id="select-email-generator" class="data-select">
|
||||
<option value="gmail-alias">Gmail +tag</option>
|
||||
<option value="duck">DuckDuckGo</option>
|
||||
<option value="custom-pool">自定义邮箱池</option>
|
||||
<option value="cloudflare">Cloudflare</option>
|
||||
<option value="icloud">iCloud 隐私邮箱</option>
|
||||
<option value="cloudflare-temp-email">Cloudflare Temp Email</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="data-row data-check-row" id="row-custom-email-pool" style="display:none;">
|
||||
<span class="data-label">邮箱池</span>
|
||||
<textarea id="input-custom-email-pool" class="data-textarea"
|
||||
placeholder="每行一个邮箱,例如 alias001@gmail.com alias002@gmail.com"></textarea>
|
||||
</div>
|
||||
<div class="data-row" id="row-temp-email-base-url" style="display:none;">
|
||||
<span class="data-label">Temp API</span>
|
||||
<input type="text" id="input-temp-email-base-url" class="data-input" placeholder="https://your-worker-domain" />
|
||||
|
||||
+158
-17
@@ -102,6 +102,8 @@ const rowMail2925PoolSettings = document.getElementById('row-mail2925-pool-setti
|
||||
const mail2925ModeButtons = Array.from(document.querySelectorAll('[data-mail2925-mode]'));
|
||||
const rowEmailGenerator = document.getElementById('row-email-generator');
|
||||
const selectEmailGenerator = document.getElementById('select-email-generator');
|
||||
const rowCustomEmailPool = document.getElementById('row-custom-email-pool');
|
||||
const inputCustomEmailPool = document.getElementById('input-custom-email-pool');
|
||||
const rowTempEmailBaseUrl = document.getElementById('row-temp-email-base-url');
|
||||
const inputTempEmailBaseUrl = document.getElementById('input-temp-email-base-url');
|
||||
const rowTempEmailAdminAuth = document.getElementById('row-temp-email-admin-auth');
|
||||
@@ -254,7 +256,9 @@ const HOTMAIL_SERVICE_MODE_REMOTE = 'remote';
|
||||
const HOTMAIL_SERVICE_MODE_LOCAL = 'local';
|
||||
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 DEFAULT_LUCKMAIL_BASE_URL = 'https://mails.luckyous.com';
|
||||
const DEFAULT_LUCKMAIL_EMAIL_TYPE = 'ms_graph';
|
||||
const DISPLAY_TIMEZONE = 'Asia/Shanghai';
|
||||
@@ -463,14 +467,14 @@ function getCurrentRegistrationEmailUiCopy() {
|
||||
if (isCustomMailProvider()) {
|
||||
return getCustomMailProviderUiCopy();
|
||||
}
|
||||
if (isManagedAliasProvider()) {
|
||||
if (usesGeneratedAliasMailProvider()) {
|
||||
return getManagedAliasProviderUiCopy();
|
||||
}
|
||||
return getEmailGeneratorUiCopy();
|
||||
}
|
||||
|
||||
function isCurrentRegistrationEmailCompatible(email = inputEmail.value.trim(), provider = selectMailProvider.value, state = latestState) {
|
||||
if (!isManagedAliasProvider(provider) || !email) {
|
||||
if (!usesGeneratedAliasMailProvider(provider, getSelectedMail2925Mode()) || !email) {
|
||||
return true;
|
||||
}
|
||||
const baseEmail = getManagedAliasBaseEmailForProvider(provider, state);
|
||||
@@ -606,8 +610,19 @@ const LOG_LEVEL_LABELS = {
|
||||
error: '错误',
|
||||
};
|
||||
|
||||
function usesGeneratedAliasMailProvider(provider, mail2925Mode = getSelectedMail2925Mode()) {
|
||||
return isManagedAliasProvider(provider, mail2925Mode);
|
||||
function usesGeneratedAliasMailProvider(
|
||||
provider,
|
||||
mail2925Mode = getSelectedMail2925Mode(),
|
||||
generator = undefined
|
||||
) {
|
||||
const customEmailPoolGenerator = typeof CUSTOM_EMAIL_POOL_GENERATOR === 'string'
|
||||
? CUSTOM_EMAIL_POOL_GENERATOR
|
||||
: 'custom-pool';
|
||||
const resolvedGenerator = generator !== undefined
|
||||
? generator
|
||||
: (typeof getSelectedEmailGenerator === 'function' ? getSelectedEmailGenerator() : '');
|
||||
return resolvedGenerator !== customEmailPoolGenerator
|
||||
&& isManagedAliasProvider(provider, mail2925Mode);
|
||||
}
|
||||
|
||||
function parseGmailBaseEmail(rawValue = '') {
|
||||
@@ -1173,7 +1188,37 @@ function formatAutoStepDelayInputValue(value) {
|
||||
return normalized === null ? '' : String(normalized);
|
||||
}
|
||||
|
||||
function normalizeCustomEmailPoolEntries(value = '') {
|
||||
const source = Array.isArray(value)
|
||||
? value
|
||||
: String(value || '').split(/[\r\n,,;;]+/);
|
||||
|
||||
return source
|
||||
.map((item) => String(item || '').trim().toLowerCase())
|
||||
.filter((item) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(item));
|
||||
}
|
||||
|
||||
function usesCustomEmailPoolGenerator(provider = selectMailProvider.value) {
|
||||
return !isCustomMailProvider(provider)
|
||||
&& !isLuckmailProvider(provider)
|
||||
&& getSelectedEmailGenerator() === CUSTOM_EMAIL_POOL_GENERATOR;
|
||||
}
|
||||
|
||||
function getCustomEmailPoolSize() {
|
||||
return normalizeCustomEmailPoolEntries(inputCustomEmailPool?.value).length;
|
||||
}
|
||||
|
||||
function syncRunCountFromCustomEmailPool() {
|
||||
if (!usesCustomEmailPoolGenerator()) {
|
||||
return;
|
||||
}
|
||||
inputRunCount.value = String(getCustomEmailPoolSize());
|
||||
}
|
||||
|
||||
function getRunCountValue() {
|
||||
if (typeof usesCustomEmailPoolGenerator === 'function' && usesCustomEmailPoolGenerator()) {
|
||||
return getCustomEmailPoolSize();
|
||||
}
|
||||
return Math.max(1, parseInt(inputRunCount.value, 10) || 1);
|
||||
}
|
||||
|
||||
@@ -1486,6 +1531,9 @@ function collectSettingsPayload() {
|
||||
mail2925Mode: getSelectedMail2925Mode(),
|
||||
mail2925UseAccountPool,
|
||||
emailGenerator: selectEmailGenerator.value,
|
||||
customEmailPool: typeof normalizeCustomEmailPoolEntries === 'function'
|
||||
? normalizeCustomEmailPoolEntries(inputCustomEmailPool?.value)
|
||||
: [],
|
||||
autoDeleteUsedIcloudAlias: checkboxAutoDeleteIcloud?.checked,
|
||||
icloudHostPreference: selectIcloudHostPreference?.value || 'auto',
|
||||
...(contributionModeEnabled ? {} : {
|
||||
@@ -1738,10 +1786,11 @@ function applyAutoRunStatus(payload = currentAutoRun) {
|
||||
|
||||
setSettingsCardLocked(settingsCardLocked);
|
||||
|
||||
inputRunCount.disabled = currentAutoRun.autoRunning;
|
||||
inputRunCount.disabled = currentAutoRun.autoRunning || usesCustomEmailPoolGenerator();
|
||||
btnAutoRun.disabled = currentAutoRun.autoRunning;
|
||||
btnFetchEmail.disabled = locked
|
||||
|| isCustomMailProvider();
|
||||
|| isCustomMailProvider()
|
||||
|| usesCustomEmailPoolGenerator();
|
||||
inputEmail.disabled = locked;
|
||||
inputAutoSkipFailures.disabled = scheduled;
|
||||
|
||||
@@ -1779,7 +1828,7 @@ function applyAutoRunStatus(payload = currentAutoRun) {
|
||||
setDefaultAutoRunButton();
|
||||
inputEmail.disabled = false;
|
||||
if (!locked) {
|
||||
btnFetchEmail.disabled = isCustomMailProvider();
|
||||
btnFetchEmail.disabled = isCustomMailProvider() || usesCustomEmailPoolGenerator();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1869,7 +1918,13 @@ function applySettingsState(state) {
|
||||
setMail2925Mode(state?.mail2925Mode);
|
||||
{
|
||||
const restoredEmailGenerator = String(state?.emailGenerator || '').trim().toLowerCase();
|
||||
if (restoredEmailGenerator === 'icloud') {
|
||||
if (restoredMailProvider === GMAIL_PROVIDER) {
|
||||
selectEmailGenerator.value = restoredEmailGenerator === CUSTOM_EMAIL_POOL_GENERATOR
|
||||
? CUSTOM_EMAIL_POOL_GENERATOR
|
||||
: GMAIL_ALIAS_GENERATOR;
|
||||
} else if (restoredEmailGenerator === CUSTOM_EMAIL_POOL_GENERATOR) {
|
||||
selectEmailGenerator.value = CUSTOM_EMAIL_POOL_GENERATOR;
|
||||
} else if (restoredEmailGenerator === 'icloud') {
|
||||
selectEmailGenerator.value = 'icloud';
|
||||
} else if (restoredEmailGenerator === 'cloudflare') {
|
||||
selectEmailGenerator.value = 'cloudflare';
|
||||
@@ -1905,6 +1960,9 @@ function applySettingsState(state) {
|
||||
setManagedAliasBaseEmailInputForProvider(restoredMailProvider, state);
|
||||
inputInbucketHost.value = state?.inbucketHost || '';
|
||||
inputInbucketMailbox.value = state?.inbucketMailbox || '';
|
||||
if (inputCustomEmailPool) {
|
||||
inputCustomEmailPool.value = normalizeCustomEmailPoolEntries(state?.customEmailPool).join('\n');
|
||||
}
|
||||
setHotmailServiceMode(state?.hotmailServiceMode);
|
||||
inputHotmailRemoteBaseUrl.value = state?.hotmailRemoteBaseUrl || '';
|
||||
inputHotmailLocalBaseUrl.value = state?.hotmailLocalBaseUrl || '';
|
||||
@@ -2390,6 +2448,12 @@ function getSelectedEmailGenerator() {
|
||||
if (generator === 'custom' || generator === 'manual') {
|
||||
return 'custom';
|
||||
}
|
||||
if (generator === GMAIL_ALIAS_GENERATOR) {
|
||||
return GMAIL_ALIAS_GENERATOR;
|
||||
}
|
||||
if (generator === CUSTOM_EMAIL_POOL_GENERATOR) {
|
||||
return CUSTOM_EMAIL_POOL_GENERATOR;
|
||||
}
|
||||
if (generator === 'icloud') {
|
||||
return 'icloud';
|
||||
}
|
||||
@@ -2402,6 +2466,22 @@ function getEmailGeneratorUiCopy() {
|
||||
if (getSelectedEmailGenerator() === 'custom') {
|
||||
return getCustomMailProviderUiCopy();
|
||||
}
|
||||
if (getSelectedEmailGenerator() === GMAIL_ALIAS_GENERATOR) {
|
||||
return {
|
||||
buttonLabel: '生成',
|
||||
placeholder: '步骤 3 自动生成 Gmail +tag 邮箱并回填',
|
||||
successVerb: '生成',
|
||||
label: 'Gmail +tag 邮箱',
|
||||
};
|
||||
}
|
||||
if (getSelectedEmailGenerator() === CUSTOM_EMAIL_POOL_GENERATOR) {
|
||||
return {
|
||||
buttonLabel: '取下一个',
|
||||
placeholder: '按邮箱池顺序自动回填,也可以手动粘贴当前轮邮箱',
|
||||
successVerb: '取用',
|
||||
label: '自定义邮箱池',
|
||||
};
|
||||
}
|
||||
if (getSelectedEmailGenerator() === 'icloud') {
|
||||
return {
|
||||
buttonLabel: '获取',
|
||||
@@ -2642,13 +2722,29 @@ function updateMailProviderUI() {
|
||||
const useMail2925 = selectMailProvider.value === '2925';
|
||||
const useMail2925AccountPool = useMail2925 && Boolean(inputMail2925UseAccountPool?.checked);
|
||||
const mail2925Mode = getSelectedMail2925Mode();
|
||||
const useGeneratedAlias = usesGeneratedAliasMailProvider(selectMailProvider.value, mail2925Mode);
|
||||
const gmailOnlyGenerators = new Set([GMAIL_ALIAS_GENERATOR, CUSTOM_EMAIL_POOL_GENERATOR]);
|
||||
Array.from(selectEmailGenerator?.options || []).forEach((option) => {
|
||||
if (!option) return;
|
||||
if (useGmail) {
|
||||
option.hidden = !gmailOnlyGenerators.has(String(option.value || '').trim().toLowerCase());
|
||||
return;
|
||||
}
|
||||
option.hidden = String(option.value || '').trim().toLowerCase() === GMAIL_ALIAS_GENERATOR;
|
||||
});
|
||||
if (useGmail && !gmailOnlyGenerators.has(String(selectEmailGenerator.value || '').trim().toLowerCase())) {
|
||||
selectEmailGenerator.value = GMAIL_ALIAS_GENERATOR;
|
||||
}
|
||||
if (!useGmail && String(selectEmailGenerator.value || '').trim().toLowerCase() === GMAIL_ALIAS_GENERATOR) {
|
||||
selectEmailGenerator.value = 'duck';
|
||||
}
|
||||
const selectedGenerator = getSelectedEmailGenerator();
|
||||
const useGeneratedAlias = usesGeneratedAliasMailProvider(selectMailProvider.value, mail2925Mode, selectedGenerator);
|
||||
const useInbucket = selectMailProvider.value === 'inbucket';
|
||||
const useHotmail = selectMailProvider.value === 'hotmail-api';
|
||||
const useLuckmail = isLuckmailProvider();
|
||||
const useCustomEmail = isCustomMailProvider();
|
||||
const useIcloudProvider = isIcloudMailProvider();
|
||||
const useEmailGenerator = !useHotmail && !useLuckmail && !useGeneratedAlias && !useCustomEmail;
|
||||
const useEmailGenerator = !useHotmail && !useLuckmail && !useCustomEmail && (!useGeneratedAlias || useGmail);
|
||||
const useCloudflareTempEmailProvider = selectMailProvider.value === 'cloudflare-temp-email';
|
||||
const aliasUiCopy = useGeneratedAlias
|
||||
? getManagedAliasProviderUiCopy(selectMailProvider.value, mail2925Mode)
|
||||
@@ -2665,7 +2761,7 @@ function updateMailProviderUI() {
|
||||
const hotmailServiceMode = getSelectedHotmailServiceMode();
|
||||
rowInbucketHost.style.display = useInbucket ? '' : 'none';
|
||||
rowInbucketMailbox.style.display = useInbucket ? '' : 'none';
|
||||
const selectedGenerator = getSelectedEmailGenerator();
|
||||
const useCustomEmailPool = useEmailGenerator && selectedGenerator === CUSTOM_EMAIL_POOL_GENERATOR;
|
||||
const useCloudflare = selectedGenerator === 'cloudflare';
|
||||
const useIcloud = selectedGenerator === 'icloud';
|
||||
const useCloudflareTempEmailGenerator = selectedGenerator === 'cloudflare-temp-email';
|
||||
@@ -2676,6 +2772,9 @@ function updateMailProviderUI() {
|
||||
if (rowEmailGenerator) {
|
||||
rowEmailGenerator.style.display = useEmailGenerator ? '' : 'none';
|
||||
}
|
||||
if (rowCustomEmailPool) {
|
||||
rowCustomEmailPool.style.display = useCustomEmailPool ? '' : 'none';
|
||||
}
|
||||
if (icloudSection) {
|
||||
const showIcloudSection = (useEmailGenerator && useIcloud) || useIcloudProvider;
|
||||
icloudSection.style.display = showIcloudSection ? '' : 'none';
|
||||
@@ -2726,7 +2825,7 @@ function updateMailProviderUI() {
|
||||
}
|
||||
inputEmailPrefix.style.display = '';
|
||||
inputEmailPrefix.readOnly = false;
|
||||
selectEmailGenerator.disabled = useHotmail || useLuckmail || useGeneratedAlias || useCustomEmail;
|
||||
selectEmailGenerator.disabled = useHotmail || useLuckmail || useCustomEmail || (useGeneratedAlias && !useGmail);
|
||||
if (useGmail) {
|
||||
labelEmailPrefix.textContent = 'Gmail 原邮箱';
|
||||
inputEmailPrefix.placeholder = '例如 yourname@gmail.com';
|
||||
@@ -2742,7 +2841,7 @@ function updateMailProviderUI() {
|
||||
if (rowHotmailLocalBaseUrl) {
|
||||
rowHotmailLocalBaseUrl.style.display = useHotmail && hotmailServiceMode === HOTMAIL_SERVICE_MODE_LOCAL ? '' : 'none';
|
||||
}
|
||||
btnFetchEmail.hidden = useHotmail || useLuckmail || useCustomEmail;
|
||||
btnFetchEmail.hidden = useHotmail || useLuckmail || useCustomEmail || useCustomEmailPool;
|
||||
inputEmail.readOnly = useHotmail || useLuckmail;
|
||||
inputEmail.placeholder = useHotmail
|
||||
? '由 Hotmail 账号池自动分配'
|
||||
@@ -2755,7 +2854,7 @@ function updateMailProviderUI() {
|
||||
if (!useHotmail && !useLuckmail) {
|
||||
inputEmail.placeholder = uiCopy.placeholder;
|
||||
}
|
||||
btnFetchEmail.disabled = useLuckmail || useCustomEmail || isAutoRunLockedPhase();
|
||||
btnFetchEmail.disabled = useLuckmail || useCustomEmail || useCustomEmailPool || isAutoRunLockedPhase();
|
||||
if (!btnFetchEmail.disabled) {
|
||||
btnFetchEmail.textContent = uiCopy.buttonLabel;
|
||||
}
|
||||
@@ -2768,20 +2867,25 @@ function updateMailProviderUI() {
|
||||
? '步骤 3 会自动生成邮箱,无需手动获取'
|
||||
: (useCustomEmail ? '请先填写自定义注册邮箱,成功一轮后会自动清空' : `先自动获取${uiCopy.label},或手动粘贴邮箱后再继续`)));
|
||||
}
|
||||
if (autoHintText && useCustomEmailPool) {
|
||||
autoHintText.textContent = getCustomEmailPoolSize() > 0
|
||||
? `当前邮箱池共 ${getCustomEmailPoolSize()} 个邮箱,自动轮数会跟随数量;实际收码仍走当前邮箱服务`
|
||||
: '请先在邮箱池里每行填写一个邮箱,自动轮数会跟随数量';
|
||||
}
|
||||
if (autoHintText && useGmail && useGeneratedAlias) {
|
||||
autoHintText.textContent = '请先填写 Gmail 原邮箱,步骤 3 会自动生成 Gmail +tag 地址';
|
||||
}
|
||||
if (autoHintText && useGeneratedAlias && aliasUiCopy?.hint) {
|
||||
autoHintText.textContent = aliasUiCopy.hint;
|
||||
}
|
||||
if (autoHintText && useMail2925AccountPool) {
|
||||
if (autoHintText && useMail2925AccountPool && !useCustomEmailPool) {
|
||||
autoHintText.textContent = getMail2925Accounts().length
|
||||
? (useGeneratedAlias
|
||||
? '当前已启用 2925 号池模式,步骤 3 会基于下拉框选中的号池邮箱生成别名地址'
|
||||
: '当前已启用 2925 号池模式,步骤 4 / 8 遇到登录页时会优先使用下拉框选中的账号自动登录')
|
||||
: '当前已启用 2925 号池模式,请先在下方 2925 账号池中添加账号并选择邮箱';
|
||||
}
|
||||
if (autoHintText && showCloudflareTempEmailReceiveMailbox) {
|
||||
if (autoHintText && showCloudflareTempEmailReceiveMailbox && !useCustomEmailPool) {
|
||||
autoHintText.textContent = '若注册邮箱会转发到 Cloudflare Temp Email,请在“邮件接收”中填写实际接收转发邮件的邮箱。';
|
||||
}
|
||||
if (useHotmail) {
|
||||
@@ -2789,6 +2893,10 @@ function updateMailProviderUI() {
|
||||
} else if (useLuckmail) {
|
||||
inputEmail.value = getCurrentLuckmailEmail();
|
||||
}
|
||||
if (useCustomEmailPool) {
|
||||
syncRunCountFromCustomEmailPool();
|
||||
}
|
||||
inputRunCount.disabled = currentAutoRun.autoRunning || useCustomEmailPool;
|
||||
renderHotmailAccounts();
|
||||
if (useMail2925) {
|
||||
renderMail2925Accounts();
|
||||
@@ -3826,7 +3934,22 @@ async function startAutoRunFromCurrentSettings() {
|
||||
console.warn('Failed to refresh contribution content hint before auto run:', error);
|
||||
}
|
||||
|
||||
const totalRuns = getRunCountValue();
|
||||
if (typeof settingsDirty !== 'undefined' && settingsDirty && typeof saveSettings === 'function') {
|
||||
await saveSettings({ silent: true });
|
||||
}
|
||||
|
||||
const customEmailPoolEnabled = typeof usesCustomEmailPoolGenerator === 'function'
|
||||
&& usesCustomEmailPoolGenerator();
|
||||
const customEmailPoolSize = customEmailPoolEnabled && typeof getCustomEmailPoolSize === 'function'
|
||||
? getCustomEmailPoolSize()
|
||||
: 0;
|
||||
if (customEmailPoolEnabled && customEmailPoolSize <= 0) {
|
||||
throw new Error('请先在邮箱池里至少填写 1 个邮箱。');
|
||||
}
|
||||
const totalRuns = customEmailPoolEnabled ? customEmailPoolSize : getRunCountValue();
|
||||
if (customEmailPoolEnabled) {
|
||||
inputRunCount.value = String(customEmailPoolSize);
|
||||
}
|
||||
let mode = 'restart';
|
||||
const autoRunSkipFailures = inputAutoSkipFailures.checked;
|
||||
const contributionNickname = String(inputContributionNickname?.value || '').trim();
|
||||
@@ -4282,6 +4405,19 @@ inputEmailPrefix.addEventListener('blur', () => {
|
||||
saveSettings({ silent: true }).catch(() => {});
|
||||
});
|
||||
|
||||
inputCustomEmailPool?.addEventListener('input', () => {
|
||||
syncRunCountFromCustomEmailPool();
|
||||
updateMailProviderUI();
|
||||
markSettingsDirty(true);
|
||||
scheduleSettingsAutoSave();
|
||||
});
|
||||
inputCustomEmailPool?.addEventListener('blur', () => {
|
||||
inputCustomEmailPool.value = normalizeCustomEmailPoolEntries(inputCustomEmailPool.value).join('\n');
|
||||
syncRunCountFromCustomEmailPool();
|
||||
updateMailProviderUI();
|
||||
saveSettings({ silent: true }).catch(() => {});
|
||||
});
|
||||
|
||||
selectMail2925PoolAccount?.addEventListener('change', async () => {
|
||||
try {
|
||||
await syncSelectedMail2925PoolAccount();
|
||||
@@ -4332,6 +4468,11 @@ inputRunCount.addEventListener('input', () => {
|
||||
updateFallbackThreadIntervalInputState();
|
||||
});
|
||||
inputRunCount.addEventListener('blur', () => {
|
||||
if (usesCustomEmailPoolGenerator()) {
|
||||
syncRunCountFromCustomEmailPool();
|
||||
updateFallbackThreadIntervalInputState();
|
||||
return;
|
||||
}
|
||||
inputRunCount.value = String(getRunCountValue());
|
||||
updateFallbackThreadIntervalInputState();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
|
||||
const source = fs.readFileSync('background.js', 'utf8');
|
||||
|
||||
function extractFunction(name) {
|
||||
const markers = [`async function ${name}(`, `function ${name}(`];
|
||||
const start = markers
|
||||
.map((marker) => source.indexOf(marker))
|
||||
.find((index) => index >= 0);
|
||||
if (start < 0) {
|
||||
throw new Error(`missing function ${name}`);
|
||||
}
|
||||
|
||||
let parenDepth = 0;
|
||||
let signatureEnded = false;
|
||||
let braceStart = -1;
|
||||
for (let i = start; i < source.length; i += 1) {
|
||||
const ch = source[i];
|
||||
if (ch === '(') {
|
||||
parenDepth += 1;
|
||||
} else if (ch === ')') {
|
||||
parenDepth -= 1;
|
||||
if (parenDepth === 0) {
|
||||
signatureEnded = true;
|
||||
}
|
||||
} else if (ch === '{' && signatureEnded) {
|
||||
braceStart = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (braceStart < 0) {
|
||||
throw new Error(`missing body for function ${name}`);
|
||||
}
|
||||
|
||||
let depth = 0;
|
||||
let end = braceStart;
|
||||
for (; end < source.length; end += 1) {
|
||||
const ch = source[end];
|
||||
if (ch === '{') depth += 1;
|
||||
if (ch === '}') {
|
||||
depth -= 1;
|
||||
if (depth === 0) {
|
||||
end += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return source.slice(start, end);
|
||||
}
|
||||
|
||||
const bundle = [
|
||||
extractFunction('normalizeEmailGenerator'),
|
||||
extractFunction('normalizeCustomEmailPool'),
|
||||
extractFunction('getCustomEmailPool'),
|
||||
extractFunction('getCustomEmailPoolEmailForRun'),
|
||||
extractFunction('getEmailGeneratorLabel'),
|
||||
].join('\n');
|
||||
|
||||
function createApi() {
|
||||
return new Function(`
|
||||
const CUSTOM_EMAIL_POOL_GENERATOR = 'custom-pool';
|
||||
const CLOUDFLARE_TEMP_EMAIL_GENERATOR = 'cloudflare-temp-email';
|
||||
|
||||
${bundle}
|
||||
|
||||
return {
|
||||
normalizeEmailGenerator,
|
||||
normalizeCustomEmailPool,
|
||||
getCustomEmailPool,
|
||||
getCustomEmailPoolEmailForRun,
|
||||
getEmailGeneratorLabel,
|
||||
};
|
||||
`)();
|
||||
}
|
||||
|
||||
test('background recognizes custom email pool generator and label', () => {
|
||||
const api = createApi();
|
||||
|
||||
assert.equal(api.normalizeEmailGenerator('custom-pool'), 'custom-pool');
|
||||
assert.equal(api.getEmailGeneratorLabel('custom-pool'), '自定义邮箱池');
|
||||
});
|
||||
|
||||
test('background normalizes custom email pool input and keeps order', () => {
|
||||
const api = createApi();
|
||||
|
||||
assert.deepEqual(
|
||||
api.normalizeCustomEmailPool(' Foo@Example.com \ninvalid\nbar@example.com;baz@example.com '),
|
||||
['foo@example.com', 'bar@example.com', 'baz@example.com']
|
||||
);
|
||||
});
|
||||
|
||||
test('background selects the matching email for the current auto-run round', () => {
|
||||
const api = createApi();
|
||||
const state = {
|
||||
customEmailPool: ['first@example.com', 'second@example.com', 'third@example.com'],
|
||||
};
|
||||
|
||||
assert.equal(api.getCustomEmailPoolEmailForRun(state, 1), 'first@example.com');
|
||||
assert.equal(api.getCustomEmailPoolEmailForRun(state, 2), 'second@example.com');
|
||||
assert.equal(api.getCustomEmailPoolEmailForRun(state, 4), '');
|
||||
});
|
||||
@@ -76,3 +76,63 @@ test('generated email helper falls back to normal generator when 2925 is in rece
|
||||
['email', 'duck@example.com'],
|
||||
]);
|
||||
});
|
||||
|
||||
test('generated email helper can read the requested address from custom email pool', async () => {
|
||||
const source = fs.readFileSync('background/generated-email-helpers.js', 'utf8');
|
||||
const globalScope = {};
|
||||
const api = new Function('self', `${source}; return self.MultiPageGeneratedEmailHelpers;`)(globalScope);
|
||||
const events = [];
|
||||
|
||||
const helpers = api.createGeneratedEmailHelpers({
|
||||
addLog: async () => {},
|
||||
buildGeneratedAliasEmail: () => {
|
||||
throw new Error('should not build alias');
|
||||
},
|
||||
buildCloudflareTempEmailHeaders: () => ({}),
|
||||
CLOUDFLARE_TEMP_EMAIL_GENERATOR: 'cloudflare-temp-email',
|
||||
CUSTOM_EMAIL_POOL_GENERATOR: 'custom-pool',
|
||||
DUCK_AUTOFILL_URL: 'https://duckduckgo.com/email',
|
||||
fetch: async () => ({ ok: true, text: async () => '{}' }),
|
||||
fetchIcloudHideMyEmail: async () => {
|
||||
throw new Error('should not use icloud generator');
|
||||
},
|
||||
getCloudflareTempEmailAddressFromResponse: () => '',
|
||||
getCloudflareTempEmailConfig: () => ({ baseUrl: '', adminAuth: '', domain: '' }),
|
||||
getCustomEmailPoolEmail: (state, targetRun) => state.customEmailPool?.[targetRun - 1] || '',
|
||||
getState: async () => ({
|
||||
customEmailPool: ['first@example.com', 'second@example.com'],
|
||||
emailGenerator: 'custom-pool',
|
||||
mailProvider: 'gmail',
|
||||
}),
|
||||
ensureMail2925AccountForFlow: async () => {
|
||||
throw new Error('should not allocate 2925 account');
|
||||
},
|
||||
joinCloudflareTempEmailUrl: () => '',
|
||||
normalizeCloudflareDomain: () => '',
|
||||
normalizeCloudflareTempEmailAddress: () => '',
|
||||
normalizeEmailGenerator: (value) => String(value || '').trim().toLowerCase(),
|
||||
isGeneratedAliasProvider: () => false,
|
||||
reuseOrCreateTab: async () => {},
|
||||
sendToContentScript: async () => {
|
||||
throw new Error('should not open duck tab');
|
||||
},
|
||||
setEmailState: async (email) => {
|
||||
events.push(['email', email]);
|
||||
},
|
||||
throwIfStopped: () => {},
|
||||
});
|
||||
|
||||
const email = await helpers.fetchGeneratedEmail({
|
||||
customEmailPool: ['first@example.com', 'second@example.com'],
|
||||
emailGenerator: 'custom-pool',
|
||||
mailProvider: 'gmail',
|
||||
}, {
|
||||
generator: 'custom-pool',
|
||||
poolIndex: 1,
|
||||
});
|
||||
|
||||
assert.equal(email, 'second@example.com');
|
||||
assert.deepStrictEqual(events, [
|
||||
['email', 'second@example.com'],
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
|
||||
const source = fs.readFileSync('sidepanel/sidepanel.js', 'utf8');
|
||||
|
||||
function extractFunction(name) {
|
||||
const markers = [`async function ${name}(`, `function ${name}(`];
|
||||
const start = markers
|
||||
.map((marker) => source.indexOf(marker))
|
||||
.find((index) => index >= 0);
|
||||
if (start < 0) {
|
||||
throw new Error(`missing function ${name}`);
|
||||
}
|
||||
|
||||
let parenDepth = 0;
|
||||
let signatureEnded = false;
|
||||
let braceStart = -1;
|
||||
for (let i = start; i < source.length; i += 1) {
|
||||
const ch = source[i];
|
||||
if (ch === '(') {
|
||||
parenDepth += 1;
|
||||
} else if (ch === ')') {
|
||||
parenDepth -= 1;
|
||||
if (parenDepth === 0) {
|
||||
signatureEnded = true;
|
||||
}
|
||||
} else if (ch === '{' && signatureEnded) {
|
||||
braceStart = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (braceStart < 0) {
|
||||
throw new Error(`missing body for function ${name}`);
|
||||
}
|
||||
|
||||
let depth = 0;
|
||||
let end = braceStart;
|
||||
for (; end < source.length; end += 1) {
|
||||
const ch = source[end];
|
||||
if (ch === '{') depth += 1;
|
||||
if (ch === '}') {
|
||||
depth -= 1;
|
||||
if (depth === 0) {
|
||||
end += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return source.slice(start, end);
|
||||
}
|
||||
|
||||
test('sidepanel html exposes custom email pool generator option and input row', () => {
|
||||
const html = fs.readFileSync('sidepanel/sidepanel.html', 'utf8');
|
||||
|
||||
assert.match(html, /option value="custom-pool">自定义邮箱池<\/option>/);
|
||||
assert.match(html, /id="row-custom-email-pool"/);
|
||||
assert.match(html, /id="input-custom-email-pool"/);
|
||||
});
|
||||
|
||||
test('sidepanel locks run count to custom email pool size', () => {
|
||||
const bundle = [
|
||||
extractFunction('isCustomMailProvider'),
|
||||
extractFunction('normalizeCustomEmailPoolEntries'),
|
||||
extractFunction('getSelectedEmailGenerator'),
|
||||
extractFunction('usesGeneratedAliasMailProvider'),
|
||||
extractFunction('usesCustomEmailPoolGenerator'),
|
||||
extractFunction('getCustomEmailPoolSize'),
|
||||
extractFunction('getRunCountValue'),
|
||||
].join('\n');
|
||||
|
||||
const api = new Function(`
|
||||
const GMAIL_PROVIDER = 'gmail';
|
||||
const GMAIL_ALIAS_GENERATOR = 'gmail-alias';
|
||||
const CUSTOM_EMAIL_POOL_GENERATOR = 'custom-pool';
|
||||
const selectMailProvider = { value: 'gmail' };
|
||||
const selectEmailGenerator = { value: 'custom-pool' };
|
||||
const inputCustomEmailPool = { value: 'first@example.com\\nsecond@example.com' };
|
||||
const inputRunCount = { value: '99' };
|
||||
|
||||
function isLuckmailProvider() {
|
||||
return false;
|
||||
}
|
||||
|
||||
function isManagedAliasProvider() {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSelectedMail2925Mode() {
|
||||
return 'provide';
|
||||
}
|
||||
|
||||
function isManagedAliasProvider(provider) {
|
||||
return String(provider || '').trim().toLowerCase() === GMAIL_PROVIDER;
|
||||
}
|
||||
|
||||
${bundle}
|
||||
|
||||
return {
|
||||
getSelectedEmailGenerator,
|
||||
usesGeneratedAliasMailProvider,
|
||||
usesCustomEmailPoolGenerator,
|
||||
getCustomEmailPoolSize,
|
||||
getRunCountValue,
|
||||
};
|
||||
`)();
|
||||
|
||||
assert.equal(api.getSelectedEmailGenerator(), 'custom-pool');
|
||||
assert.equal(api.usesGeneratedAliasMailProvider('gmail', 'provide', 'gmail-alias'), true);
|
||||
assert.equal(api.usesGeneratedAliasMailProvider('gmail', 'provide', 'custom-pool'), false);
|
||||
assert.equal(api.usesCustomEmailPoolGenerator(), true);
|
||||
assert.equal(api.getCustomEmailPoolSize(), 2);
|
||||
assert.equal(api.getRunCountValue(), 2);
|
||||
});
|
||||
Reference in New Issue
Block a user