feat: 支持 Cloudflare Temp Email 固定子域

This commit is contained in:
qqqasdwx
2026-05-23 10:15:13 +00:00
parent 5f73c505a0
commit 7fe46cee31
18 changed files with 424 additions and 27 deletions
@@ -73,6 +73,8 @@ const PERSISTED_SETTING_DEFAULTS = {
accountRunHistoryTextEnabled: false,
cloudflareTempEmailLookupMode: 'receive-mailbox',
cloudflareTempEmailUseRandomSubdomain: false,
cloudflareTempEmailUseFixedSubdomain: false,
cloudflareTempEmailSubdomainPrefix: '',
cloudflareTempEmailDomain: '',
cloudflareTempEmailDomains: [],
};
@@ -97,6 +99,16 @@ function normalizeCloudflareDomains(value) { return Array.isArray(value) ? value
function normalizeCloudflareTempEmailBaseUrl(value) { return String(value || '').trim(); }
function normalizeCloudflareTempEmailAddress(value = '') { return String(value || '').trim().toLowerCase(); }
function normalizeCloudflareTempEmailDomain(value) { return String(value || '').trim().toLowerCase(); }
function normalizeCloudflareTempEmailSubdomainPrefix(value) {
const normalized = String(value || '').trim().toLowerCase();
return /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(normalized) ? normalized : '';
}
function buildCloudflareTempEmailEffectiveDomain(config = {}) {
const domain = normalizeCloudflareTempEmailDomain(config.domain);
const prefix = normalizeCloudflareTempEmailSubdomainPrefix(config.subdomainPrefix);
if (!domain) return '';
return config.useFixedSubdomain ? (prefix ? \`\${prefix}.\${domain}\` : '') : domain;
}
function normalizeCloudflareTempEmailDomains(value) {
const seen = new Set();
const domains = [];
@@ -120,17 +132,24 @@ return {
`)();
assert.equal(api.normalizePersistentSettingValue('cloudflareTempEmailUseRandomSubdomain', 1), true);
assert.equal(api.normalizePersistentSettingValue('cloudflareTempEmailUseFixedSubdomain', 1), true);
assert.equal(api.normalizePersistentSettingValue('cloudflareTempEmailSubdomainPrefix', 'Team-1'), 'team-1');
assert.equal(api.normalizePersistentSettingValue('cloudflareTempEmailSubdomainPrefix', 'team.one'), '');
assert.equal(api.normalizePersistentSettingValue('cloudflareTempEmailLookupMode', 'registration-email'), 'registration-email');
assert.equal(api.normalizePersistentSettingValue('cloudflareTempEmailLookupMode', 'bad'), 'receive-mailbox');
const payload = api.buildPersistentSettingsPayload({
cloudflareTempEmailLookupMode: 'registration-email',
cloudflareTempEmailUseRandomSubdomain: true,
cloudflareTempEmailUseFixedSubdomain: true,
cloudflareTempEmailSubdomainPrefix: 'Team',
cloudflareTempEmailDomain: 'mail.example.com',
cloudflareTempEmailDomains: ['mail.example.com', 'alt.example.com'],
});
assert.equal(payload.cloudflareTempEmailLookupMode, 'registration-email');
assert.equal(payload.cloudflareTempEmailUseRandomSubdomain, true);
assert.equal(payload.cloudflareTempEmailUseRandomSubdomain, false);
assert.equal(payload.cloudflareTempEmailUseFixedSubdomain, true);
assert.equal(payload.cloudflareTempEmailSubdomainPrefix, 'team');
assert.equal(payload.cloudflareTempEmailDomain, 'mail.example.com');
assert.deepEqual(payload.cloudflareTempEmailDomains, ['mail.example.com', 'alt.example.com']);
@@ -141,6 +160,8 @@ return {
cloudflareTempEmailLookupMode: 'registration-email',
cloudflareTempEmailReceiveMailbox: 'Forward@Example.com',
cloudflareTempEmailUseRandomSubdomain: true,
cloudflareTempEmailUseFixedSubdomain: true,
cloudflareTempEmailSubdomainPrefix: 'Team',
cloudflareTempEmailDomain: 'mail.example.com',
cloudflareTempEmailDomains: ['mail.example.com'],
});
@@ -150,9 +171,12 @@ return {
customAuth: 'custom-secret',
lookupMode: 'registration-email',
receiveMailbox: 'forward@example.com',
useRandomSubdomain: true,
useRandomSubdomain: false,
useFixedSubdomain: true,
subdomainPrefix: 'team',
domain: 'mail.example.com',
domains: ['mail.example.com'],
effectiveDomain: 'team.mail.example.com',
});
});
@@ -169,6 +193,8 @@ const PERSISTED_SETTING_DEFAULTS = {
autoDeleteUsedIcloudAlias: false,
accountRunHistoryTextEnabled: false,
cloudflareTempEmailUseRandomSubdomain: false,
cloudflareTempEmailUseFixedSubdomain: false,
cloudflareTempEmailSubdomainPrefix: '',
cloudflareTempEmailDomain: '',
cloudflareTempEmailDomains: [],
};
@@ -200,6 +226,7 @@ function normalizeCloudflareTempEmailBaseUrl(value) { return String(value || '')
function normalizeCloudflareTempEmailAddress(value = '') { return String(value || '').trim().toLowerCase(); }
function normalizeCloudflareTempEmailReceiveMailbox(value = '') { return String(value || '').trim().toLowerCase(); }
function normalizeCloudflareTempEmailDomain(value) { return String(value || '').trim().toLowerCase(); }
function normalizeCloudflareTempEmailSubdomainPrefix(value) { return String(value || '').trim().toLowerCase(); }
function normalizeCloudflareTempEmailDomains(value) { return Array.isArray(value) ? value.map((item) => String(item || '').trim().toLowerCase()).filter(Boolean) : []; }
function normalizeHotmailAccounts(value) { return Array.isArray(value) ? value : []; }
function normalizeMail2925Accounts(value) { return Array.isArray(value) ? value : []; }
@@ -561,6 +561,84 @@ test('generated email helper requests random subdomain creation while preserving
});
});
test('generated email helper uses fixed subdomain as the effective temp email domain', async () => {
const api = loadGeneratedEmailHelpersApi();
const requests = [];
const savedEmails = [];
const helpers = api.createGeneratedEmailHelpers({
addLog: async () => {},
buildGeneratedAliasEmail: () => {
throw new Error('should not build managed alias');
},
buildCloudflareTempEmailEffectiveDomain: (config) => `${config.subdomainPrefix}.${config.domain}`,
buildCloudflareTempEmailHeaders: () => ({ 'x-admin-auth': 'admin-secret' }),
CLOUDFLARE_TEMP_EMAIL_GENERATOR: 'cloudflare-temp-email',
DUCK_AUTOFILL_URL: 'https://duckduckgo.com/email',
fetch: async (url, options = {}) => {
requests.push({
url,
method: options.method,
body: options.body ? JSON.parse(options.body) : null,
});
return {
ok: true,
text: async () => JSON.stringify({ address: 'user@team.mail.example.com' }),
};
},
fetchIcloudHideMyEmail: async () => {
throw new Error('should not use icloud generator');
},
getCloudflareTempEmailAddressFromResponse: (payload) => payload.address,
getCloudflareTempEmailConfig: () => ({
baseUrl: 'https://temp.example.com',
adminAuth: 'admin-secret',
customAuth: '',
useRandomSubdomain: true,
useFixedSubdomain: true,
subdomainPrefix: 'team',
domain: 'mail.example.com',
}),
getState: async () => ({
mailProvider: '163',
emailGenerator: 'cloudflare-temp-email',
}),
ensureMail2925AccountForFlow: async () => {
throw new Error('should not allocate mail2925 account');
},
joinCloudflareTempEmailUrl: (baseUrl, path) => `${baseUrl}${path}`,
normalizeCloudflareDomain: () => '',
normalizeCloudflareTempEmailAddress: (value) => String(value || '').trim().toLowerCase(),
normalizeEmailGenerator: (value) => String(value || '').trim().toLowerCase(),
isGeneratedAliasProvider: () => false,
reuseOrCreateTab: async () => {},
sendToContentScript: async () => {
throw new Error('should not use duck generator');
},
setEmailState: async (email) => {
savedEmails.push(email);
},
throwIfStopped: () => {},
});
const email = await helpers.fetchGeneratedEmail({
emailGenerator: 'cloudflare-temp-email',
}, {
generator: 'cloudflare-temp-email',
localPart: 'user',
});
assert.equal(email, 'user@team.mail.example.com');
assert.deepEqual(savedEmails, ['user@team.mail.example.com']);
assert.equal(requests.length, 1);
assert.deepEqual(requests[0].body, {
enablePrefix: true,
enableRandomSubdomain: false,
name: 'user',
domain: 'team.mail.example.com',
});
});
test('generated email helper honors iCloud always-new fetch mode', async () => {
const api = loadGeneratedEmailHelpersApi();
const icloudOptions = [];
+34
View File
@@ -2,12 +2,14 @@ const test = require('node:test');
const assert = require('node:assert/strict');
const {
buildCloudflareTempEmailEffectiveDomain,
buildCloudflareTempEmailHeaders,
getCloudflareTempEmailAddressFromResponse,
normalizeCloudflareTempEmailBaseUrl,
normalizeCloudflareTempEmailDomain,
normalizeCloudflareTempEmailDomains,
normalizeCloudflareTempEmailMailApiMessages,
normalizeCloudflareTempEmailSubdomainPrefix,
} = require('../cloudflare-temp-email-utils.js');
const {
pickVerificationMessageWithTimeFallback,
@@ -34,6 +36,38 @@ test('normalizeCloudflareTempEmailDomain and domains de-duplicate valid entries'
);
});
test('cloudflare temp email fixed subdomain helpers validate one label and build effective domain', () => {
assert.equal(normalizeCloudflareTempEmailSubdomainPrefix(' Team-1 '), 'team-1');
assert.equal(normalizeCloudflareTempEmailSubdomainPrefix('a.example'), '');
assert.equal(normalizeCloudflareTempEmailSubdomainPrefix('-team'), '');
assert.equal(normalizeCloudflareTempEmailSubdomainPrefix('team_1'), '');
assert.equal(
buildCloudflareTempEmailEffectiveDomain({
domain: 'Mail.Example.com',
useFixedSubdomain: true,
subdomainPrefix: 'Team',
}),
'team.mail.example.com'
);
assert.equal(
buildCloudflareTempEmailEffectiveDomain({
domain: 'mail.example.com',
useFixedSubdomain: false,
subdomainPrefix: 'team',
}),
'mail.example.com'
);
assert.equal(
buildCloudflareTempEmailEffectiveDomain({
domain: 'mail.example.com',
useFixedSubdomain: true,
subdomainPrefix: '',
}),
''
);
});
test('buildCloudflareTempEmailHeaders includes auth headers and content type when needed', () => {
assert.deepEqual(
buildCloudflareTempEmailHeaders(
@@ -69,6 +69,10 @@ test('sidepanel html places cloudflare temp email controls in a standalone secti
assert.match(html, /data-temp-email-lookup-mode="registration-email"/);
assert.match(html, /id="row-temp-email-random-subdomain-toggle"/);
assert.match(html, /id="input-temp-email-use-random-subdomain"/);
assert.match(html, /id="row-temp-email-fixed-subdomain-toggle"/);
assert.match(html, /id="input-temp-email-use-fixed-subdomain"/);
assert.match(html, /id="row-temp-email-fixed-subdomain-prefix"/);
assert.match(html, /id="input-temp-email-subdomain-prefix"/);
assert.match(html, /id="btn-temp-email-domain-mode"[^>]*>更新</);
assert.doesNotMatch(html, /id="row-temp-email-random-subdomain-domain"/);
});
@@ -142,6 +146,8 @@ const inputTempEmailAdminAuth = { value: '' };
const inputTempEmailCustomAuth = { value: '' };
const inputTempEmailReceiveMailbox = { value: '' };
const inputTempEmailUseRandomSubdomain = { checked: false };
const inputTempEmailUseFixedSubdomain = { checked: false };
const inputTempEmailSubdomainPrefix = { value: '' };
const calls = {
domainOptions: [],
domainEditMode: [],
@@ -150,6 +156,10 @@ const calls = {
function renderCloudflareTempEmailDomainOptions(value) { calls.domainOptions.push(value); }
function setCloudflareTempEmailDomainEditMode(editing, options) { calls.domainEditMode.push({ editing, options }); }
function setCloudflareTempEmailLookupMode(value) { calls.lookupModes.push(value); }
function normalizeCloudflareTempEmailSubdomainPrefixValue(value = '') {
const normalized = String(value || '').trim().toLowerCase();
return /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(normalized) ? normalized : '';
}
${bundle}
return {
applyCloudflareTempEmailSettingsState,
@@ -159,6 +169,8 @@ return {
inputTempEmailCustomAuth,
inputTempEmailReceiveMailbox,
inputTempEmailUseRandomSubdomain,
inputTempEmailUseFixedSubdomain,
inputTempEmailSubdomainPrefix,
};
`)();
@@ -169,6 +181,8 @@ return {
cloudflareTempEmailLookupMode: 'registration-email',
cloudflareTempEmailReceiveMailbox: 'relay@example.com',
cloudflareTempEmailUseRandomSubdomain: true,
cloudflareTempEmailUseFixedSubdomain: true,
cloudflareTempEmailSubdomainPrefix: 'Team',
cloudflareTempEmailDomain: 'mail.example.com',
});
@@ -176,7 +190,9 @@ return {
assert.equal(api.inputTempEmailAdminAuth.value, 'admin-secret');
assert.equal(api.inputTempEmailCustomAuth.value, 'custom-secret');
assert.equal(api.inputTempEmailReceiveMailbox.value, 'relay@example.com');
assert.equal(api.inputTempEmailUseRandomSubdomain.checked, true);
assert.equal(api.inputTempEmailUseRandomSubdomain.checked, false);
assert.equal(api.inputTempEmailUseFixedSubdomain.checked, true);
assert.equal(api.inputTempEmailSubdomainPrefix.value, 'team');
assert.deepEqual(api.calls.lookupModes, ['registration-email']);
assert.deepEqual(api.calls.domainOptions, ['mail.example.com']);
assert.deepEqual(api.calls.domainEditMode, [{ editing: false, options: { clearInput: true } }]);
@@ -416,6 +432,8 @@ const rowTempEmailCustomAuth = ${JSON.stringify(createRow('none'))};
const rowTempEmailLookupMode = ${JSON.stringify(createRow('none'))};
const rowTempEmailReceiveMailbox = ${JSON.stringify(createRow('none'))};
const rowTempEmailRandomSubdomainToggle = ${JSON.stringify(createRow('none'))};
const rowTempEmailFixedSubdomainToggle = ${JSON.stringify(createRow('none'))};
const rowTempEmailFixedSubdomainPrefix = ${JSON.stringify(createRow('none'))};
const rowTempEmailDomain = ${JSON.stringify(createRow('none'))};
const cloudflareTempEmailSection = ${JSON.stringify(createRow('none'))};
const hotmailSection = ${JSON.stringify(createRow('none'))};
@@ -436,7 +454,10 @@ const rowHotmailLocalBaseUrl = ${JSON.stringify(createRow('none'))};
const inputMail2925UseAccountPool = { checked: false };
const selectMailProvider = { value: '163' };
const selectEmailGenerator = { value: 'cloudflare-temp-email', disabled: false };
const selectTempEmailDomain = { value: 'mail.example.com' };
const inputTempEmailUseRandomSubdomain = { checked: false };
const inputTempEmailUseFixedSubdomain = { checked: false };
const inputTempEmailSubdomainPrefix = { value: 'team' };
const calls = {
tempDomainEditMode: [],
};
@@ -460,6 +481,14 @@ function getSelectedHotmailServiceMode() { return 'local'; }
function getCloudflareDomainsFromState() { return { domains: [], activeDomain: '' }; }
function setCloudflareDomainEditMode() {}
function getCloudflareTempEmailDomainsFromState() { return { domains: ['mail.example.com'], activeDomain: 'mail.example.com' }; }
function normalizeCloudflareTempEmailDomainValue(value = '') { return String(value || '').trim().toLowerCase(); }
function normalizeCloudflareTempEmailSubdomainPrefixValue(value = '') { return String(value || '').trim().toLowerCase(); }
function buildCloudflareTempEmailEffectiveDomainValue(domain = '', subdomainPrefix = '', options = {}) {
const normalizedDomain = normalizeCloudflareTempEmailDomainValue(domain);
const normalizedPrefix = normalizeCloudflareTempEmailSubdomainPrefixValue(subdomainPrefix);
if (options.requirePrefix && !normalizedPrefix) return '';
return normalizedPrefix ? \`\${normalizedPrefix}.\${normalizedDomain}\` : normalizedDomain;
}
function setCloudflareTempEmailDomainEditMode(editing) { calls.tempDomainEditMode.push(editing); }
function queueIcloudAliasRefresh() {}
function hideIcloudLoginHelp() {}
@@ -477,8 +506,12 @@ return {
rowTempEmailLookupMode,
rowTempEmailReceiveMailbox,
rowTempEmailRandomSubdomainToggle,
rowTempEmailFixedSubdomainToggle,
rowTempEmailFixedSubdomainPrefix,
rowTempEmailDomain,
inputTempEmailUseRandomSubdomain,
inputTempEmailUseFixedSubdomain,
inputTempEmailSubdomainPrefix,
selectMailProvider,
selectEmailGenerator,
setLookupMode(value) {
@@ -492,6 +525,8 @@ return {
api.updateMailProviderUI();
assert.equal(api.cloudflareTempEmailSection.style.display, '');
assert.equal(api.rowTempEmailRandomSubdomainToggle.style.display, '');
assert.equal(api.rowTempEmailFixedSubdomainToggle.style.display, '');
assert.equal(api.rowTempEmailFixedSubdomainPrefix.style.display, 'none');
assert.equal(api.rowTempEmailDomain.style.display, '');
api.selectMailProvider.value = 'cloudflare-temp-email';
@@ -513,4 +548,16 @@ return {
assert.equal(api.cloudflareTempEmailSection.style.display, '');
assert.equal(api.rowTempEmailDomain.style.display, '');
assert.match(api.autoHintText.textContent, /RANDOM_SUBDOMAIN_DOMAINS/);
api.inputTempEmailUseRandomSubdomain.checked = false;
api.inputTempEmailUseFixedSubdomain.checked = true;
api.inputTempEmailSubdomainPrefix.value = 'team';
api.updateMailProviderUI();
assert.equal(api.rowTempEmailFixedSubdomainPrefix.style.display, '');
assert.match(api.autoHintText.textContent, /team\.mail\.example\.com/);
assert.match(api.autoHintText.textContent, /ENABLE_CREATE_ADDRESS_SUBDOMAIN_MATCH/);
api.inputTempEmailSubdomainPrefix.value = '';
api.updateMailProviderUI();
assert.match(api.autoHintText.textContent, /请填写有效的子域前缀/);
});
@@ -245,6 +245,8 @@ const inputTempEmailAdminAuth = { value: 'admin-secret' };
const inputTempEmailCustomAuth = { value: 'custom-secret' };
const inputTempEmailReceiveMailbox = { value: 'relay@example.com' };
const inputTempEmailUseRandomSubdomain = { checked: true };
const inputTempEmailUseFixedSubdomain = { checked: false };
const inputTempEmailSubdomainPrefix = { value: '' };
const inputAutoSkipFailures = { checked: false };
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '5' };
const inputAutoStepDelaySeconds = { value: '10' };
@@ -293,6 +295,7 @@ function normalizeLuckmailBaseUrl(value) { return String(value || '').trim(); }
function normalizeLuckmailEmailType(value) { return String(value || '').trim(); }
function normalizeCloudflareTempEmailBaseUrlValue(value) { return String(value || '').trim(); }
function normalizeCloudflareTempEmailReceiveMailboxValue(value) { return String(value || '').trim(); }
function normalizeCloudflareTempEmailSubdomainPrefixValue(value) { return String(value || '').trim().toLowerCase(); }
function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) || 0; }
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
function normalizeVerificationResendCount(value, fallback) { return Number.isFinite(Number(value)) ? Number(value) : fallback; }
+7
View File
@@ -130,6 +130,8 @@ const inputTempEmailAdminAuth = { value: '' };
const inputTempEmailCustomAuth = { value: '' };
const inputTempEmailReceiveMailbox = { value: '' };
const inputTempEmailUseRandomSubdomain = { checked: false };
const inputTempEmailUseFixedSubdomain = { checked: false };
const inputTempEmailSubdomainPrefix = { value: '' };
const inputAutoSkipFailures = { checked: false };
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '0' };
const inputAutoStepDelaySeconds = { value: '' };
@@ -215,6 +217,7 @@ 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 normalizeCloudflareTempEmailSubdomainPrefixValue(value) { return String(value || '').trim().toLowerCase(); }
function normalizeAccountRunHistoryHelperBaseUrlValue(value) { return String(value || '').trim(); }
function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) || 0; }
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
@@ -273,6 +276,8 @@ const rowTempEmailAdminAuth = createRow();
const rowTempEmailCustomAuth = createRow();
const rowTempEmailReceiveMailbox = createRow();
const rowTempEmailRandomSubdomainToggle = createRow();
const rowTempEmailFixedSubdomainToggle = createRow();
const rowTempEmailFixedSubdomainPrefix = createRow();
const rowTempEmailDomain = createRow();
const cloudflareTempEmailSection = createRow();
const hotmailSection = createRow();
@@ -299,6 +304,8 @@ const selectIcloudTargetMailboxType = { value: 'icloud-inbox' };
const selectIcloudForwardMailProvider = { value: 'gmail' };
const selectIcloudHostPreference = { value: 'icloud.com.cn' };
const inputTempEmailUseRandomSubdomain = { checked: false };
const inputTempEmailUseFixedSubdomain = { checked: false };
const inputTempEmailSubdomainPrefix = { value: '' };
const inputRunCount = { disabled: false };
const currentAutoRun = { autoRunning: false };
const MAIL_PROVIDER_LOGIN_CONFIGS = { gmail: { label: 'Gmail 邮箱' } };
@@ -201,6 +201,8 @@ const inputTempEmailAdminAuth = { value: '' };
const inputTempEmailCustomAuth = { value: '' };
const inputTempEmailReceiveMailbox = { value: '' };
const inputTempEmailUseRandomSubdomain = { checked: false };
const inputTempEmailUseFixedSubdomain = { checked: false };
const inputTempEmailSubdomainPrefix = { value: '' };
const inputAutoSkipFailures = { checked: false };
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '0' };
const inputAutoStepDelaySeconds = { value: '' };
@@ -253,6 +255,7 @@ 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 normalizeCloudflareTempEmailSubdomainPrefixValue(value) { return String(value || '').trim().toLowerCase(); }
function normalizeAccountRunHistoryHelperBaseUrlValue(value) { return String(value || '').trim(); }
function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) || 0; }
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
@@ -976,6 +976,8 @@ const inputTempEmailAdminAuth = { value: '' };
const inputTempEmailCustomAuth = { value: '' };
const inputTempEmailReceiveMailbox = { value: '' };
const inputTempEmailUseRandomSubdomain = { checked: false };
const inputTempEmailUseFixedSubdomain = { checked: false };
const inputTempEmailSubdomainPrefix = { value: '' };
const inputAutoSkipFailures = { checked: false };
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '0' };
const inputAutoStepDelaySeconds = { value: '' };
@@ -1067,6 +1069,7 @@ 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 normalizeCloudflareTempEmailSubdomainPrefixValue(value) { return String(value || '').trim().toLowerCase(); }
function normalizeAccountRunHistoryHelperBaseUrlValue(value) { return String(value || '').trim(); }
function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) || 0; }
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }