feat: support custom email pool in the merged dev registration flow
- 吸收 dev 最新 sidepanel 与收码链路改动,保留 Cloudflare Temp Email 独立设置区、贡献模式自动前提醒和 2925 当前账号恢复接线 - 修复生成邮箱辅助层对运行态参数的判断,避免 Gmail 别名与自定义邮箱池误用旧的已保存状态 - 补充自定义邮箱池相关测试与文档,更新 README、项目结构说明和完整链路说明
This commit is contained in:
@@ -24,6 +24,8 @@
|
||||
dom.rowSub2ApiPassword,
|
||||
dom.rowSub2ApiGroup,
|
||||
dom.rowSub2ApiDefaultProxy,
|
||||
dom.rowCodex2ApiUrl,
|
||||
dom.rowCodex2ApiAdminKey,
|
||||
dom.rowCustomPassword,
|
||||
dom.rowAccountRunHistoryHelperBaseUrl,
|
||||
].filter(Boolean);
|
||||
|
||||
@@ -806,6 +806,17 @@ header {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
#row-codex2api-url .data-label,
|
||||
#row-codex2api-admin-key .data-label {
|
||||
width: 76px;
|
||||
}
|
||||
|
||||
#row-codex2api-url .data-label {
|
||||
font-size: 10px;
|
||||
letter-spacing: 0.02em;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.data-value {
|
||||
font-size: 13px;
|
||||
color: var(--text-muted);
|
||||
@@ -2393,6 +2404,19 @@ header {
|
||||
line-height: 1.55;
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 14px;
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.modal-message a,
|
||||
.modal-alert a {
|
||||
color: var(--blue);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
.modal-message a:hover,
|
||||
.modal-alert a:hover {
|
||||
color: var(--cyan);
|
||||
}
|
||||
|
||||
.modal-alert {
|
||||
|
||||
+61
-25
@@ -112,6 +112,7 @@
|
||||
<select id="select-panel-mode" class="data-select">
|
||||
<option value="cpa">CPA 面板</option>
|
||||
<option value="sub2api">SUB2API</option>
|
||||
<option value="codex2api">Codex2API</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="contribution-mode-panel" class="contribution-mode-panel" hidden>
|
||||
@@ -192,6 +193,16 @@
|
||||
<input type="text" id="input-sub2api-default-proxy" class="data-input"
|
||||
placeholder="留空则不使用代理;或填写代理名称 / ID" />
|
||||
</div>
|
||||
<div class="data-row" id="row-codex2api-url" style="display:none;">
|
||||
<span class="data-label">Codex2API</span>
|
||||
<input type="text" id="input-codex2api-url" class="data-input"
|
||||
placeholder="http://localhost:8080/admin/accounts" />
|
||||
</div>
|
||||
<div class="data-row" id="row-codex2api-admin-key" style="display:none;">
|
||||
<span class="data-label">管理密钥</span>
|
||||
<input type="password" id="input-codex2api-admin-key" class="data-input"
|
||||
placeholder="请输入 Codex2API Admin Secret" />
|
||||
</div>
|
||||
<div class="data-row" id="row-custom-password">
|
||||
<span class="data-label">账户密码</span>
|
||||
<div class="input-with-icon">
|
||||
@@ -242,31 +253,6 @@
|
||||
<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" />
|
||||
</div>
|
||||
<div class="data-row" id="row-temp-email-admin-auth" style="display:none;">
|
||||
<span class="data-label">Admin Auth</span>
|
||||
<input type="password" id="input-temp-email-admin-auth" class="data-input data-input-with-icon" placeholder="Cloudflare Temp Email admin password" />
|
||||
</div>
|
||||
<div class="data-row" id="row-temp-email-custom-auth" style="display:none;">
|
||||
<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。" />
|
||||
</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;">
|
||||
<span class="data-label">Temp 域名</span>
|
||||
<div class="data-inline">
|
||||
<select id="select-temp-email-domain" class="data-select"></select>
|
||||
<input type="text" id="input-temp-email-domain" class="data-input" placeholder="例如 mail.example.com"
|
||||
style="display:none;" />
|
||||
<button id="btn-temp-email-domain-mode" class="btn btn-outline btn-sm" type="button">添加</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-row" id="row-cf-domain" style="display:none;">
|
||||
<span class="data-label">CF 域名</span>
|
||||
<div class="data-inline">
|
||||
@@ -396,6 +382,56 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cloudflare-temp-email-section" class="data-card hotmail-card" style="display:none;">
|
||||
<div class="section-mini-header">
|
||||
<div class="section-mini-copy">
|
||||
<span class="section-label">Cloudflare Temp Email</span>
|
||||
<span class="data-value">用于生成邮箱或接收转发邮件</span>
|
||||
</div>
|
||||
<div class="section-mini-actions">
|
||||
<button id="btn-cloudflare-temp-email-usage-guide" class="btn btn-ghost btn-xs" type="button">使用教程</button>
|
||||
<button id="btn-cloudflare-temp-email-github" class="btn btn-ghost btn-xs" type="button">GitHub</button>
|
||||
</div>
|
||||
</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" />
|
||||
</div>
|
||||
<div class="data-row" id="row-temp-email-admin-auth" style="display:none;">
|
||||
<span class="data-label">Admin Auth</span>
|
||||
<input type="password" id="input-temp-email-admin-auth" class="data-input data-input-with-icon" placeholder="Cloudflare Temp Email admin password" />
|
||||
</div>
|
||||
<div class="data-row" id="row-temp-email-custom-auth" style="display:none;">
|
||||
<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。" />
|
||||
</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-random-subdomain-toggle" style="display:none;">
|
||||
<span class="data-label">随机子域</span>
|
||||
<div class="data-inline">
|
||||
<label class="toggle-switch" for="input-temp-email-use-random-subdomain" title="依赖后端 RANDOM_SUBDOMAIN_DOMAINS 配置">
|
||||
<input type="checkbox" id="input-temp-email-use-random-subdomain" />
|
||||
<span class="toggle-switch-track" aria-hidden="true">
|
||||
<span class="toggle-switch-thumb"></span>
|
||||
</span>
|
||||
<span>启用</span>
|
||||
</label>
|
||||
<span class="setting-caption">依赖后端 RANDOM_SUBDOMAIN_DOMAINS</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-row" id="row-temp-email-domain" style="display:none;">
|
||||
<span class="data-label">Temp 域名</span>
|
||||
<div class="data-inline">
|
||||
<select id="select-temp-email-domain" class="data-select"></select>
|
||||
<input type="text" id="input-temp-email-domain" class="data-input" placeholder="例如 mail.example.com"
|
||||
style="display:none;" />
|
||||
<button id="btn-temp-email-domain-mode" class="btn btn-outline btn-sm" type="button">添加</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="hotmail-section" class="data-card hotmail-card" style="display:none;">
|
||||
<div class="section-mini-header">
|
||||
<div class="section-mini-copy">
|
||||
|
||||
+301
-23
@@ -94,6 +94,10 @@ const rowSub2ApiGroup = document.getElementById('row-sub2api-group');
|
||||
const inputSub2ApiGroup = document.getElementById('input-sub2api-group');
|
||||
const rowSub2ApiDefaultProxy = document.getElementById('row-sub2api-default-proxy');
|
||||
const inputSub2ApiDefaultProxy = document.getElementById('input-sub2api-default-proxy');
|
||||
const rowCodex2ApiUrl = document.getElementById('row-codex2api-url');
|
||||
const inputCodex2ApiUrl = document.getElementById('input-codex2api-url');
|
||||
const rowCodex2ApiAdminKey = document.getElementById('row-codex2api-admin-key');
|
||||
const inputCodex2ApiAdminKey = document.getElementById('input-codex2api-admin-key');
|
||||
const rowCustomPassword = document.getElementById('row-custom-password');
|
||||
const selectMailProvider = document.getElementById('select-mail-provider');
|
||||
const btnMailLogin = document.getElementById('btn-mail-login');
|
||||
@@ -112,10 +116,15 @@ const rowTempEmailCustomAuth = document.getElementById('row-temp-email-custom-au
|
||||
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 rowTempEmailRandomSubdomainToggle = document.getElementById('row-temp-email-random-subdomain-toggle');
|
||||
const inputTempEmailUseRandomSubdomain = document.getElementById('input-temp-email-use-random-subdomain');
|
||||
const rowTempEmailDomain = document.getElementById('row-temp-email-domain');
|
||||
const selectTempEmailDomain = document.getElementById('select-temp-email-domain');
|
||||
const inputTempEmailDomain = document.getElementById('input-temp-email-domain');
|
||||
const btnTempEmailDomainMode = document.getElementById('btn-temp-email-domain-mode');
|
||||
const cloudflareTempEmailSection = document.getElementById('cloudflare-temp-email-section');
|
||||
const btnCloudflareTempEmailUsageGuide = document.getElementById('btn-cloudflare-temp-email-usage-guide');
|
||||
const btnCloudflareTempEmailGithub = document.getElementById('btn-cloudflare-temp-email-github');
|
||||
const hotmailSection = document.getElementById('hotmail-section');
|
||||
const mail2925Section = document.getElementById('mail2925-section');
|
||||
const luckmailSection = document.getElementById('luckmail-section');
|
||||
@@ -248,6 +257,7 @@ const DEFAULT_CPA_CALLBACK_MODE = 'step8';
|
||||
const MAIL_2925_MODE_PROVIDE = 'provide';
|
||||
const MAIL_2925_MODE_RECEIVE = 'receive';
|
||||
const DEFAULT_MAIL_2925_MODE = MAIL_2925_MODE_PROVIDE;
|
||||
const NEW_USER_GUIDE_PROMPT_DISMISSED_STORAGE_KEY = 'multipage-new-user-guide-prompt-dismissed';
|
||||
const AUTO_SKIP_FAILURES_PROMPT_DISMISSED_STORAGE_KEY = 'multipage-auto-skip-failures-prompt-dismissed';
|
||||
const AUTO_RUN_FALLBACK_RISK_PROMPT_DISMISSED_STORAGE_KEY = 'multipage-auto-run-fallback-risk-prompt-dismissed';
|
||||
const CONTRIBUTION_CONTENT_PROMPT_DISMISSED_VERSION_STORAGE_KEY = 'multipage-contribution-content-prompt-dismissed-version';
|
||||
@@ -610,6 +620,10 @@ const LOG_LEVEL_LABELS = {
|
||||
error: '错误',
|
||||
};
|
||||
|
||||
const CLOUDFLARE_TEMP_EMAIL_REPOSITORY_URL = 'https://github.com/dreamhunter2333/cloudflare_temp_email';
|
||||
const CLOUDFLARE_TEMP_EMAIL_BUILD_TUTORIAL_URL = 'https://linux.do/t/topic/316819';
|
||||
const CLOUDFLARE_TEMP_EMAIL_RANDOM_SUBDOMAIN_ISSUE_URL = 'https://github.com/dreamhunter2333/cloudflare_temp_email/issues/942';
|
||||
|
||||
function usesGeneratedAliasMailProvider(
|
||||
provider,
|
||||
mail2925Mode = getSelectedMail2925Mode(),
|
||||
@@ -685,6 +699,19 @@ function resetActionModalAlert() {
|
||||
autoStartAlert.className = 'modal-alert';
|
||||
}
|
||||
|
||||
function setActionModalMessageContent({ text = '', html = '' } = {}) {
|
||||
if (!autoStartMessage) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (html) {
|
||||
autoStartMessage.innerHTML = html;
|
||||
return;
|
||||
}
|
||||
|
||||
autoStartMessage.textContent = text;
|
||||
}
|
||||
|
||||
function resetActionModalButtons() {
|
||||
const buttons = [btnAutoStartCancel, btnAutoStartRestart, btnAutoStartContinue];
|
||||
buttons.forEach((button) => {
|
||||
@@ -760,7 +787,7 @@ function resolveModalChoice(choice) {
|
||||
}
|
||||
}
|
||||
|
||||
function openActionModal({ title, message, actions, option, alert, buildResult }) {
|
||||
function openActionModal({ title, message, messageHtml, actions, option, alert, buildResult }) {
|
||||
if (!autoStartModal) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
@@ -771,7 +798,7 @@ function openActionModal({ title, message, actions, option, alert, buildResult }
|
||||
|
||||
resetActionModalButtons();
|
||||
autoStartTitle.textContent = title;
|
||||
autoStartMessage.textContent = message;
|
||||
setActionModalMessageContent({ text: message, html: messageHtml });
|
||||
currentModalActions = actions || [];
|
||||
modalResultBuilder = typeof buildResult === 'function' ? buildResult : null;
|
||||
const buttonSlots = currentModalActions.length <= 2
|
||||
@@ -865,6 +892,59 @@ function setPromptDismissed(storageKey, dismissed) {
|
||||
}
|
||||
}
|
||||
|
||||
function isNewUserGuidePromptDismissed() {
|
||||
return isPromptDismissed(NEW_USER_GUIDE_PROMPT_DISMISSED_STORAGE_KEY);
|
||||
}
|
||||
|
||||
function setNewUserGuidePromptDismissed(dismissed) {
|
||||
setPromptDismissed(NEW_USER_GUIDE_PROMPT_DISMISSED_STORAGE_KEY, dismissed);
|
||||
}
|
||||
|
||||
function shouldPromptNewUserGuide() {
|
||||
if (isNewUserGuidePromptDismissed()) {
|
||||
return false;
|
||||
}
|
||||
if (!btnContributionMode || btnContributionMode.disabled) {
|
||||
return false;
|
||||
}
|
||||
if (latestState?.contributionMode) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getContributionPortalUrl() {
|
||||
return String(contributionContentService?.portalUrl || 'https://apikey.qzz.io').trim();
|
||||
}
|
||||
|
||||
function openNewUserGuidePrompt() {
|
||||
return openActionModal({
|
||||
title: '新手引导',
|
||||
message: '如果你是第一次使用,可以先查看贡献页里的公告和使用教程。点击“查看引导”会自动打开贡献页面。',
|
||||
alert: {
|
||||
text: '本提示仅出现一次。',
|
||||
},
|
||||
actions: [
|
||||
{ id: null, label: '取消', variant: 'btn-ghost' },
|
||||
{ id: 'confirm', label: '查看引导', variant: 'btn-primary' },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
async function maybeShowNewUserGuidePrompt() {
|
||||
if (!shouldPromptNewUserGuide()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
setNewUserGuidePromptDismissed(true);
|
||||
const choice = await openNewUserGuidePrompt();
|
||||
if (choice === 'confirm') {
|
||||
openExternalUrl(getContributionPortalUrl());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getDismissedContributionContentPromptVersion() {
|
||||
return String(localStorage.getItem(CONTRIBUTION_CONTENT_PROMPT_DISMISSED_VERSION_STORAGE_KEY) || '').trim();
|
||||
}
|
||||
@@ -1501,6 +1581,18 @@ function setCloudflareTempEmailDomainEditMode(editing, options = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
function applyCloudflareTempEmailSettingsState(state = {}) {
|
||||
inputTempEmailBaseUrl.value = state?.cloudflareTempEmailBaseUrl || '';
|
||||
inputTempEmailAdminAuth.value = state?.cloudflareTempEmailAdminAuth || '';
|
||||
inputTempEmailCustomAuth.value = state?.cloudflareTempEmailCustomAuth || '';
|
||||
inputTempEmailReceiveMailbox.value = state?.cloudflareTempEmailReceiveMailbox || '';
|
||||
if (inputTempEmailUseRandomSubdomain) {
|
||||
inputTempEmailUseRandomSubdomain.checked = Boolean(state?.cloudflareTempEmailUseRandomSubdomain);
|
||||
}
|
||||
renderCloudflareTempEmailDomainOptions(state?.cloudflareTempEmailDomain || '');
|
||||
setCloudflareTempEmailDomainEditMode(false, { clearInput: true });
|
||||
}
|
||||
|
||||
function collectSettingsPayload() {
|
||||
const { domains, activeDomain } = getCloudflareDomainsFromState();
|
||||
const selectedCloudflareDomain = normalizeCloudflareDomainValue(
|
||||
@@ -1524,12 +1616,15 @@ function collectSettingsPayload() {
|
||||
sub2apiPassword: inputSub2ApiPassword.value,
|
||||
sub2apiGroupName: inputSub2ApiGroup.value.trim(),
|
||||
sub2apiDefaultProxyName: inputSub2ApiDefaultProxy.value.trim(),
|
||||
codex2apiUrl: inputCodex2ApiUrl.value.trim(),
|
||||
codex2apiAdminKey: inputCodex2ApiAdminKey.value.trim(),
|
||||
...(contributionModeEnabled ? {} : {
|
||||
customPassword: inputPassword.value,
|
||||
}),
|
||||
mailProvider: selectMailProvider.value,
|
||||
mail2925Mode: getSelectedMail2925Mode(),
|
||||
mail2925UseAccountPool,
|
||||
currentMail2925AccountId: String(latestState?.currentMail2925AccountId || '').trim(),
|
||||
emailGenerator: selectEmailGenerator.value,
|
||||
customEmailPool: typeof normalizeCustomEmailPoolEntries === 'function'
|
||||
? normalizeCustomEmailPoolEntries(inputCustomEmailPool?.value)
|
||||
@@ -1556,6 +1651,7 @@ function collectSettingsPayload() {
|
||||
cloudflareTempEmailAdminAuth: inputTempEmailAdminAuth.value,
|
||||
cloudflareTempEmailCustomAuth: inputTempEmailCustomAuth.value,
|
||||
cloudflareTempEmailReceiveMailbox: normalizeCloudflareTempEmailReceiveMailboxValue(inputTempEmailReceiveMailbox.value),
|
||||
cloudflareTempEmailUseRandomSubdomain: Boolean(inputTempEmailUseRandomSubdomain?.checked),
|
||||
cloudflareTempEmailDomain: selectedCloudflareTempEmailDomain,
|
||||
cloudflareTempEmailDomains: tempEmailDomains,
|
||||
autoRunSkipFailures: inputAutoSkipFailures.checked,
|
||||
@@ -1907,6 +2003,8 @@ function applySettingsState(state) {
|
||||
inputSub2ApiPassword.value = state?.sub2apiPassword || '';
|
||||
inputSub2ApiGroup.value = state?.sub2apiGroupName || '';
|
||||
inputSub2ApiDefaultProxy.value = state?.sub2apiDefaultProxyName || '';
|
||||
inputCodex2ApiUrl.value = state?.codex2apiUrl || '';
|
||||
inputCodex2ApiAdminKey.value = state?.codex2apiAdminKey || '';
|
||||
const restoredMailProvider = isCustomMailProvider(state?.mailProvider)
|
||||
|| [ICLOUD_PROVIDER, 'hotmail-api', GMAIL_PROVIDER, 'luckmail-api', '163', '163-vip', 'qq', 'inbucket', '2925', 'cloudflare-temp-email'].includes(String(state?.mailProvider || '').trim())
|
||||
? String(state?.mailProvider || '163').trim()
|
||||
@@ -1970,14 +2068,9 @@ function applySettingsState(state) {
|
||||
inputLuckmailBaseUrl.value = normalizeLuckmailBaseUrl(state?.luckmailBaseUrl);
|
||||
selectLuckmailEmailType.value = normalizeLuckmailEmailType(state?.luckmailEmailType);
|
||||
inputLuckmailDomain.value = state?.luckmailDomain || '';
|
||||
inputTempEmailBaseUrl.value = state?.cloudflareTempEmailBaseUrl || '';
|
||||
inputTempEmailAdminAuth.value = state?.cloudflareTempEmailAdminAuth || '';
|
||||
inputTempEmailCustomAuth.value = state?.cloudflareTempEmailCustomAuth || '';
|
||||
inputTempEmailReceiveMailbox.value = state?.cloudflareTempEmailReceiveMailbox || '';
|
||||
applyCloudflareTempEmailSettingsState(state);
|
||||
renderCloudflareDomainOptions(state?.cloudflareDomain || '');
|
||||
setCloudflareDomainEditMode(false, { clearInput: true });
|
||||
renderCloudflareTempEmailDomainOptions(state?.cloudflareTempEmailDomain || '');
|
||||
setCloudflareTempEmailDomainEditMode(false, { clearInput: true });
|
||||
inputAutoSkipFailures.checked = Boolean(state?.autoRunSkipFailures);
|
||||
inputAutoSkipFailuresThreadIntervalMinutes.value = String(normalizeAutoRunThreadIntervalMinutes(state?.autoRunFallbackThreadIntervalMinutes));
|
||||
inputAutoDelayEnabled.checked = Boolean(state?.autoRunDelayEnabled);
|
||||
@@ -2096,6 +2189,51 @@ function openReleaseListPage() {
|
||||
openExternalUrl(getReleaseListUrl());
|
||||
}
|
||||
|
||||
function buildCloudflareTempEmailUsageGuideModalConfig() {
|
||||
const useCloudflareTempEmailProvider = String(selectMailProvider?.value || '').trim().toLowerCase() === 'cloudflare-temp-email';
|
||||
const useCloudflareTempEmailGenerator = getSelectedEmailGenerator() === 'cloudflare-temp-email';
|
||||
let alertText = '当前还没有把 Cloudflare Temp Email 选为邮箱服务或邮箱生成器。下面说明同时覆盖“生成邮箱”和“接收转发邮件”两种用法。';
|
||||
if (useCloudflareTempEmailProvider && useCloudflareTempEmailGenerator) {
|
||||
alertText = '当前同时把 Cloudflare Temp Email 用作“邮箱服务”和“邮箱生成器”。请同时配置生成邮箱和接收转发两套必填项。';
|
||||
} else if (useCloudflareTempEmailProvider) {
|
||||
alertText = '当前把 Cloudflare Temp Email 用作“邮箱服务”。重点填写 Temp API、Custom Auth 和 邮件接收。';
|
||||
} else if (useCloudflareTempEmailGenerator) {
|
||||
alertText = '当前把 Cloudflare Temp Email 用作“邮箱生成器”。重点填写 Temp API、Admin Auth 和 Temp 域名;随机子域按需开启。';
|
||||
}
|
||||
|
||||
return {
|
||||
title: 'Cloudflare Temp Email 使用教程',
|
||||
alert: { text: alertText },
|
||||
messageHtml: `Temp API:填写 Cloudflare Temp Email 后端地址。<br><br>
|
||||
Admin Auth:填写后端 admin auth。<br>
|
||||
仅在“邮箱生成 = Cloudflare Temp Email”时必填。<br><br>
|
||||
Custom Auth:仅当站点额外开启访问密码时填写。没有开启就留空。<br><br>
|
||||
Temp 域名:填写允许创建的基础域名。启用随机子域时,这里仍然填写基础域名。<br><br>
|
||||
随机子域:仅在“邮箱生成 = Cloudflare Temp Email”时使用。<br>
|
||||
后端需要已配置 RANDOM_SUBDOMAIN_DOMAINS。<br>
|
||||
CF DNS 需要设置 MX *,参考 <a href="${CLOUDFLARE_TEMP_EMAIL_RANDOM_SUBDOMAIN_ISSUE_URL}" target="_blank" rel="noopener noreferrer">Issue #942</a>。<br><br>
|
||||
邮件接收:仅在“邮箱服务 = Cloudflare Temp Email”时填写。<br>
|
||||
这里填写真正接收转发邮件的目标邮箱。<br><br>
|
||||
搭建教程:<a href="${CLOUDFLARE_TEMP_EMAIL_BUILD_TUTORIAL_URL}" target="_blank" rel="noopener noreferrer">LINUX DO 教程</a>。`,
|
||||
};
|
||||
}
|
||||
|
||||
function showCloudflareTempEmailUsageGuide() {
|
||||
const modalConfig = buildCloudflareTempEmailUsageGuideModalConfig();
|
||||
return openActionModal({
|
||||
title: modalConfig.title,
|
||||
messageHtml: modalConfig.messageHtml,
|
||||
alert: modalConfig.alert,
|
||||
actions: [
|
||||
{ id: 'ok', label: '知道了', variant: 'btn-primary' },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
function openCloudflareTempEmailRepositoryPage() {
|
||||
openExternalUrl(CLOUDFLARE_TEMP_EMAIL_REPOSITORY_URL);
|
||||
}
|
||||
|
||||
function createUpdateNoteList(notes = []) {
|
||||
if (!Array.isArray(notes) || notes.length === 0) {
|
||||
const empty = document.createElement('p');
|
||||
@@ -2289,11 +2427,70 @@ async function initializeReleaseInfo() {
|
||||
}
|
||||
|
||||
function getContributionUpdateHintMessage(snapshot = currentContributionContentSnapshot) {
|
||||
if (!snapshot?.promptVersion) {
|
||||
const lines = getContributionUpdatePromptLines(snapshot);
|
||||
if (!lines.length) {
|
||||
return '';
|
||||
}
|
||||
if (lines.length === 1) {
|
||||
return lines[0];
|
||||
}
|
||||
return lines.map((line, index) => `${index + 1}. ${line}`).join('\n');
|
||||
}
|
||||
|
||||
return '公告 / 使用教程有更新了,可点上方“贡献/使用”查看。';
|
||||
function getContributionUpdatePromptLines(snapshot = currentContributionContentSnapshot) {
|
||||
if (!snapshot?.promptVersion) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const items = Array.isArray(snapshot.items) ? snapshot.items : [];
|
||||
const hasAnnouncementOrTutorial = items.some((item) =>
|
||||
item
|
||||
&& item.isVisible
|
||||
&& ['announcement', 'tutorial'].includes(String(item.slug || '').trim().toLowerCase())
|
||||
);
|
||||
const hasQuestionnaire = items.some((item) =>
|
||||
item
|
||||
&& item.isVisible
|
||||
&& String(item.slug || '').trim().toLowerCase() === 'questionnaire'
|
||||
);
|
||||
|
||||
const lines = [];
|
||||
if (hasAnnouncementOrTutorial) {
|
||||
lines.push('公告 / 使用教程有更新了,可点上方“贡献/使用”查看。');
|
||||
}
|
||||
if (hasQuestionnaire) {
|
||||
lines.push('有新的征求意见,请佬友共同参与选择。');
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
function shouldPromptContributionUpdateBeforeAutoRun(snapshot = currentContributionContentSnapshot) {
|
||||
const promptVersion = String(snapshot?.promptVersion || '').trim();
|
||||
if (!promptVersion) {
|
||||
return false;
|
||||
}
|
||||
if (promptVersion === getDismissedContributionContentPromptVersion()) {
|
||||
return false;
|
||||
}
|
||||
return getContributionUpdatePromptLines(snapshot).length > 0;
|
||||
}
|
||||
|
||||
async function maybeConfirmContributionUpdateBeforeAutoRun(snapshot = currentContributionContentSnapshot) {
|
||||
if (!shouldPromptContributionUpdateBeforeAutoRun(snapshot)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const confirmed = await openConfirmModal({
|
||||
title: '自动前提醒',
|
||||
message: getContributionUpdateHintMessage(snapshot),
|
||||
confirmLabel: '确定继续',
|
||||
confirmVariant: 'btn-primary',
|
||||
});
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
dismissContributionUpdateHint();
|
||||
return true;
|
||||
}
|
||||
|
||||
function positionContributionUpdateHint() {
|
||||
@@ -2722,19 +2919,25 @@ function updateMailProviderUI() {
|
||||
const useMail2925 = selectMailProvider.value === '2925';
|
||||
const useMail2925AccountPool = useMail2925 && Boolean(inputMail2925UseAccountPool?.checked);
|
||||
const mail2925Mode = getSelectedMail2925Mode();
|
||||
const gmailOnlyGenerators = new Set([GMAIL_ALIAS_GENERATOR, CUSTOM_EMAIL_POOL_GENERATOR]);
|
||||
const gmailAliasGenerator = typeof GMAIL_ALIAS_GENERATOR === 'string'
|
||||
? GMAIL_ALIAS_GENERATOR
|
||||
: 'gmail-alias';
|
||||
const customEmailPoolGenerator = typeof CUSTOM_EMAIL_POOL_GENERATOR === 'string'
|
||||
? CUSTOM_EMAIL_POOL_GENERATOR
|
||||
: 'custom-pool';
|
||||
const gmailOnlyGenerators = new Set([gmailAliasGenerator, customEmailPoolGenerator]);
|
||||
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;
|
||||
option.hidden = String(option.value || '').trim().toLowerCase() === gmailAliasGenerator;
|
||||
});
|
||||
if (useGmail && !gmailOnlyGenerators.has(String(selectEmailGenerator.value || '').trim().toLowerCase())) {
|
||||
selectEmailGenerator.value = GMAIL_ALIAS_GENERATOR;
|
||||
selectEmailGenerator.value = gmailAliasGenerator;
|
||||
}
|
||||
if (!useGmail && String(selectEmailGenerator.value || '').trim().toLowerCase() === GMAIL_ALIAS_GENERATOR) {
|
||||
if (!useGmail && String(selectEmailGenerator.value || '').trim().toLowerCase() === gmailAliasGenerator) {
|
||||
selectEmailGenerator.value = 'duck';
|
||||
}
|
||||
const selectedGenerator = getSelectedEmailGenerator();
|
||||
@@ -2761,20 +2964,24 @@ function updateMailProviderUI() {
|
||||
const hotmailServiceMode = getSelectedHotmailServiceMode();
|
||||
rowInbucketHost.style.display = useInbucket ? '' : 'none';
|
||||
rowInbucketMailbox.style.display = useInbucket ? '' : 'none';
|
||||
const useCustomEmailPool = useEmailGenerator && selectedGenerator === CUSTOM_EMAIL_POOL_GENERATOR;
|
||||
const useCustomEmailPool = useEmailGenerator && selectedGenerator === customEmailPoolGenerator;
|
||||
const useCloudflare = selectedGenerator === 'cloudflare';
|
||||
const useIcloud = selectedGenerator === 'icloud';
|
||||
const useCloudflareTempEmailGenerator = selectedGenerator === 'cloudflare-temp-email';
|
||||
const showCloudflareDomain = useEmailGenerator && useCloudflare;
|
||||
const showCloudflareTempEmailSettings = useCloudflareTempEmailProvider || (useEmailGenerator && useCloudflareTempEmailGenerator);
|
||||
const showCloudflareTempEmailReceiveMailbox = useCloudflareTempEmailProvider && !useCloudflareTempEmailGenerator;
|
||||
const showCloudflareTempEmailRandomSubdomainToggle = useEmailGenerator && useCloudflareTempEmailGenerator;
|
||||
const showCloudflareTempEmailDomain = useEmailGenerator && useCloudflareTempEmailGenerator;
|
||||
if (rowEmailGenerator) {
|
||||
rowEmailGenerator.style.display = useEmailGenerator ? '' : 'none';
|
||||
}
|
||||
if (rowCustomEmailPool) {
|
||||
if (typeof rowCustomEmailPool !== 'undefined' && rowCustomEmailPool) {
|
||||
rowCustomEmailPool.style.display = useCustomEmailPool ? '' : 'none';
|
||||
}
|
||||
if (cloudflareTempEmailSection) {
|
||||
cloudflareTempEmailSection.style.display = showCloudflareTempEmailSettings ? '' : 'none';
|
||||
}
|
||||
if (icloudSection) {
|
||||
const showIcloudSection = (useEmailGenerator && useIcloud) || useIcloudProvider;
|
||||
icloudSection.style.display = showIcloudSection ? '' : 'none';
|
||||
@@ -2796,6 +3003,9 @@ function updateMailProviderUI() {
|
||||
rowTempEmailAdminAuth.style.display = showCloudflareTempEmailSettings ? '' : 'none';
|
||||
rowTempEmailCustomAuth.style.display = showCloudflareTempEmailSettings ? '' : 'none';
|
||||
rowTempEmailReceiveMailbox.style.display = showCloudflareTempEmailReceiveMailbox ? '' : 'none';
|
||||
if (rowTempEmailRandomSubdomainToggle) {
|
||||
rowTempEmailRandomSubdomainToggle.style.display = showCloudflareTempEmailRandomSubdomainToggle ? '' : 'none';
|
||||
}
|
||||
rowTempEmailDomain.style.display = showCloudflareTempEmailDomain ? '' : 'none';
|
||||
const { domains: tempEmailDomains } = getCloudflareTempEmailDomainsFromState();
|
||||
if (showCloudflareTempEmailDomain) {
|
||||
@@ -2888,6 +3098,9 @@ function updateMailProviderUI() {
|
||||
if (autoHintText && showCloudflareTempEmailReceiveMailbox && !useCustomEmailPool) {
|
||||
autoHintText.textContent = '若注册邮箱会转发到 Cloudflare Temp Email,请在“邮件接收”中填写实际接收转发邮件的邮箱。';
|
||||
}
|
||||
if (autoHintText && showCloudflareTempEmailRandomSubdomainToggle && inputTempEmailUseRandomSubdomain?.checked) {
|
||||
autoHintText.textContent = '已启用随机子域名:扩展会按当前选中的 Temp 域名提交,并额外携带 enableRandomSubdomain;是否生效取决于后端 RANDOM_SUBDOMAIN_DOMAINS 配置。';
|
||||
}
|
||||
if (useHotmail) {
|
||||
inputEmail.value = getCurrentHotmailEmail();
|
||||
} else if (useLuckmail) {
|
||||
@@ -2896,7 +3109,9 @@ function updateMailProviderUI() {
|
||||
if (useCustomEmailPool) {
|
||||
syncRunCountFromCustomEmailPool();
|
||||
}
|
||||
inputRunCount.disabled = currentAutoRun.autoRunning || useCustomEmailPool;
|
||||
if (typeof inputRunCount !== 'undefined' && inputRunCount) {
|
||||
inputRunCount.disabled = currentAutoRun.autoRunning || useCustomEmailPool;
|
||||
}
|
||||
renderHotmailAccounts();
|
||||
if (useMail2925) {
|
||||
renderMail2925Accounts();
|
||||
@@ -2972,18 +3187,24 @@ async function saveCloudflareTempEmailDomainSettings(domains, activeDomain, opti
|
||||
|
||||
function updatePanelModeUI() {
|
||||
const useSub2Api = selectPanelMode.value === 'sub2api';
|
||||
rowVpsUrl.style.display = useSub2Api ? 'none' : '';
|
||||
rowVpsPassword.style.display = useSub2Api ? 'none' : '';
|
||||
rowLocalCpaStep9Mode.style.display = useSub2Api ? 'none' : '';
|
||||
const useCodex2Api = selectPanelMode.value === 'codex2api';
|
||||
const useCpa = !useSub2Api && !useCodex2Api;
|
||||
rowVpsUrl.style.display = useCpa ? '' : 'none';
|
||||
rowVpsPassword.style.display = useCpa ? '' : 'none';
|
||||
rowLocalCpaStep9Mode.style.display = useCpa ? '' : 'none';
|
||||
rowSub2ApiUrl.style.display = useSub2Api ? '' : 'none';
|
||||
rowSub2ApiEmail.style.display = useSub2Api ? '' : 'none';
|
||||
rowSub2ApiPassword.style.display = useSub2Api ? '' : 'none';
|
||||
rowSub2ApiGroup.style.display = useSub2Api ? '' : 'none';
|
||||
rowSub2ApiDefaultProxy.style.display = useSub2Api ? '' : 'none';
|
||||
rowCodex2ApiUrl.style.display = useCodex2Api ? '' : 'none';
|
||||
rowCodex2ApiAdminKey.style.display = useCodex2Api ? '' : 'none';
|
||||
|
||||
const step9Btn = document.querySelector('.step-btn[data-step-key="platform-verify"]');
|
||||
if (step9Btn) {
|
||||
step9Btn.textContent = useSub2Api ? 'SUB2API 回调验证' : 'CPA 回调验证';
|
||||
step9Btn.textContent = useSub2Api
|
||||
? 'SUB2API 回调验证'
|
||||
: (useCodex2Api ? 'Codex2API 回调验证' : 'CPA 回调验证');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3215,6 +3436,11 @@ async function fetchGeneratedEmail(options = {}) {
|
||||
generator: selectEmailGenerator.value,
|
||||
mailProvider: selectMailProvider.value,
|
||||
mail2925Mode: getSelectedMail2925Mode(),
|
||||
...(getSelectedEmailGenerator() === CUSTOM_EMAIL_POOL_GENERATOR
|
||||
? {
|
||||
customEmailPool: normalizeCustomEmailPoolEntries(inputCustomEmailPool?.value),
|
||||
}
|
||||
: {}),
|
||||
...buildManagedAliasBaseEmailPayload(),
|
||||
},
|
||||
});
|
||||
@@ -3884,6 +4110,14 @@ btnRepoHome?.addEventListener('click', () => {
|
||||
openRepositoryHomePage();
|
||||
});
|
||||
|
||||
btnCloudflareTempEmailUsageGuide?.addEventListener('click', () => {
|
||||
showCloudflareTempEmailUsageGuide();
|
||||
});
|
||||
|
||||
btnCloudflareTempEmailGithub?.addEventListener('click', () => {
|
||||
openCloudflareTempEmailRepositoryPage();
|
||||
});
|
||||
|
||||
extensionUpdateStatus?.addEventListener('click', () => {
|
||||
openReleaseListPage();
|
||||
});
|
||||
@@ -3928,12 +4162,18 @@ autoStartModal?.addEventListener('click', (event) => {
|
||||
btnAutoStartClose?.addEventListener('click', () => resolveModalChoice(null));
|
||||
|
||||
async function startAutoRunFromCurrentSettings() {
|
||||
let contributionSnapshot = null;
|
||||
try {
|
||||
await refreshContributionContentHint();
|
||||
contributionSnapshot = await refreshContributionContentHint();
|
||||
} catch (error) {
|
||||
console.warn('Failed to refresh contribution content hint before auto run:', error);
|
||||
}
|
||||
|
||||
const confirmedContributionUpdate = await maybeConfirmContributionUpdateBeforeAutoRun(contributionSnapshot);
|
||||
if (!confirmedContributionUpdate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof settingsDirty !== 'undefined' && settingsDirty && typeof saveSettings === 'function') {
|
||||
await saveSettings({ silent: true });
|
||||
}
|
||||
@@ -4393,6 +4633,22 @@ inputSub2ApiDefaultProxy.addEventListener('blur', () => {
|
||||
saveSettings({ silent: true }).catch(() => { });
|
||||
});
|
||||
|
||||
inputCodex2ApiUrl.addEventListener('input', () => {
|
||||
markSettingsDirty(true);
|
||||
scheduleSettingsAutoSave();
|
||||
});
|
||||
inputCodex2ApiUrl.addEventListener('blur', () => {
|
||||
saveSettings({ silent: true }).catch(() => { });
|
||||
});
|
||||
|
||||
inputCodex2ApiAdminKey.addEventListener('input', () => {
|
||||
markSettingsDirty(true);
|
||||
scheduleSettingsAutoSave();
|
||||
});
|
||||
inputCodex2ApiAdminKey.addEventListener('blur', () => {
|
||||
saveSettings({ silent: true }).catch(() => { });
|
||||
});
|
||||
|
||||
inputEmailPrefix.addEventListener('input', () => {
|
||||
maybeClearGeneratedAliasAfterEmailPrefixChange().catch(() => { });
|
||||
syncManagedAliasBaseEmailDraftFromInput();
|
||||
@@ -4528,6 +4784,13 @@ inputTempEmailReceiveMailbox.addEventListener('blur', () => {
|
||||
saveSettings({ silent: true }).catch(() => { });
|
||||
});
|
||||
|
||||
inputTempEmailUseRandomSubdomain?.addEventListener('change', () => {
|
||||
updateMailProviderUI();
|
||||
clearRegistrationEmail({ silent: true }).catch(() => { });
|
||||
markSettingsDirty(true);
|
||||
saveSettings({ silent: true }).catch(() => { });
|
||||
});
|
||||
|
||||
inputAutoSkipFailuresThreadIntervalMinutes.addEventListener('input', () => {
|
||||
markSettingsDirty(true);
|
||||
scheduleSettingsAutoSave();
|
||||
@@ -4750,9 +5013,19 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
||||
if (message.payload.cloudflareTempEmailReceiveMailbox !== undefined) {
|
||||
inputTempEmailReceiveMailbox.value = message.payload.cloudflareTempEmailReceiveMailbox || '';
|
||||
}
|
||||
if (message.payload.cloudflareTempEmailUseRandomSubdomain !== undefined && inputTempEmailUseRandomSubdomain) {
|
||||
inputTempEmailUseRandomSubdomain.checked = Boolean(message.payload.cloudflareTempEmailUseRandomSubdomain);
|
||||
}
|
||||
if (message.payload.cloudflareTempEmailDomain !== undefined || message.payload.cloudflareTempEmailDomains !== undefined) {
|
||||
renderCloudflareTempEmailDomainOptions(message.payload.cloudflareTempEmailDomain || latestState?.cloudflareTempEmailDomain || '');
|
||||
}
|
||||
if (
|
||||
message.payload.cloudflareTempEmailUseRandomSubdomain !== undefined
|
||||
|| message.payload.cloudflareTempEmailDomain !== undefined
|
||||
|| message.payload.cloudflareTempEmailDomains !== undefined
|
||||
) {
|
||||
updateMailProviderUI();
|
||||
}
|
||||
if (message.payload.currentHotmailAccountId !== undefined || message.payload.hotmailAccounts !== undefined) {
|
||||
renderHotmailAccounts();
|
||||
if (selectMailProvider.value === 'hotmail-api') {
|
||||
@@ -4948,7 +5221,12 @@ restoreState().then(() => {
|
||||
updatePanelModeUI();
|
||||
updateButtonStates();
|
||||
updateStatusDisplay(latestState);
|
||||
return refreshContributionContentHint();
|
||||
return refreshContributionContentHint()
|
||||
.catch((error) => {
|
||||
console.warn('Failed to refresh contribution content hint during initialization:', error);
|
||||
return null;
|
||||
})
|
||||
.then(() => maybeShowNewUserGuidePrompt());
|
||||
}).catch((err) => {
|
||||
console.error('Failed to initialize sidepanel state:', err);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user