diff --git a/background.js b/background.js
index 8341250..a74ae57 100644
--- a/background.js
+++ b/background.js
@@ -200,6 +200,7 @@ const PERSISTED_SETTING_DEFAULTS = {
cloudflareTempEmailBaseUrl: '',
cloudflareTempEmailAdminAuth: '',
cloudflareTempEmailCustomAuth: '',
+ cloudflareTempEmailReceiveMailbox: '',
cloudflareTempEmailDomain: '',
cloudflareTempEmailDomains: [],
hotmailAccounts: [],
@@ -648,11 +649,32 @@ function getCloudflareTempEmailConfig(state = {}) {
baseUrl: normalizeCloudflareTempEmailBaseUrl(state.cloudflareTempEmailBaseUrl),
adminAuth: String(state.cloudflareTempEmailAdminAuth || ''),
customAuth: String(state.cloudflareTempEmailCustomAuth || ''),
+ receiveMailbox: normalizeCloudflareTempEmailReceiveMailbox(state.cloudflareTempEmailReceiveMailbox),
domain: normalizeCloudflareTempEmailDomain(state.cloudflareTempEmailDomain),
domains: normalizeCloudflareTempEmailDomains(state.cloudflareTempEmailDomains),
};
}
+function normalizeCloudflareTempEmailReceiveMailbox(value = '') {
+ const normalized = normalizeCloudflareTempEmailAddress(value);
+ if (!normalized) return '';
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(normalized) ? normalized : '';
+}
+
+function resolveCloudflareTempEmailPollTargetEmail(state = {}, pollPayload = {}, config = getCloudflareTempEmailConfig(state)) {
+ const configuredReceiveMailbox = normalizeCloudflareTempEmailReceiveMailbox(config.receiveMailbox);
+ if (configuredReceiveMailbox) {
+ return configuredReceiveMailbox;
+ }
+
+ const requestedTarget = normalizeCloudflareTempEmailReceiveMailbox(pollPayload.targetEmail);
+ if (requestedTarget) {
+ return requestedTarget;
+ }
+
+ return normalizeCloudflareTempEmailReceiveMailbox(state.email);
+}
+
function normalizePersistentSettingValue(key, value) {
switch (key) {
case 'panelMode':
@@ -715,6 +737,8 @@ function normalizePersistentSettingValue(key, value) {
case 'cloudflareTempEmailAdminAuth':
case 'cloudflareTempEmailCustomAuth':
return String(value || '');
+ case 'cloudflareTempEmailReceiveMailbox':
+ return normalizeCloudflareTempEmailReceiveMailbox(value);
case 'cloudflareTempEmailDomain':
return normalizeCloudflareTempEmailDomain(value);
case 'cloudflareTempEmailDomains':
@@ -2629,12 +2653,18 @@ async function listCloudflareTempEmailMessages(state, options = {}) {
}
async function pollCloudflareTempEmailVerificationCode(step, state, pollPayload = {}) {
- const targetEmail = normalizeCloudflareTempEmailAddress(pollPayload.targetEmail || state.email);
+ const config = ensureCloudflareTempEmailConfig(state, { requireAdminAuth: true });
+ const targetEmail = resolveCloudflareTempEmailPollTargetEmail(state, pollPayload, config);
+ const registrationEmail = normalizeCloudflareTempEmailReceiveMailbox(state.email);
if (!targetEmail) {
- throw new Error('Cloudflare Temp Email 轮询前缺少目标邮箱地址。');
+ throw new Error('Cloudflare Temp Email 轮询前缺少目标邮箱地址,请先填写注册邮箱或“邮件接收”邮箱。');
}
- await addLog(`步骤 ${step}:正在轮询 Cloudflare Temp Email 邮件(${targetEmail})...`, 'info');
+ if (registrationEmail && registrationEmail !== targetEmail) {
+ await addLog(`步骤 ${step}:正在轮询 Cloudflare Temp Email 收件邮箱(${targetEmail}),注册邮箱为 ${registrationEmail}...`, 'info');
+ } else {
+ await addLog(`步骤 ${step}:正在轮询 Cloudflare Temp Email 邮件(${targetEmail})...`, 'info');
+ }
const maxAttempts = Number(pollPayload.maxAttempts) || 5;
const intervalMs = Number(pollPayload.intervalMs) || 3000;
let lastError = null;
@@ -2642,7 +2672,7 @@ async function pollCloudflareTempEmailVerificationCode(step, state, pollPayload
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
throwIfStopped();
try {
- const { config, messages } = await listCloudflareTempEmailMessages(state, {
+ const { messages } = await listCloudflareTempEmailMessages(state, {
address: targetEmail,
limit: pollPayload.limit || CLOUDFLARE_TEMP_EMAIL_DEFAULT_PAGE_SIZE,
offset: pollPayload.offset || 0,
diff --git a/sidepanel/sidepanel.html b/sidepanel/sidepanel.html
index 24060c9..d123f68 100644
--- a/sidepanel/sidepanel.html
+++ b/sidepanel/sidepanel.html
@@ -202,6 +202,10 @@
Custom Auth
+
Temp 域名
diff --git a/sidepanel/sidepanel.js b/sidepanel/sidepanel.js
index c145bff..19229c4 100644
--- a/sidepanel/sidepanel.js
+++ b/sidepanel/sidepanel.js
@@ -78,6 +78,8 @@ const rowTempEmailAdminAuth = document.getElementById('row-temp-email-admin-auth
const inputTempEmailAdminAuth = document.getElementById('input-temp-email-admin-auth');
const rowTempEmailCustomAuth = document.getElementById('row-temp-email-custom-auth');
const inputTempEmailCustomAuth = document.getElementById('input-temp-email-custom-auth');
+const rowTempEmailReceiveMailbox = document.getElementById('row-temp-email-receive-mailbox');
+const inputTempEmailReceiveMailbox = document.getElementById('input-temp-email-receive-mailbox');
const rowTempEmailDomain = document.getElementById('row-temp-email-domain');
const selectTempEmailDomain = document.getElementById('select-temp-email-domain');
const inputTempEmailDomain = document.getElementById('input-temp-email-domain');
@@ -1004,6 +1006,12 @@ function normalizeCloudflareTempEmailBaseUrlValue(value = '') {
}
}
+function normalizeCloudflareTempEmailReceiveMailboxValue(value = '') {
+ const normalized = String(value || '').trim().toLowerCase();
+ if (!normalized) return '';
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(normalized) ? normalized : '';
+}
+
function normalizeCloudflareTempEmailDomainValue(value = '') {
return normalizeCloudflareDomainValue(value);
}
@@ -1162,6 +1170,7 @@ function collectSettingsPayload() {
cloudflareTempEmailBaseUrl: normalizeCloudflareTempEmailBaseUrlValue(inputTempEmailBaseUrl.value),
cloudflareTempEmailAdminAuth: inputTempEmailAdminAuth.value,
cloudflareTempEmailCustomAuth: inputTempEmailCustomAuth.value,
+ cloudflareTempEmailReceiveMailbox: normalizeCloudflareTempEmailReceiveMailboxValue(inputTempEmailReceiveMailbox.value),
cloudflareTempEmailDomain: selectedCloudflareTempEmailDomain,
cloudflareTempEmailDomains: tempEmailDomains,
autoRunSkipFailures: inputAutoSkipFailures.checked,
@@ -1521,6 +1530,7 @@ function applySettingsState(state) {
inputTempEmailBaseUrl.value = state?.cloudflareTempEmailBaseUrl || '';
inputTempEmailAdminAuth.value = state?.cloudflareTempEmailAdminAuth || '';
inputTempEmailCustomAuth.value = state?.cloudflareTempEmailCustomAuth || '';
+ inputTempEmailReceiveMailbox.value = state?.cloudflareTempEmailReceiveMailbox || '';
renderCloudflareDomainOptions(state?.cloudflareDomain || '');
setCloudflareDomainEditMode(false, { clearInput: true });
renderCloudflareTempEmailDomainOptions(state?.cloudflareTempEmailDomain || '');
@@ -2656,6 +2666,7 @@ function updateMailProviderUI() {
const useCloudflareTempEmailGenerator = selectedGenerator === 'cloudflare-temp-email';
const showCloudflareDomain = useEmailGenerator && useCloudflare;
const showCloudflareTempEmailSettings = useCloudflareTempEmailProvider || (useEmailGenerator && useCloudflareTempEmailGenerator);
+ const showCloudflareTempEmailReceiveMailbox = useCloudflareTempEmailProvider && !useCloudflareTempEmailGenerator;
const showCloudflareTempEmailDomain = useEmailGenerator && useCloudflareTempEmailGenerator;
if (rowEmailGenerator) {
rowEmailGenerator.style.display = useEmailGenerator ? '' : 'none';
@@ -2680,6 +2691,7 @@ function updateMailProviderUI() {
rowTempEmailBaseUrl.style.display = showCloudflareTempEmailSettings ? '' : 'none';
rowTempEmailAdminAuth.style.display = showCloudflareTempEmailSettings ? '' : 'none';
rowTempEmailCustomAuth.style.display = showCloudflareTempEmailSettings ? '' : 'none';
+ rowTempEmailReceiveMailbox.style.display = showCloudflareTempEmailReceiveMailbox ? '' : 'none';
rowTempEmailDomain.style.display = showCloudflareTempEmailDomain ? '' : 'none';
const { domains: tempEmailDomains } = getCloudflareTempEmailDomainsFromState();
if (showCloudflareTempEmailDomain) {
@@ -2737,6 +2749,9 @@ function updateMailProviderUI() {
if (autoHintText && useGmail && useGeneratedAlias) {
autoHintText.textContent = '请先填写 Gmail 原邮箱,步骤 3 会自动生成 Gmail +tag 地址';
}
+ if (autoHintText && showCloudflareTempEmailReceiveMailbox) {
+ autoHintText.textContent = '若注册邮箱会转发到 Cloudflare Temp Email,请在“邮件接收”中填写实际接收转发邮件的邮箱。';
+ }
if (useHotmail) {
inputEmail.value = getCurrentHotmailEmail();
} else if (useLuckmail) {
@@ -4717,6 +4732,15 @@ inputTempEmailCustomAuth.addEventListener('blur', () => {
saveSettings({ silent: true }).catch(() => { });
});
+inputTempEmailReceiveMailbox.addEventListener('input', () => {
+ markSettingsDirty(true);
+ scheduleSettingsAutoSave();
+});
+inputTempEmailReceiveMailbox.addEventListener('blur', () => {
+ inputTempEmailReceiveMailbox.value = normalizeCloudflareTempEmailReceiveMailboxValue(inputTempEmailReceiveMailbox.value);
+ saveSettings({ silent: true }).catch(() => { });
+});
+
inputAutoSkipFailuresThreadIntervalMinutes.addEventListener('input', () => {
markSettingsDirty(true);
scheduleSettingsAutoSave();
@@ -4889,6 +4913,9 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
if (message.payload.cloudflareTempEmailCustomAuth !== undefined) {
inputTempEmailCustomAuth.value = message.payload.cloudflareTempEmailCustomAuth || '';
}
+ if (message.payload.cloudflareTempEmailReceiveMailbox !== undefined) {
+ inputTempEmailReceiveMailbox.value = message.payload.cloudflareTempEmailReceiveMailbox || '';
+ }
if (message.payload.cloudflareTempEmailDomain !== undefined || message.payload.cloudflareTempEmailDomains !== undefined) {
renderCloudflareTempEmailDomainOptions(message.payload.cloudflareTempEmailDomain || latestState?.cloudflareTempEmailDomain || '');
}
diff --git a/tests/background-icloud.test.js b/tests/background-icloud.test.js
index c7f26db..e690da3 100644
--- a/tests/background-icloud.test.js
+++ b/tests/background-icloud.test.js
@@ -113,6 +113,13 @@ function normalizeCloudflareDomain(value = '') {
function normalizeCloudflareDomains(values = []) {
return Array.isArray(values) ? values : [];
}
+function normalizeCloudflareTempEmailAddress(value = '') {
+ return String(value || '').trim().toLowerCase();
+}
+function normalizeCloudflareTempEmailReceiveMailbox(value = '') {
+ const normalized = normalizeCloudflareTempEmailAddress(value);
+ return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(normalized) ? normalized : '';
+}
function normalizeHotmailAccounts(values = []) {
return Array.isArray(values) ? values : [];
}
@@ -168,6 +175,7 @@ test('normalizePersistentSettingValue handles icloud settings', () => {
assert.equal(api.normalizePersistentSettingValue('icloudHostPreference', 'icloud.com'), 'icloud.com');
assert.equal(api.normalizePersistentSettingValue('icloudHostPreference', 'bad-host'), 'auto');
assert.equal(api.normalizePersistentSettingValue('autoDeleteUsedIcloudAlias', 1), true);
+ assert.equal(api.normalizePersistentSettingValue('cloudflareTempEmailReceiveMailbox', ' Forward@Example.com '), 'forward@example.com');
});
test('finalizeIcloudAliasAfterSuccessfulFlow marks icloud aliases as used without deleting when auto-delete is off', async () => {
diff --git a/tests/cloudflare-temp-email-provider.test.js b/tests/cloudflare-temp-email-provider.test.js
index cc8a473..4bbdc55 100644
--- a/tests/cloudflare-temp-email-provider.test.js
+++ b/tests/cloudflare-temp-email-provider.test.js
@@ -51,31 +51,10 @@ function extractFunction(name) {
return source.slice(start, end);
}
-test('pollCloudflareTempEmailVerificationCode returns code even if delete fails', async () => {
- const bundle = [
- extractFunction('isStopError'),
- extractFunction('throwIfStopped'),
- extractFunction('summarizeCloudflareTempEmailMessagesForLog'),
- extractFunction('pollCloudflareTempEmailVerificationCode'),
- ].join('\n');
-
-const api = new Function(`
-let stopRequested = false;
-const STOP_ERROR_MESSAGE = '流程已被用户停止。';
-const CLOUDFLARE_TEMP_EMAIL_DEFAULT_PAGE_SIZE = 20;
-const logs = [];
-function normalizeCloudflareTempEmailAddress(value) {
- return String(value || '').trim().toLowerCase();
-}
-
-async function addLog(message, level) {
- logs.push({ message, level });
-}
-async function sleepWithStop() {}
-async function listCloudflareTempEmailMessages() {
- return {
- config: {},
- messages: [{
+function createProviderApi(options = {}) {
+ const {
+ receiveMailbox = '',
+ messages = [{
id: 'mail-1',
address: 'user@example.com',
receivedDateTime: '2026-04-13T09:20:00.000Z',
@@ -83,21 +62,59 @@ async function listCloudflareTempEmailMessages() {
from: { emailAddress: { address: 'noreply@tm.openai.com' } },
bodyPreview: 'Your verification code is 123456.',
}],
+ deleteShouldFail = false,
+ } = options;
+
+ const bundle = [
+ extractFunction('isStopError'),
+ extractFunction('throwIfStopped'),
+ extractFunction('normalizeCloudflareTempEmailReceiveMailbox'),
+ extractFunction('resolveCloudflareTempEmailPollTargetEmail'),
+ extractFunction('summarizeCloudflareTempEmailMessagesForLog'),
+ extractFunction('pollCloudflareTempEmailVerificationCode'),
+ ].join('\n');
+
+ return new Function('options', `
+let stopRequested = false;
+const STOP_ERROR_MESSAGE = '流程已被用户停止。';
+const CLOUDFLARE_TEMP_EMAIL_DEFAULT_PAGE_SIZE = 20;
+const logs = [];
+const listCalls = [];
+const messages = options.messages;
+function normalizeCloudflareTempEmailAddress(value) {
+ return String(value || '').trim().toLowerCase();
+}
+async function addLog(message, level) {
+ logs.push({ message, level });
+}
+async function sleepWithStop() {}
+function ensureCloudflareTempEmailConfig() {
+ return { receiveMailbox: options.receiveMailbox };
+}
+async function listCloudflareTempEmailMessages(_state, config) {
+ listCalls.push(config.address);
+ return {
+ config: {},
+ messages,
};
}
-function pickVerificationMessageWithTimeFallback(messages) {
+function pickVerificationMessageWithTimeFallback(currentMessages) {
return {
- match: {
- code: '123456',
- receivedAt: Date.parse(messages[0].receivedDateTime),
- message: messages[0],
- },
+ match: currentMessages[0]
+ ? {
+ code: String(currentMessages[0].bodyPreview).match(/(\\d{6})/)[1],
+ receivedAt: Date.parse(currentMessages[0].receivedDateTime),
+ message: currentMessages[0],
+ }
+ : null,
usedRelaxedFilters: false,
usedTimeFallback: false,
};
}
async function deleteCloudflareTempEmailMail() {
- throw new Error('delete failed');
+ if (options.deleteShouldFail) {
+ throw new Error('delete failed');
+ }
}
${bundle}
@@ -105,10 +122,14 @@ ${bundle}
return {
pollCloudflareTempEmailVerificationCode,
snapshot() {
- return { logs };
+ return { logs, listCalls };
},
};
-`)();
+`)(options);
+}
+
+test('pollCloudflareTempEmailVerificationCode returns code even if delete fails', async () => {
+ const api = createProviderApi({ deleteShouldFail: true });
const result = await api.pollCloudflareTempEmailVerificationCode(4, { email: 'user@example.com' }, {
targetEmail: 'user@example.com',
@@ -119,42 +140,40 @@ return {
assert.equal(result.code, '123456');
const state = api.snapshot();
assert.equal(state.logs.some((entry) => entry.message.includes('删除 Cloudflare Temp Email 邮件失败')), true);
+ assert.deepEqual(state.listCalls, ['user@example.com']);
});
-test('pollCloudflareTempEmailVerificationCode requires target email', async () => {
- const bundle = [
- extractFunction('isStopError'),
- extractFunction('throwIfStopped'),
- extractFunction('pollCloudflareTempEmailVerificationCode'),
- ].join('\n');
-
- const api = new Function(`
-let stopRequested = false;
-const STOP_ERROR_MESSAGE = '流程已被用户停止。';
-const CLOUDFLARE_TEMP_EMAIL_DEFAULT_PAGE_SIZE = 20;
-function normalizeCloudflareTempEmailAddress(value) {
- return String(value || '').trim().toLowerCase();
-}
-async function addLog() {}
-async function sleepWithStop() {}
-async function listCloudflareTempEmailMessages() {
- throw new Error('should not reach list');
-}
-function pickVerificationMessageWithTimeFallback() {
- return { match: null, usedRelaxedFilters: false, usedTimeFallback: false };
-}
-async function deleteCloudflareTempEmailMail() {}
-function summarizeCloudflareTempEmailMessagesForLog() {
- return '';
-}
-
-${bundle}
-
-return { pollCloudflareTempEmailVerificationCode };
-`)();
+test('pollCloudflareTempEmailVerificationCode requires target email or receive mailbox', async () => {
+ const api = createProviderApi({ messages: [] });
await assert.rejects(
api.pollCloudflareTempEmailVerificationCode(4, {}, {}),
- /缺少目标邮箱地址/
+ /目标邮箱地址|邮件接收邮箱/
);
});
+
+test('pollCloudflareTempEmailVerificationCode prefers configured receive mailbox over registration email', async () => {
+ const api = createProviderApi({
+ receiveMailbox: 'forward-box@email.20021108.xyz',
+ messages: [{
+ id: 'mail-2',
+ address: 'forward-box@email.20021108.xyz',
+ receivedDateTime: '2026-04-13T10:20:00.000Z',
+ subject: 'Login verification code',
+ from: { emailAddress: { address: 'noreply@tm.openai.com' } },
+ bodyPreview: 'Your verification code is 654321.',
+ }],
+ });
+
+ const result = await api.pollCloudflareTempEmailVerificationCode(4, {
+ email: 'duck-forwarded@duck.com',
+ cloudflareTempEmailReceiveMailbox: 'forward-box@email.20021108.xyz',
+ }, {
+ targetEmail: 'duck-forwarded@duck.com',
+ maxAttempts: 1,
+ intervalMs: 1,
+ });
+
+ assert.equal(result.code, '654321');
+ assert.deepEqual(api.snapshot().listCalls, ['forward-box@email.20021108.xyz']);
+});