feat: 新增邮件接收功能,支持配置 Cloudflare Temp Email 收件邮箱

This commit is contained in:
QLHazyCoder
2026-04-15 20:29:35 +08:00
parent 49eccd579c
commit 544ecb33c2
5 changed files with 158 additions and 70 deletions
+34 -4
View File
@@ -200,6 +200,7 @@ const PERSISTED_SETTING_DEFAULTS = {
cloudflareTempEmailBaseUrl: '', cloudflareTempEmailBaseUrl: '',
cloudflareTempEmailAdminAuth: '', cloudflareTempEmailAdminAuth: '',
cloudflareTempEmailCustomAuth: '', cloudflareTempEmailCustomAuth: '',
cloudflareTempEmailReceiveMailbox: '',
cloudflareTempEmailDomain: '', cloudflareTempEmailDomain: '',
cloudflareTempEmailDomains: [], cloudflareTempEmailDomains: [],
hotmailAccounts: [], hotmailAccounts: [],
@@ -648,11 +649,32 @@ function getCloudflareTempEmailConfig(state = {}) {
baseUrl: normalizeCloudflareTempEmailBaseUrl(state.cloudflareTempEmailBaseUrl), baseUrl: normalizeCloudflareTempEmailBaseUrl(state.cloudflareTempEmailBaseUrl),
adminAuth: String(state.cloudflareTempEmailAdminAuth || ''), adminAuth: String(state.cloudflareTempEmailAdminAuth || ''),
customAuth: String(state.cloudflareTempEmailCustomAuth || ''), customAuth: String(state.cloudflareTempEmailCustomAuth || ''),
receiveMailbox: normalizeCloudflareTempEmailReceiveMailbox(state.cloudflareTempEmailReceiveMailbox),
domain: normalizeCloudflareTempEmailDomain(state.cloudflareTempEmailDomain), domain: normalizeCloudflareTempEmailDomain(state.cloudflareTempEmailDomain),
domains: normalizeCloudflareTempEmailDomains(state.cloudflareTempEmailDomains), 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) { function normalizePersistentSettingValue(key, value) {
switch (key) { switch (key) {
case 'panelMode': case 'panelMode':
@@ -715,6 +737,8 @@ function normalizePersistentSettingValue(key, value) {
case 'cloudflareTempEmailAdminAuth': case 'cloudflareTempEmailAdminAuth':
case 'cloudflareTempEmailCustomAuth': case 'cloudflareTempEmailCustomAuth':
return String(value || ''); return String(value || '');
case 'cloudflareTempEmailReceiveMailbox':
return normalizeCloudflareTempEmailReceiveMailbox(value);
case 'cloudflareTempEmailDomain': case 'cloudflareTempEmailDomain':
return normalizeCloudflareTempEmailDomain(value); return normalizeCloudflareTempEmailDomain(value);
case 'cloudflareTempEmailDomains': case 'cloudflareTempEmailDomains':
@@ -2629,12 +2653,18 @@ async function listCloudflareTempEmailMessages(state, options = {}) {
} }
async function pollCloudflareTempEmailVerificationCode(step, state, pollPayload = {}) { 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) { 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 maxAttempts = Number(pollPayload.maxAttempts) || 5;
const intervalMs = Number(pollPayload.intervalMs) || 3000; const intervalMs = Number(pollPayload.intervalMs) || 3000;
let lastError = null; let lastError = null;
@@ -2642,7 +2672,7 @@ async function pollCloudflareTempEmailVerificationCode(step, state, pollPayload
for (let attempt = 1; attempt <= maxAttempts; attempt++) { for (let attempt = 1; attempt <= maxAttempts; attempt++) {
throwIfStopped(); throwIfStopped();
try { try {
const { config, messages } = await listCloudflareTempEmailMessages(state, { const { messages } = await listCloudflareTempEmailMessages(state, {
address: targetEmail, address: targetEmail,
limit: pollPayload.limit || CLOUDFLARE_TEMP_EMAIL_DEFAULT_PAGE_SIZE, limit: pollPayload.limit || CLOUDFLARE_TEMP_EMAIL_DEFAULT_PAGE_SIZE,
offset: pollPayload.offset || 0, offset: pollPayload.offset || 0,
+4
View File
@@ -202,6 +202,10 @@
<span class="data-label">Custom Auth</span> <span class="data-label">Custom Auth</span>
<input type="password" id="input-temp-email-custom-auth" class="data-input data-input-with-icon" placeholder="仅当站点启用了访问密码时再填写;这是额外鉴权,不替代 Admin Auth。" /> <input type="password" id="input-temp-email-custom-auth" class="data-input data-input-with-icon" placeholder="仅当站点启用了访问密码时再填写;这是额外鉴权,不替代 Admin Auth。" />
</div> </div>
<div class="data-row" id="row-temp-email-receive-mailbox" style="display:none;">
<span class="data-label">邮件接收</span>
<input type="text" id="input-temp-email-receive-mailbox" class="data-input" placeholder="用于接收转发邮件的邮箱,例如 1@email.example.com" />
</div>
<div class="data-row" id="row-temp-email-domain" style="display:none;"> <div class="data-row" id="row-temp-email-domain" style="display:none;">
<span class="data-label">Temp 域名</span> <span class="data-label">Temp 域名</span>
<div class="data-inline"> <div class="data-inline">
+27
View File
@@ -78,6 +78,8 @@ const rowTempEmailAdminAuth = document.getElementById('row-temp-email-admin-auth
const inputTempEmailAdminAuth = document.getElementById('input-temp-email-admin-auth'); const inputTempEmailAdminAuth = document.getElementById('input-temp-email-admin-auth');
const rowTempEmailCustomAuth = document.getElementById('row-temp-email-custom-auth'); const rowTempEmailCustomAuth = document.getElementById('row-temp-email-custom-auth');
const inputTempEmailCustomAuth = document.getElementById('input-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 rowTempEmailDomain = document.getElementById('row-temp-email-domain');
const selectTempEmailDomain = document.getElementById('select-temp-email-domain'); const selectTempEmailDomain = document.getElementById('select-temp-email-domain');
const inputTempEmailDomain = document.getElementById('input-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 = '') { function normalizeCloudflareTempEmailDomainValue(value = '') {
return normalizeCloudflareDomainValue(value); return normalizeCloudflareDomainValue(value);
} }
@@ -1162,6 +1170,7 @@ function collectSettingsPayload() {
cloudflareTempEmailBaseUrl: normalizeCloudflareTempEmailBaseUrlValue(inputTempEmailBaseUrl.value), cloudflareTempEmailBaseUrl: normalizeCloudflareTempEmailBaseUrlValue(inputTempEmailBaseUrl.value),
cloudflareTempEmailAdminAuth: inputTempEmailAdminAuth.value, cloudflareTempEmailAdminAuth: inputTempEmailAdminAuth.value,
cloudflareTempEmailCustomAuth: inputTempEmailCustomAuth.value, cloudflareTempEmailCustomAuth: inputTempEmailCustomAuth.value,
cloudflareTempEmailReceiveMailbox: normalizeCloudflareTempEmailReceiveMailboxValue(inputTempEmailReceiveMailbox.value),
cloudflareTempEmailDomain: selectedCloudflareTempEmailDomain, cloudflareTempEmailDomain: selectedCloudflareTempEmailDomain,
cloudflareTempEmailDomains: tempEmailDomains, cloudflareTempEmailDomains: tempEmailDomains,
autoRunSkipFailures: inputAutoSkipFailures.checked, autoRunSkipFailures: inputAutoSkipFailures.checked,
@@ -1521,6 +1530,7 @@ function applySettingsState(state) {
inputTempEmailBaseUrl.value = state?.cloudflareTempEmailBaseUrl || ''; inputTempEmailBaseUrl.value = state?.cloudflareTempEmailBaseUrl || '';
inputTempEmailAdminAuth.value = state?.cloudflareTempEmailAdminAuth || ''; inputTempEmailAdminAuth.value = state?.cloudflareTempEmailAdminAuth || '';
inputTempEmailCustomAuth.value = state?.cloudflareTempEmailCustomAuth || ''; inputTempEmailCustomAuth.value = state?.cloudflareTempEmailCustomAuth || '';
inputTempEmailReceiveMailbox.value = state?.cloudflareTempEmailReceiveMailbox || '';
renderCloudflareDomainOptions(state?.cloudflareDomain || ''); renderCloudflareDomainOptions(state?.cloudflareDomain || '');
setCloudflareDomainEditMode(false, { clearInput: true }); setCloudflareDomainEditMode(false, { clearInput: true });
renderCloudflareTempEmailDomainOptions(state?.cloudflareTempEmailDomain || ''); renderCloudflareTempEmailDomainOptions(state?.cloudflareTempEmailDomain || '');
@@ -2656,6 +2666,7 @@ function updateMailProviderUI() {
const useCloudflareTempEmailGenerator = selectedGenerator === 'cloudflare-temp-email'; const useCloudflareTempEmailGenerator = selectedGenerator === 'cloudflare-temp-email';
const showCloudflareDomain = useEmailGenerator && useCloudflare; const showCloudflareDomain = useEmailGenerator && useCloudflare;
const showCloudflareTempEmailSettings = useCloudflareTempEmailProvider || (useEmailGenerator && useCloudflareTempEmailGenerator); const showCloudflareTempEmailSettings = useCloudflareTempEmailProvider || (useEmailGenerator && useCloudflareTempEmailGenerator);
const showCloudflareTempEmailReceiveMailbox = useCloudflareTempEmailProvider && !useCloudflareTempEmailGenerator;
const showCloudflareTempEmailDomain = useEmailGenerator && useCloudflareTempEmailGenerator; const showCloudflareTempEmailDomain = useEmailGenerator && useCloudflareTempEmailGenerator;
if (rowEmailGenerator) { if (rowEmailGenerator) {
rowEmailGenerator.style.display = useEmailGenerator ? '' : 'none'; rowEmailGenerator.style.display = useEmailGenerator ? '' : 'none';
@@ -2680,6 +2691,7 @@ function updateMailProviderUI() {
rowTempEmailBaseUrl.style.display = showCloudflareTempEmailSettings ? '' : 'none'; rowTempEmailBaseUrl.style.display = showCloudflareTempEmailSettings ? '' : 'none';
rowTempEmailAdminAuth.style.display = showCloudflareTempEmailSettings ? '' : 'none'; rowTempEmailAdminAuth.style.display = showCloudflareTempEmailSettings ? '' : 'none';
rowTempEmailCustomAuth.style.display = showCloudflareTempEmailSettings ? '' : 'none'; rowTempEmailCustomAuth.style.display = showCloudflareTempEmailSettings ? '' : 'none';
rowTempEmailReceiveMailbox.style.display = showCloudflareTempEmailReceiveMailbox ? '' : 'none';
rowTempEmailDomain.style.display = showCloudflareTempEmailDomain ? '' : 'none'; rowTempEmailDomain.style.display = showCloudflareTempEmailDomain ? '' : 'none';
const { domains: tempEmailDomains } = getCloudflareTempEmailDomainsFromState(); const { domains: tempEmailDomains } = getCloudflareTempEmailDomainsFromState();
if (showCloudflareTempEmailDomain) { if (showCloudflareTempEmailDomain) {
@@ -2737,6 +2749,9 @@ function updateMailProviderUI() {
if (autoHintText && useGmail && useGeneratedAlias) { if (autoHintText && useGmail && useGeneratedAlias) {
autoHintText.textContent = '请先填写 Gmail 原邮箱,步骤 3 会自动生成 Gmail +tag 地址'; autoHintText.textContent = '请先填写 Gmail 原邮箱,步骤 3 会自动生成 Gmail +tag 地址';
} }
if (autoHintText && showCloudflareTempEmailReceiveMailbox) {
autoHintText.textContent = '若注册邮箱会转发到 Cloudflare Temp Email,请在“邮件接收”中填写实际接收转发邮件的邮箱。';
}
if (useHotmail) { if (useHotmail) {
inputEmail.value = getCurrentHotmailEmail(); inputEmail.value = getCurrentHotmailEmail();
} else if (useLuckmail) { } else if (useLuckmail) {
@@ -4717,6 +4732,15 @@ inputTempEmailCustomAuth.addEventListener('blur', () => {
saveSettings({ silent: true }).catch(() => { }); 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', () => { inputAutoSkipFailuresThreadIntervalMinutes.addEventListener('input', () => {
markSettingsDirty(true); markSettingsDirty(true);
scheduleSettingsAutoSave(); scheduleSettingsAutoSave();
@@ -4889,6 +4913,9 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
if (message.payload.cloudflareTempEmailCustomAuth !== undefined) { if (message.payload.cloudflareTempEmailCustomAuth !== undefined) {
inputTempEmailCustomAuth.value = message.payload.cloudflareTempEmailCustomAuth || ''; inputTempEmailCustomAuth.value = message.payload.cloudflareTempEmailCustomAuth || '';
} }
if (message.payload.cloudflareTempEmailReceiveMailbox !== undefined) {
inputTempEmailReceiveMailbox.value = message.payload.cloudflareTempEmailReceiveMailbox || '';
}
if (message.payload.cloudflareTempEmailDomain !== undefined || message.payload.cloudflareTempEmailDomains !== undefined) { if (message.payload.cloudflareTempEmailDomain !== undefined || message.payload.cloudflareTempEmailDomains !== undefined) {
renderCloudflareTempEmailDomainOptions(message.payload.cloudflareTempEmailDomain || latestState?.cloudflareTempEmailDomain || ''); renderCloudflareTempEmailDomainOptions(message.payload.cloudflareTempEmailDomain || latestState?.cloudflareTempEmailDomain || '');
} }
+8
View File
@@ -113,6 +113,13 @@ function normalizeCloudflareDomain(value = '') {
function normalizeCloudflareDomains(values = []) { function normalizeCloudflareDomains(values = []) {
return Array.isArray(values) ? 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 = []) { function normalizeHotmailAccounts(values = []) {
return Array.isArray(values) ? 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', 'icloud.com'), 'icloud.com');
assert.equal(api.normalizePersistentSettingValue('icloudHostPreference', 'bad-host'), 'auto'); assert.equal(api.normalizePersistentSettingValue('icloudHostPreference', 'bad-host'), 'auto');
assert.equal(api.normalizePersistentSettingValue('autoDeleteUsedIcloudAlias', 1), true); 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 () => { test('finalizeIcloudAliasAfterSuccessfulFlow marks icloud aliases as used without deleting when auto-delete is off', async () => {
+85 -66
View File
@@ -51,31 +51,10 @@ function extractFunction(name) {
return source.slice(start, end); return source.slice(start, end);
} }
test('pollCloudflareTempEmailVerificationCode returns code even if delete fails', async () => { function createProviderApi(options = {}) {
const bundle = [ const {
extractFunction('isStopError'), receiveMailbox = '',
extractFunction('throwIfStopped'), messages = [{
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: [{
id: 'mail-1', id: 'mail-1',
address: 'user@example.com', address: 'user@example.com',
receivedDateTime: '2026-04-13T09:20:00.000Z', receivedDateTime: '2026-04-13T09:20:00.000Z',
@@ -83,21 +62,59 @@ async function listCloudflareTempEmailMessages() {
from: { emailAddress: { address: 'noreply@tm.openai.com' } }, from: { emailAddress: { address: 'noreply@tm.openai.com' } },
bodyPreview: 'Your verification code is 123456.', 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 { return {
match: { match: currentMessages[0]
code: '123456', ? {
receivedAt: Date.parse(messages[0].receivedDateTime), code: String(currentMessages[0].bodyPreview).match(/(\\d{6})/)[1],
message: messages[0], receivedAt: Date.parse(currentMessages[0].receivedDateTime),
}, message: currentMessages[0],
}
: null,
usedRelaxedFilters: false, usedRelaxedFilters: false,
usedTimeFallback: false, usedTimeFallback: false,
}; };
} }
async function deleteCloudflareTempEmailMail() { async function deleteCloudflareTempEmailMail() {
throw new Error('delete failed'); if (options.deleteShouldFail) {
throw new Error('delete failed');
}
} }
${bundle} ${bundle}
@@ -105,10 +122,14 @@ ${bundle}
return { return {
pollCloudflareTempEmailVerificationCode, pollCloudflareTempEmailVerificationCode,
snapshot() { 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' }, { const result = await api.pollCloudflareTempEmailVerificationCode(4, { email: 'user@example.com' }, {
targetEmail: 'user@example.com', targetEmail: 'user@example.com',
@@ -119,42 +140,40 @@ return {
assert.equal(result.code, '123456'); assert.equal(result.code, '123456');
const state = api.snapshot(); const state = api.snapshot();
assert.equal(state.logs.some((entry) => entry.message.includes('删除 Cloudflare Temp Email 邮件失败')), true); 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 () => { test('pollCloudflareTempEmailVerificationCode requires target email or receive mailbox', async () => {
const bundle = [ const api = createProviderApi({ messages: [] });
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 };
`)();
await assert.rejects( await assert.rejects(
api.pollCloudflareTempEmailVerificationCode(4, {}, {}), 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']);
});