Merge pull request #278 from qqqasdwx/feature/cloudflare-temp-email-fixed-subdomain
feat: 支持 Cloudflare Temp Email 固定子域
This commit is contained in:
+23
-3
@@ -371,6 +371,7 @@ const {
|
|||||||
} = self.LuckMailUtils;
|
} = self.LuckMailUtils;
|
||||||
const {
|
const {
|
||||||
DEFAULT_MAIL_PAGE_SIZE: CLOUDFLARE_TEMP_EMAIL_DEFAULT_PAGE_SIZE,
|
DEFAULT_MAIL_PAGE_SIZE: CLOUDFLARE_TEMP_EMAIL_DEFAULT_PAGE_SIZE,
|
||||||
|
buildCloudflareTempEmailEffectiveDomain,
|
||||||
buildCloudflareTempEmailHeaders,
|
buildCloudflareTempEmailHeaders,
|
||||||
getCloudflareTempEmailAddressFromResponse,
|
getCloudflareTempEmailAddressFromResponse,
|
||||||
joinCloudflareTempEmailUrl,
|
joinCloudflareTempEmailUrl,
|
||||||
@@ -379,6 +380,7 @@ const {
|
|||||||
normalizeCloudflareTempEmailDomain,
|
normalizeCloudflareTempEmailDomain,
|
||||||
normalizeCloudflareTempEmailDomains,
|
normalizeCloudflareTempEmailDomains,
|
||||||
normalizeCloudflareTempEmailMailApiMessages,
|
normalizeCloudflareTempEmailMailApiMessages,
|
||||||
|
normalizeCloudflareTempEmailSubdomainPrefix,
|
||||||
} = self.CloudflareTempEmailUtils;
|
} = self.CloudflareTempEmailUtils;
|
||||||
const {
|
const {
|
||||||
DEFAULT_MAIL_PAGE_SIZE: CLOUD_MAIL_DEFAULT_PAGE_SIZE,
|
DEFAULT_MAIL_PAGE_SIZE: CLOUD_MAIL_DEFAULT_PAGE_SIZE,
|
||||||
@@ -1428,6 +1430,8 @@ const PERSISTED_SETTING_DEFAULTS = {
|
|||||||
cloudflareTempEmailLookupMode: DEFAULT_CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE,
|
cloudflareTempEmailLookupMode: DEFAULT_CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE,
|
||||||
cloudflareTempEmailReceiveMailbox: '',
|
cloudflareTempEmailReceiveMailbox: '',
|
||||||
cloudflareTempEmailUseRandomSubdomain: false,
|
cloudflareTempEmailUseRandomSubdomain: false,
|
||||||
|
cloudflareTempEmailUseFixedSubdomain: false,
|
||||||
|
cloudflareTempEmailSubdomainPrefix: '',
|
||||||
cloudflareTempEmailDomain: '',
|
cloudflareTempEmailDomain: '',
|
||||||
cloudflareTempEmailDomains: [],
|
cloudflareTempEmailDomains: [],
|
||||||
cloudMailBaseUrl: '',
|
cloudMailBaseUrl: '',
|
||||||
@@ -2899,16 +2903,25 @@ function getHotmailServiceSettings(state = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getCloudflareTempEmailConfig(state = {}) {
|
function getCloudflareTempEmailConfig(state = {}) {
|
||||||
return {
|
const useFixedSubdomain = Boolean(state.cloudflareTempEmailUseFixedSubdomain);
|
||||||
|
const subdomainPrefix = normalizeCloudflareTempEmailSubdomainPrefix(state.cloudflareTempEmailSubdomainPrefix);
|
||||||
|
const domain = normalizeCloudflareTempEmailDomain(state.cloudflareTempEmailDomain);
|
||||||
|
const config = {
|
||||||
baseUrl: normalizeCloudflareTempEmailBaseUrl(state.cloudflareTempEmailBaseUrl),
|
baseUrl: normalizeCloudflareTempEmailBaseUrl(state.cloudflareTempEmailBaseUrl),
|
||||||
adminAuth: String(state.cloudflareTempEmailAdminAuth || ''),
|
adminAuth: String(state.cloudflareTempEmailAdminAuth || ''),
|
||||||
customAuth: String(state.cloudflareTempEmailCustomAuth || ''),
|
customAuth: String(state.cloudflareTempEmailCustomAuth || ''),
|
||||||
lookupMode: normalizeCloudflareTempEmailLookupMode(state.cloudflareTempEmailLookupMode),
|
lookupMode: normalizeCloudflareTempEmailLookupMode(state.cloudflareTempEmailLookupMode),
|
||||||
receiveMailbox: normalizeCloudflareTempEmailReceiveMailbox(state.cloudflareTempEmailReceiveMailbox),
|
receiveMailbox: normalizeCloudflareTempEmailReceiveMailbox(state.cloudflareTempEmailReceiveMailbox),
|
||||||
useRandomSubdomain: Boolean(state.cloudflareTempEmailUseRandomSubdomain),
|
useRandomSubdomain: useFixedSubdomain ? false : Boolean(state.cloudflareTempEmailUseRandomSubdomain),
|
||||||
domain: normalizeCloudflareTempEmailDomain(state.cloudflareTempEmailDomain),
|
useFixedSubdomain,
|
||||||
|
subdomainPrefix,
|
||||||
|
domain,
|
||||||
domains: normalizeCloudflareTempEmailDomains(state.cloudflareTempEmailDomains),
|
domains: normalizeCloudflareTempEmailDomains(state.cloudflareTempEmailDomains),
|
||||||
};
|
};
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
effectiveDomain: buildCloudflareTempEmailEffectiveDomain(config),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeCloudflareTempEmailReceiveMailbox(value = '') {
|
function normalizeCloudflareTempEmailReceiveMailbox(value = '') {
|
||||||
@@ -3402,6 +3415,7 @@ function normalizePersistentSettingValue(key, value) {
|
|||||||
case 'autoDeleteUsedIcloudAlias':
|
case 'autoDeleteUsedIcloudAlias':
|
||||||
case 'accountRunHistoryTextEnabled':
|
case 'accountRunHistoryTextEnabled':
|
||||||
case 'cloudflareTempEmailUseRandomSubdomain':
|
case 'cloudflareTempEmailUseRandomSubdomain':
|
||||||
|
case 'cloudflareTempEmailUseFixedSubdomain':
|
||||||
return Boolean(value);
|
return Boolean(value);
|
||||||
case 'icloudHostPreference':
|
case 'icloudHostPreference':
|
||||||
return normalizeIcloudHost(value) || 'auto';
|
return normalizeIcloudHost(value) || 'auto';
|
||||||
@@ -3455,6 +3469,8 @@ function normalizePersistentSettingValue(key, value) {
|
|||||||
return normalizeCloudflareTempEmailLookupMode(value);
|
return normalizeCloudflareTempEmailLookupMode(value);
|
||||||
case 'cloudflareTempEmailReceiveMailbox':
|
case 'cloudflareTempEmailReceiveMailbox':
|
||||||
return normalizeCloudflareTempEmailReceiveMailbox(value);
|
return normalizeCloudflareTempEmailReceiveMailbox(value);
|
||||||
|
case 'cloudflareTempEmailSubdomainPrefix':
|
||||||
|
return normalizeCloudflareTempEmailSubdomainPrefix(value);
|
||||||
case 'cloudflareTempEmailDomain':
|
case 'cloudflareTempEmailDomain':
|
||||||
return normalizeCloudflareTempEmailDomain(value);
|
return normalizeCloudflareTempEmailDomain(value);
|
||||||
case 'cloudflareTempEmailDomains':
|
case 'cloudflareTempEmailDomains':
|
||||||
@@ -3613,6 +3629,9 @@ function buildPersistentSettingsPayload(input = {}, options = {}) {
|
|||||||
}
|
}
|
||||||
payload.cloudflareTempEmailDomains = domains;
|
payload.cloudflareTempEmailDomains = domains;
|
||||||
}
|
}
|
||||||
|
if (payload.cloudflareTempEmailUseFixedSubdomain) {
|
||||||
|
payload.cloudflareTempEmailUseRandomSubdomain = false;
|
||||||
|
}
|
||||||
if (payload.cloudMailDomains) {
|
if (payload.cloudMailDomains) {
|
||||||
const domains = normalizeCloudMailDomains(payload.cloudMailDomains);
|
const domains = normalizeCloudMailDomains(payload.cloudMailDomains);
|
||||||
if (payload.cloudMailDomain && !domains.includes(payload.cloudMailDomain)) {
|
if (payload.cloudMailDomain && !domains.includes(payload.cloudMailDomain)) {
|
||||||
@@ -11840,6 +11859,7 @@ function getCurrentPayPalAccount(state = null) {
|
|||||||
const generatedEmailHelpers = self.MultiPageGeneratedEmailHelpers?.createGeneratedEmailHelpers({
|
const generatedEmailHelpers = self.MultiPageGeneratedEmailHelpers?.createGeneratedEmailHelpers({
|
||||||
addLog,
|
addLog,
|
||||||
buildGeneratedAliasEmail,
|
buildGeneratedAliasEmail,
|
||||||
|
buildCloudflareTempEmailEffectiveDomain,
|
||||||
buildCloudflareTempEmailHeaders,
|
buildCloudflareTempEmailHeaders,
|
||||||
CLOUDFLARE_TEMP_EMAIL_GENERATOR,
|
CLOUDFLARE_TEMP_EMAIL_GENERATOR,
|
||||||
CUSTOM_EMAIL_POOL_GENERATOR,
|
CUSTOM_EMAIL_POOL_GENERATOR,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
const {
|
const {
|
||||||
addLog,
|
addLog,
|
||||||
buildGeneratedAliasEmail,
|
buildGeneratedAliasEmail,
|
||||||
|
buildCloudflareTempEmailEffectiveDomain,
|
||||||
buildCloudflareTempEmailHeaders,
|
buildCloudflareTempEmailHeaders,
|
||||||
CLOUDFLARE_TEMP_EMAIL_GENERATOR,
|
CLOUDFLARE_TEMP_EMAIL_GENERATOR,
|
||||||
CUSTOM_EMAIL_POOL_GENERATOR,
|
CUSTOM_EMAIL_POOL_GENERATOR,
|
||||||
@@ -92,6 +93,12 @@
|
|||||||
if (requireDomain && !config.domain) {
|
if (requireDomain && !config.domain) {
|
||||||
throw new Error('Cloudflare Temp Email 域名为空或格式无效。');
|
throw new Error('Cloudflare Temp Email 域名为空或格式无效。');
|
||||||
}
|
}
|
||||||
|
if (config.useFixedSubdomain && !config.effectiveDomain && typeof buildCloudflareTempEmailEffectiveDomain === 'function') {
|
||||||
|
config.effectiveDomain = buildCloudflareTempEmailEffectiveDomain(config);
|
||||||
|
}
|
||||||
|
if (requireDomain && config.useFixedSubdomain && !config.effectiveDomain) {
|
||||||
|
throw new Error('Cloudflare Temp Email 固定子域前缀为空或格式无效。');
|
||||||
|
}
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,11 +166,16 @@
|
|||||||
requireDomain: true,
|
requireDomain: true,
|
||||||
});
|
});
|
||||||
const requestedName = String(options.localPart || options.name || '').trim().toLowerCase() || generateCloudflareAliasLocalPart();
|
const requestedName = String(options.localPart || options.name || '').trim().toLowerCase() || generateCloudflareAliasLocalPart();
|
||||||
|
const effectiveDomain = config.effectiveDomain || (
|
||||||
|
typeof buildCloudflareTempEmailEffectiveDomain === 'function'
|
||||||
|
? buildCloudflareTempEmailEffectiveDomain(config)
|
||||||
|
: config.domain
|
||||||
|
);
|
||||||
const payload = {
|
const payload = {
|
||||||
enablePrefix: true,
|
enablePrefix: true,
|
||||||
enableRandomSubdomain: Boolean(config.useRandomSubdomain),
|
enableRandomSubdomain: config.useFixedSubdomain ? false : Boolean(config.useRandomSubdomain),
|
||||||
name: requestedName,
|
name: requestedName,
|
||||||
domain: config.domain,
|
domain: effectiveDomain,
|
||||||
};
|
};
|
||||||
const result = await requestCloudflareTempEmailJson(config, '/admin/new_address', {
|
const result = await requestCloudflareTempEmailJson(config, '/admin/new_address', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|||||||
@@ -58,6 +58,29 @@
|
|||||||
return domains;
|
return domains;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeCloudflareTempEmailSubdomainPrefix(rawValue = '') {
|
||||||
|
let value = String(rawValue || '').trim().toLowerCase();
|
||||||
|
if (!value) return '';
|
||||||
|
value = value.replace(/^@+/, '');
|
||||||
|
value = value.replace(/^https?:\/\//, '');
|
||||||
|
value = value.replace(/\/.*$/, '');
|
||||||
|
value = value.replace(/^\.+|\.+$/g, '');
|
||||||
|
if (!/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(value)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildCloudflareTempEmailEffectiveDomain(config = {}) {
|
||||||
|
const domain = normalizeCloudflareTempEmailDomain(config.domain);
|
||||||
|
if (!domain) return '';
|
||||||
|
const useFixedSubdomain = Boolean(config.useFixedSubdomain);
|
||||||
|
const subdomainPrefix = normalizeCloudflareTempEmailSubdomainPrefix(config.subdomainPrefix);
|
||||||
|
if (!useFixedSubdomain) return domain;
|
||||||
|
if (!subdomainPrefix) return '';
|
||||||
|
return `${subdomainPrefix}.${domain}`;
|
||||||
|
}
|
||||||
|
|
||||||
function buildCloudflareTempEmailHeaders(config = {}, options = {}) {
|
function buildCloudflareTempEmailHeaders(config = {}, options = {}) {
|
||||||
const headers = {};
|
const headers = {};
|
||||||
const adminAuth = firstNonEmptyString([config.adminAuth, config.cloudflareTempEmailAdminAuth]);
|
const adminAuth = firstNonEmptyString([config.adminAuth, config.cloudflareTempEmailAdminAuth]);
|
||||||
@@ -563,6 +586,7 @@
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
DEFAULT_MAIL_PAGE_SIZE,
|
DEFAULT_MAIL_PAGE_SIZE,
|
||||||
|
buildCloudflareTempEmailEffectiveDomain,
|
||||||
buildCloudflareTempEmailHeaders,
|
buildCloudflareTempEmailHeaders,
|
||||||
getCloudflareTempEmailAddressFromResponse,
|
getCloudflareTempEmailAddressFromResponse,
|
||||||
joinCloudflareTempEmailUrl,
|
joinCloudflareTempEmailUrl,
|
||||||
@@ -572,5 +596,6 @@
|
|||||||
normalizeCloudflareTempEmailDomains,
|
normalizeCloudflareTempEmailDomains,
|
||||||
normalizeCloudflareTempEmailMailApiMessages,
|
normalizeCloudflareTempEmailMailApiMessages,
|
||||||
normalizeCloudflareTempEmailMessage,
|
normalizeCloudflareTempEmailMessage,
|
||||||
|
normalizeCloudflareTempEmailSubdomainPrefix,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@
|
|||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| 01 | 相关项目地址与部署说明 | `cpa`、`sub2api`、项目地址、部署前提、部署环境 | `docs/使用教程/分部分/01-相关项目地址与部署说明.md` |
|
| 01 | 相关项目地址与部署说明 | `cpa`、`sub2api`、项目地址、部署前提、部署环境 | `docs/使用教程/分部分/01-相关项目地址与部署说明.md` |
|
||||||
| 02 | 更新扩展 | `git pull`、`GitHub Desktop`、手动覆盖更新、扩展重新加载 | `docs/使用教程/分部分/02-更新扩展.md` |
|
| 02 | 更新扩展 | `git pull`、`GitHub Desktop`、手动覆盖更新、扩展重新加载 | `docs/使用教程/分部分/02-更新扩展.md` |
|
||||||
| 03 | Cloudflare Temp Email 使用说明 | `Cloudflare Temp Email`、`Admin Auth`、`Custom Auth`、随机子域、邮件接收 | `docs/使用教程/分部分/03-Cloudflare-Temp-Email-使用说明.md` |
|
| 03 | Cloudflare Temp Email 使用说明 | `Cloudflare Temp Email`、`Admin Auth`、`Custom Auth`、随机子域、固定子域、邮件接收 | `docs/使用教程/分部分/03-Cloudflare-Temp-Email-使用说明.md` |
|
||||||
| 04 | iCloud 隐私邮箱使用方法 | `iCloud+`、`隐藏邮件地址`、Apple ID、转发邮箱、刷新隐私邮箱 | `docs/使用教程/分部分/04-iCloud-隐私邮箱使用方法.md` |
|
| 04 | iCloud 隐私邮箱使用方法 | `iCloud+`、`隐藏邮件地址`、Apple ID、转发邮箱、刷新隐私邮箱 | `docs/使用教程/分部分/04-iCloud-隐私邮箱使用方法.md` |
|
||||||
| 05 | QQ 邮箱切换邮箱使用教程 | `QQ 邮箱`、英文邮箱、`Foxmail`、删除后重建 | `docs/使用教程/分部分/05-QQ-邮箱切换邮箱使用教程.md` |
|
| 05 | QQ 邮箱切换邮箱使用教程 | `QQ 邮箱`、英文邮箱、`Foxmail`、删除后重建 | `docs/使用教程/分部分/05-QQ-邮箱切换邮箱使用教程.md` |
|
||||||
| 06 | PayPal 注册与绑卡使用教程 | `PayPal`、注册、绑卡、钱包、身份认证、右上角通知 | `docs/使用教程/分部分/06-PayPal-注册与绑卡使用教程.md` |
|
| 06 | PayPal 注册与绑卡使用教程 | `PayPal`、注册、绑卡、钱包、身份认证、右上角通知 | `docs/使用教程/分部分/06-PayPal-注册与绑卡使用教程.md` |
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ AI 维护时默认按下面的范围归类:
|
|||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| 01 | 相关项目地址与部署说明 | `cpa`、`sub2api`、项目地址、部署前提、部署环境 | `docs/使用教程/分部分/01-相关项目地址与部署说明.md` |
|
| 01 | 相关项目地址与部署说明 | `cpa`、`sub2api`、项目地址、部署前提、部署环境 | `docs/使用教程/分部分/01-相关项目地址与部署说明.md` |
|
||||||
| 02 | 更新扩展 | `git pull`、`GitHub Desktop`、手动覆盖更新、扩展重新加载 | `docs/使用教程/分部分/02-更新扩展.md` |
|
| 02 | 更新扩展 | `git pull`、`GitHub Desktop`、手动覆盖更新、扩展重新加载 | `docs/使用教程/分部分/02-更新扩展.md` |
|
||||||
| 03 | Cloudflare Temp Email 使用说明 | `Cloudflare Temp Email`、`Admin Auth`、`Custom Auth`、随机子域、邮件接收 | `docs/使用教程/分部分/03-Cloudflare-Temp-Email-使用说明.md` |
|
| 03 | Cloudflare Temp Email 使用说明 | `Cloudflare Temp Email`、`Admin Auth`、`Custom Auth`、随机子域、固定子域、邮件接收 | `docs/使用教程/分部分/03-Cloudflare-Temp-Email-使用说明.md` |
|
||||||
| 04 | iCloud 隐私邮箱使用方法 | `iCloud+`、`隐藏邮件地址`、Apple ID、转发邮箱、刷新隐私邮箱 | `docs/使用教程/分部分/04-iCloud-隐私邮箱使用方法.md` |
|
| 04 | iCloud 隐私邮箱使用方法 | `iCloud+`、`隐藏邮件地址`、Apple ID、转发邮箱、刷新隐私邮箱 | `docs/使用教程/分部分/04-iCloud-隐私邮箱使用方法.md` |
|
||||||
| 05 | QQ 邮箱切换邮箱使用教程 | `QQ 邮箱`、英文邮箱、`Foxmail`、删除后重建 | `docs/使用教程/分部分/05-QQ-邮箱切换邮箱使用教程.md` |
|
| 05 | QQ 邮箱切换邮箱使用教程 | `QQ 邮箱`、英文邮箱、`Foxmail`、删除后重建 | `docs/使用教程/分部分/05-QQ-邮箱切换邮箱使用教程.md` |
|
||||||
| 06 | PayPal 注册与绑卡使用教程 | `PayPal`、注册、绑卡、钱包、身份认证、右上角通知 | `docs/使用教程/分部分/06-PayPal-注册与绑卡使用教程.md` |
|
| 06 | PayPal 注册与绑卡使用教程 | `PayPal`、注册、绑卡、钱包、身份认证、右上角通知 | `docs/使用教程/分部分/06-PayPal-注册与绑卡使用教程.md` |
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
## 部分信息
|
## 部分信息
|
||||||
|
|
||||||
- `section_slug`: `cloudflare-temp-email`
|
- `section_slug`: `cloudflare-temp-email`
|
||||||
- `适用主题`: `Cloudflare Temp Email`、`Admin Auth`、`Custom Auth`、随机子域、邮件接收
|
- `适用主题`: `Cloudflare Temp Email`、`Admin Auth`、`Custom Auth`、随机子域、固定子域、邮件接收
|
||||||
- `维护方式`: `直接更新本文件`
|
- `维护方式`: `直接更新本文件`
|
||||||
|
|
||||||
## 适用场景
|
## 适用场景
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
- 一个可用的 `Cloudflare Temp Email` 后端地址
|
- 一个可用的 `Cloudflare Temp Email` 后端地址
|
||||||
- 如果要使用随机子域,对应域名解析已经提前配置好
|
- 如果要使用随机子域,对应域名解析已经提前配置好
|
||||||
|
- 如果要使用固定子域,后端已经开启 `ENABLE_CREATE_ADDRESS_SUBDOMAIN_MATCH`
|
||||||
- 后端的 `admin auth`
|
- 后端的 `admin auth`
|
||||||
- 如果站点额外设置了访问密码,对应的访问认证信息
|
- 如果站点额外设置了访问密码,对应的访问认证信息
|
||||||
- 一个真正用于接收转发邮件的收件邮箱
|
- 一个真正用于接收转发邮件的收件邮箱
|
||||||
@@ -52,23 +53,39 @@
|
|||||||
|
|
||||||
### 第五步:配置 `Temp 域名`
|
### 第五步:配置 `Temp 域名`
|
||||||
|
|
||||||
这里填写允许创建邮箱的基础域名。
|
这里选择允许创建邮箱的基础域名。
|
||||||
即使你开启了 `随机子域`,这里仍然填写基础域名,而不是随机出来的子域名。
|
即使你开启了 `随机子域` 或 `固定子域`,这里仍然选择基础域名,而不是最终子域名。
|
||||||
|
|
||||||
### 第六步:按需开启 `随机子域`
|
### 第六步:按需开启 `随机子域`
|
||||||
|
|
||||||
只有在 `邮箱生成 = Cloudflare Temp Email` 时,这一项才会生效。
|
只有在 `邮箱生成 = Cloudflare Temp Email` 时,这一项才会生效。
|
||||||
|
`随机子域` 与 `固定子域` 互斥,只能开启其中一个。
|
||||||
启用前需要先确认:
|
启用前需要先确认:
|
||||||
|
|
||||||
- 后端已经配置 `RANDOM_SUBDOMAIN_DOMAINS`
|
- 后端已经配置 `RANDOM_SUBDOMAIN_DOMAINS`
|
||||||
- Cloudflare DNS 已经设置 `MX *`
|
- Cloudflare DNS 已经设置 `MX *`
|
||||||
|
|
||||||
### 第七步:作为 `邮箱服务` 时填写 `邮件接收`
|
### 第七步:按需开启 `固定子域`
|
||||||
|
|
||||||
|
只有在 `邮箱生成 = Cloudflare Temp Email` 时,这一项才会生效。
|
||||||
|
开启 `固定子域` 后再填写 `子域前缀`,例如:
|
||||||
|
|
||||||
|
- `子域前缀 = a`
|
||||||
|
- `Temp 域名 = b.com`
|
||||||
|
- 最终提交给后端的域名是 `a.b.com`
|
||||||
|
|
||||||
|
切换 `Temp 域名` 后,子域前缀会继续复用。例如选择 `c.com` 后会生成 `xxx@a.c.com`。
|
||||||
|
启用前需要先确认:
|
||||||
|
|
||||||
|
- 后端已经开启 `ENABLE_CREATE_ADDRESS_SUBDOMAIN_MATCH`
|
||||||
|
- 目标子域名的邮件解析已经准备好,或通配 MX 可以覆盖该子域
|
||||||
|
|
||||||
|
### 第八步:作为 `邮箱服务` 时填写 `邮件接收`
|
||||||
|
|
||||||
如果 `邮箱服务` 也选了 `Cloudflare Temp Email`,还需要填写真正的收件邮箱。
|
如果 `邮箱服务` 也选了 `Cloudflare Temp Email`,还需要填写真正的收件邮箱。
|
||||||
后续转发邮件会送到这里。
|
后续转发邮件会送到这里。
|
||||||
|
|
||||||
### 第八步:查看后端搭建参考
|
### 第九步:查看后端搭建参考
|
||||||
|
|
||||||
如果你还没有部署后端,可以参考:
|
如果你还没有部署后端,可以参考:
|
||||||
|
|
||||||
@@ -88,8 +105,14 @@
|
|||||||
|
|
||||||
通常是因为后端没有配置 `RANDOM_SUBDOMAIN_DOMAINS`,或者 Cloudflare DNS 没有完成 `MX *` 设置。
|
通常是因为后端没有配置 `RANDOM_SUBDOMAIN_DOMAINS`,或者 Cloudflare DNS 没有完成 `MX *` 设置。
|
||||||
|
|
||||||
|
### 为什么固定子域没有生效?
|
||||||
|
|
||||||
|
通常是因为后端没有开启 `ENABLE_CREATE_ADDRESS_SUBDOMAIN_MATCH`,或者 `子域前缀` 不符合单段 DNS label 规则。
|
||||||
|
前缀只能使用小写字母、数字和中横线,不能包含点号、下划线,也不能以中横线开头或结尾。
|
||||||
|
|
||||||
## 注意事项
|
## 注意事项
|
||||||
|
|
||||||
- 如果同时把它用作 `邮箱生成` 和 `邮箱服务`,要把两边相关字段都检查一遍
|
- 如果同时把它用作 `邮箱生成` 和 `邮箱服务`,要把两边相关字段都检查一遍
|
||||||
- `Custom Auth` 只有额外访问密码场景才需要填写
|
- `Custom Auth` 只有额外访问密码场景才需要填写
|
||||||
- 开启随机子域前,先确认后端和 DNS 已经准备好
|
- `随机子域` 与 `固定子域` 互斥,开启固定子域时会自动关闭随机子域
|
||||||
|
- 开启随机子域或固定子域前,先确认后端和 DNS 已经准备好
|
||||||
|
|||||||
@@ -1378,6 +1378,10 @@ header {
|
|||||||
}
|
}
|
||||||
.data-input::placeholder { color: var(--text-muted); }
|
.data-input::placeholder { color: var(--text-muted); }
|
||||||
.data-input:focus { border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-soft); }
|
.data-input:focus { border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-soft); }
|
||||||
|
.data-input.is-invalid {
|
||||||
|
border-color: var(--red);
|
||||||
|
box-shadow: 0 0 0 3px var(--red-soft);
|
||||||
|
}
|
||||||
|
|
||||||
.data-textarea {
|
.data-textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -1490,6 +1494,38 @@ header {
|
|||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.temp-email-subdomain-mode-wrap,
|
||||||
|
.temp-email-subdomain-prefix-wrap {
|
||||||
|
align-items: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.temp-email-subdomain-mode-wrap .choice-group,
|
||||||
|
.temp-email-subdomain-prefix-wrap .data-input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.temp-email-subdomain-mode-wrap .setting-caption {
|
||||||
|
white-space: normal;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-feedback {
|
||||||
|
min-height: 15px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.25;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-feedback.is-error {
|
||||||
|
color: var(--red);
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-feedback-muted {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
#btn-fetch-email,
|
#btn-fetch-email,
|
||||||
#btn-save-settings {
|
#btn-save-settings {
|
||||||
padding-inline: 10px;
|
padding-inline: 10px;
|
||||||
|
|||||||
+25
-13
@@ -812,22 +812,34 @@
|
|||||||
<input type="text" id="input-temp-email-receive-mailbox" class="data-input"
|
<input type="text" id="input-temp-email-receive-mailbox" class="data-input"
|
||||||
placeholder="用于接收转发邮件的邮箱,例如 1@email.example.com" />
|
placeholder="用于接收转发邮件的邮箱,例如 1@email.example.com" />
|
||||||
</div>
|
</div>
|
||||||
<div class="data-row" id="row-temp-email-random-subdomain-toggle" style="display:none;">
|
<div class="data-row" id="row-temp-email-subdomain-mode" style="display:none;">
|
||||||
<span class="data-label">随机子域</span>
|
<span class="data-label">子域模式</span>
|
||||||
<div class="data-inline">
|
<div class="data-inline temp-email-subdomain-mode-wrap">
|
||||||
<label class="toggle-switch" for="input-temp-email-use-random-subdomain"
|
<input type="checkbox" id="input-temp-email-use-random-subdomain" hidden />
|
||||||
title="依赖后端 RANDOM_SUBDOMAIN_DOMAINS 配置">
|
<input type="checkbox" id="input-temp-email-use-fixed-subdomain" hidden />
|
||||||
<input type="checkbox" id="input-temp-email-use-random-subdomain" />
|
<div id="temp-email-subdomain-mode-group" class="choice-group" role="group"
|
||||||
<span class="toggle-switch-track" aria-hidden="true">
|
aria-label="Cloudflare Temp Email 子域模式">
|
||||||
<span class="toggle-switch-thumb"></span>
|
<button type="button" class="choice-btn" data-temp-email-subdomain-mode="none">不使用</button>
|
||||||
</span>
|
<button type="button" class="choice-btn" data-temp-email-subdomain-mode="random"
|
||||||
<span>启用</span>
|
title="依赖后端 RANDOM_SUBDOMAIN_DOMAINS 配置">随机</button>
|
||||||
</label>
|
<button type="button" class="choice-btn" data-temp-email-subdomain-mode="fixed"
|
||||||
<span class="setting-caption">依赖后端 RANDOM_SUBDOMAIN_DOMAINS</span>
|
title="依赖后端 ENABLE_CREATE_ADDRESS_SUBDOMAIN_MATCH 配置">固定</button>
|
||||||
|
</div>
|
||||||
|
<span id="temp-email-subdomain-mode-caption" class="setting-caption setting-caption-left">按基础域名直接生成</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="data-row" id="row-temp-email-fixed-subdomain-prefix" style="display:none;">
|
||||||
|
<span class="data-label">子域前缀</span>
|
||||||
|
<div class="data-inline temp-email-subdomain-prefix-wrap">
|
||||||
|
<input type="text" id="input-temp-email-subdomain-prefix" class="data-input"
|
||||||
|
placeholder="例如 team;基础域名为 mail.example.com 时生成 xxx@team.mail.example.com"
|
||||||
|
aria-describedby="temp-email-subdomain-prefix-feedback temp-email-effective-domain-preview" />
|
||||||
|
<span id="temp-email-subdomain-prefix-feedback" class="field-feedback" aria-live="polite"></span>
|
||||||
|
<span id="temp-email-effective-domain-preview" class="field-feedback field-feedback-muted"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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" id="label-temp-email-domain">Temp 域名</span>
|
||||||
<div class="data-inline">
|
<div class="data-inline">
|
||||||
<input type="hidden" id="select-temp-email-domain" value="" />
|
<input type="hidden" id="select-temp-email-domain" value="" />
|
||||||
<div id="temp-email-domain-picker" class="editable-list-picker">
|
<div id="temp-email-domain-picker" class="editable-list-picker">
|
||||||
|
|||||||
+231
-14
@@ -297,9 +297,17 @@ const rowTempEmailLookupMode = document.getElementById('row-temp-email-lookup-mo
|
|||||||
const tempEmailLookupModeButtons = Array.from(document.querySelectorAll('[data-temp-email-lookup-mode]'));
|
const tempEmailLookupModeButtons = Array.from(document.querySelectorAll('[data-temp-email-lookup-mode]'));
|
||||||
const rowTempEmailReceiveMailbox = document.getElementById('row-temp-email-receive-mailbox');
|
const rowTempEmailReceiveMailbox = document.getElementById('row-temp-email-receive-mailbox');
|
||||||
const inputTempEmailReceiveMailbox = document.getElementById('input-temp-email-receive-mailbox');
|
const inputTempEmailReceiveMailbox = document.getElementById('input-temp-email-receive-mailbox');
|
||||||
const rowTempEmailRandomSubdomainToggle = document.getElementById('row-temp-email-random-subdomain-toggle');
|
const rowTempEmailSubdomainMode = document.getElementById('row-temp-email-subdomain-mode');
|
||||||
|
const tempEmailSubdomainModeButtons = Array.from(document.querySelectorAll('[data-temp-email-subdomain-mode]'));
|
||||||
|
const tempEmailSubdomainModeCaption = document.getElementById('temp-email-subdomain-mode-caption');
|
||||||
const inputTempEmailUseRandomSubdomain = document.getElementById('input-temp-email-use-random-subdomain');
|
const inputTempEmailUseRandomSubdomain = document.getElementById('input-temp-email-use-random-subdomain');
|
||||||
|
const inputTempEmailUseFixedSubdomain = document.getElementById('input-temp-email-use-fixed-subdomain');
|
||||||
|
const rowTempEmailFixedSubdomainPrefix = document.getElementById('row-temp-email-fixed-subdomain-prefix');
|
||||||
|
const inputTempEmailSubdomainPrefix = document.getElementById('input-temp-email-subdomain-prefix');
|
||||||
|
const tempEmailSubdomainPrefixFeedback = document.getElementById('temp-email-subdomain-prefix-feedback');
|
||||||
|
const tempEmailEffectiveDomainPreview = document.getElementById('temp-email-effective-domain-preview');
|
||||||
const rowTempEmailDomain = document.getElementById('row-temp-email-domain');
|
const rowTempEmailDomain = document.getElementById('row-temp-email-domain');
|
||||||
|
const labelTempEmailDomain = document.getElementById('label-temp-email-domain');
|
||||||
const selectTempEmailDomain = document.getElementById('select-temp-email-domain');
|
const selectTempEmailDomain = document.getElementById('select-temp-email-domain');
|
||||||
const tempEmailDomainPickerRoot = document.getElementById('temp-email-domain-picker');
|
const tempEmailDomainPickerRoot = document.getElementById('temp-email-domain-picker');
|
||||||
const btnTempEmailDomainMenu = document.getElementById('btn-temp-email-domain-menu');
|
const btnTempEmailDomainMenu = document.getElementById('btn-temp-email-domain-menu');
|
||||||
@@ -825,6 +833,10 @@ const DEFAULT_MAIL_2925_MODE = MAIL_2925_MODE_PROVIDE;
|
|||||||
const CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE_RECEIVE_MAILBOX = 'receive-mailbox';
|
const CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE_RECEIVE_MAILBOX = 'receive-mailbox';
|
||||||
const CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE_REGISTRATION_EMAIL = 'registration-email';
|
const CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE_REGISTRATION_EMAIL = 'registration-email';
|
||||||
const DEFAULT_CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE = CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE_RECEIVE_MAILBOX;
|
const DEFAULT_CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE = CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE_RECEIVE_MAILBOX;
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_NONE = 'none';
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM = 'random';
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED = 'fixed';
|
||||||
|
const DEFAULT_CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE = CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_NONE;
|
||||||
const NEW_USER_GUIDE_PROMPT_DISMISSED_STORAGE_KEY = 'multipage-new-user-guide-prompt-dismissed';
|
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_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 AUTO_RUN_FALLBACK_RISK_PROMPT_DISMISSED_STORAGE_KEY = 'multipage-auto-run-fallback-risk-prompt-dismissed';
|
||||||
@@ -4092,6 +4104,54 @@ function normalizeCloudflareTempEmailDomainValue(value = '') {
|
|||||||
return normalizeCloudflareDomainValue(value);
|
return normalizeCloudflareDomainValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeCloudflareTempEmailSubdomainPrefixValue(value = '') {
|
||||||
|
let normalized = String(value || '').trim().toLowerCase();
|
||||||
|
if (!normalized) return '';
|
||||||
|
normalized = normalized.replace(/^@+/, '');
|
||||||
|
normalized = normalized.replace(/^https?:\/\//, '');
|
||||||
|
normalized = normalized.replace(/\/.*$/, '');
|
||||||
|
normalized = normalized.replace(/^\.+|\.+$/g, '');
|
||||||
|
if (!/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(normalized)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildCloudflareTempEmailEffectiveDomainValue(domain = '', subdomainPrefix = '', options = {}) {
|
||||||
|
const normalizedDomain = normalizeCloudflareTempEmailDomainValue(domain);
|
||||||
|
if (!normalizedDomain) return '';
|
||||||
|
const normalizedPrefix = normalizeCloudflareTempEmailSubdomainPrefixValue(subdomainPrefix);
|
||||||
|
if (options.requirePrefix && !normalizedPrefix) return '';
|
||||||
|
return normalizedPrefix ? `${normalizedPrefix}.${normalizedDomain}` : normalizedDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCloudflareTempEmailSubdomainPrefixValidation(value = '') {
|
||||||
|
const raw = String(value || '').trim();
|
||||||
|
if (!raw) {
|
||||||
|
return {
|
||||||
|
raw,
|
||||||
|
normalized: '',
|
||||||
|
valid: false,
|
||||||
|
message: '请填写子域前缀',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const normalized = normalizeCloudflareTempEmailSubdomainPrefixValue(raw);
|
||||||
|
if (!normalized) {
|
||||||
|
return {
|
||||||
|
raw,
|
||||||
|
normalized: '',
|
||||||
|
valid: false,
|
||||||
|
message: '仅支持 1-63 位字母、数字或中划线,且不能以中划线开头或结尾',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
raw,
|
||||||
|
normalized,
|
||||||
|
valid: true,
|
||||||
|
message: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeCloudflareTempEmailDomains(values = []) {
|
function normalizeCloudflareTempEmailDomains(values = []) {
|
||||||
const seen = new Set();
|
const seen = new Set();
|
||||||
const domains = [];
|
const domains = [];
|
||||||
@@ -4181,8 +4241,17 @@ function applyCloudflareTempEmailSettingsState(state = {}) {
|
|||||||
inputTempEmailCustomAuth.value = state?.cloudflareTempEmailCustomAuth || '';
|
inputTempEmailCustomAuth.value = state?.cloudflareTempEmailCustomAuth || '';
|
||||||
inputTempEmailReceiveMailbox.value = state?.cloudflareTempEmailReceiveMailbox || '';
|
inputTempEmailReceiveMailbox.value = state?.cloudflareTempEmailReceiveMailbox || '';
|
||||||
setCloudflareTempEmailLookupMode(state?.cloudflareTempEmailLookupMode);
|
setCloudflareTempEmailLookupMode(state?.cloudflareTempEmailLookupMode);
|
||||||
if (inputTempEmailUseRandomSubdomain) {
|
setCloudflareTempEmailSubdomainMode(
|
||||||
inputTempEmailUseRandomSubdomain.checked = Boolean(state?.cloudflareTempEmailUseRandomSubdomain);
|
state?.cloudflareTempEmailUseFixedSubdomain
|
||||||
|
? CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED
|
||||||
|
: (state?.cloudflareTempEmailUseRandomSubdomain
|
||||||
|
? CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM
|
||||||
|
: CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_NONE)
|
||||||
|
);
|
||||||
|
if (inputTempEmailSubdomainPrefix) {
|
||||||
|
inputTempEmailSubdomainPrefix.value = normalizeCloudflareTempEmailSubdomainPrefixValue(
|
||||||
|
state?.cloudflareTempEmailSubdomainPrefix || ''
|
||||||
|
);
|
||||||
}
|
}
|
||||||
renderCloudflareTempEmailDomainOptions(state?.cloudflareTempEmailDomain || '');
|
renderCloudflareTempEmailDomainOptions(state?.cloudflareTempEmailDomain || '');
|
||||||
setCloudflareTempEmailDomainEditMode(false, { clearInput: true });
|
setCloudflareTempEmailDomainEditMode(false, { clearInput: true });
|
||||||
@@ -4233,6 +4302,7 @@ function collectSettingsPayload() {
|
|||||||
const selectedCloudflareTempEmailDomain = normalizeCloudflareTempEmailDomainValue(
|
const selectedCloudflareTempEmailDomain = normalizeCloudflareTempEmailDomainValue(
|
||||||
!cloudflareTempEmailDomainEditMode ? selectTempEmailDomain.value : tempEmailActiveDomain
|
!cloudflareTempEmailDomainEditMode ? selectTempEmailDomain.value : tempEmailActiveDomain
|
||||||
) || tempEmailActiveDomain;
|
) || tempEmailActiveDomain;
|
||||||
|
const cloudflareTempEmailSubdomainMode = getSelectedCloudflareTempEmailSubdomainMode();
|
||||||
const normalizeCloudMailBaseUrlInput = typeof normalizeCloudMailBaseUrlValue === 'function'
|
const normalizeCloudMailBaseUrlInput = typeof normalizeCloudMailBaseUrlValue === 'function'
|
||||||
? normalizeCloudMailBaseUrlValue
|
? normalizeCloudMailBaseUrlValue
|
||||||
: normalizeCloudflareTempEmailBaseUrlValue;
|
: normalizeCloudflareTempEmailBaseUrlValue;
|
||||||
@@ -5128,7 +5198,13 @@ function collectSettingsPayload() {
|
|||||||
? getSelectedCloudflareTempEmailLookupMode()
|
? getSelectedCloudflareTempEmailLookupMode()
|
||||||
: 'receive-mailbox',
|
: 'receive-mailbox',
|
||||||
cloudflareTempEmailReceiveMailbox: normalizeCloudflareTempEmailReceiveMailboxValue(inputTempEmailReceiveMailbox.value),
|
cloudflareTempEmailReceiveMailbox: normalizeCloudflareTempEmailReceiveMailboxValue(inputTempEmailReceiveMailbox.value),
|
||||||
cloudflareTempEmailUseRandomSubdomain: Boolean(inputTempEmailUseRandomSubdomain?.checked),
|
cloudflareTempEmailUseRandomSubdomain: cloudflareTempEmailSubdomainMode
|
||||||
|
=== CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM,
|
||||||
|
cloudflareTempEmailUseFixedSubdomain: cloudflareTempEmailSubdomainMode
|
||||||
|
=== CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED,
|
||||||
|
cloudflareTempEmailSubdomainPrefix: normalizeCloudflareTempEmailSubdomainPrefixValue(
|
||||||
|
inputTempEmailSubdomainPrefix?.value || ''
|
||||||
|
),
|
||||||
cloudflareTempEmailDomain: selectedCloudflareTempEmailDomain,
|
cloudflareTempEmailDomain: selectedCloudflareTempEmailDomain,
|
||||||
cloudflareTempEmailDomains: tempEmailDomains,
|
cloudflareTempEmailDomains: tempEmailDomains,
|
||||||
cloudMailBaseUrl: normalizeCloudMailBaseUrlInput((typeof inputCloudMailBaseUrl !== 'undefined' && inputCloudMailBaseUrl) ? inputCloudMailBaseUrl.value : ''),
|
cloudMailBaseUrl: normalizeCloudMailBaseUrlInput((typeof inputCloudMailBaseUrl !== 'undefined' && inputCloudMailBaseUrl) ? inputCloudMailBaseUrl.value : ''),
|
||||||
@@ -5209,6 +5285,17 @@ function normalizeCloudflareTempEmailLookupMode(value = '') {
|
|||||||
: DEFAULT_CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE;
|
: DEFAULT_CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeCloudflareTempEmailSubdomainMode(value = '') {
|
||||||
|
const normalized = String(value || '').trim().toLowerCase();
|
||||||
|
if (normalized === CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM) {
|
||||||
|
return CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM;
|
||||||
|
}
|
||||||
|
if (normalized === CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED) {
|
||||||
|
return CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED;
|
||||||
|
}
|
||||||
|
return DEFAULT_CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeHotmailServiceMode(value = '') {
|
function normalizeHotmailServiceMode(value = '') {
|
||||||
if (typeof normalizeHotmailServiceModeFromUtils === 'function') {
|
if (typeof normalizeHotmailServiceModeFromUtils === 'function') {
|
||||||
return normalizeHotmailServiceModeFromUtils(value);
|
return normalizeHotmailServiceModeFromUtils(value);
|
||||||
@@ -8842,6 +8929,37 @@ function setCloudflareTempEmailLookupMode(mode) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function syncCloudflareTempEmailSubdomainModeButtons(mode) {
|
||||||
|
const resolvedMode = normalizeCloudflareTempEmailSubdomainMode(mode);
|
||||||
|
tempEmailSubdomainModeButtons.forEach((button) => {
|
||||||
|
const active = button.dataset.tempEmailSubdomainMode === resolvedMode;
|
||||||
|
button.classList.toggle('is-active', active);
|
||||||
|
button.setAttribute('aria-pressed', String(active));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSelectedCloudflareTempEmailSubdomainMode() {
|
||||||
|
if (inputTempEmailUseFixedSubdomain?.checked) {
|
||||||
|
return CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED;
|
||||||
|
}
|
||||||
|
if (inputTempEmailUseRandomSubdomain?.checked) {
|
||||||
|
return CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM;
|
||||||
|
}
|
||||||
|
const activeButton = tempEmailSubdomainModeButtons.find((button) => button.classList.contains('is-active'));
|
||||||
|
return normalizeCloudflareTempEmailSubdomainMode(activeButton?.dataset.tempEmailSubdomainMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCloudflareTempEmailSubdomainMode(mode) {
|
||||||
|
const resolvedMode = normalizeCloudflareTempEmailSubdomainMode(mode);
|
||||||
|
if (inputTempEmailUseRandomSubdomain) {
|
||||||
|
inputTempEmailUseRandomSubdomain.checked = resolvedMode === CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM;
|
||||||
|
}
|
||||||
|
if (inputTempEmailUseFixedSubdomain) {
|
||||||
|
inputTempEmailUseFixedSubdomain.checked = resolvedMode === CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED;
|
||||||
|
}
|
||||||
|
syncCloudflareTempEmailSubdomainModeButtons(resolvedMode);
|
||||||
|
}
|
||||||
|
|
||||||
function getSelectedHotmailServiceMode() {
|
function getSelectedHotmailServiceMode() {
|
||||||
const activeButton = hotmailServiceModeButtons.find((button) => button.classList.contains('is-active'));
|
const activeButton = hotmailServiceModeButtons.find((button) => button.classList.contains('is-active'));
|
||||||
return normalizeHotmailServiceMode(activeButton?.dataset.hotmailServiceMode);
|
return normalizeHotmailServiceMode(activeButton?.dataset.hotmailServiceMode);
|
||||||
@@ -12958,8 +13076,26 @@ function updateMailProviderUI() {
|
|||||||
const isIcloudComCnHost = selectedIcloudHost === 'icloud.com.cn';
|
const isIcloudComCnHost = selectedIcloudHost === 'icloud.com.cn';
|
||||||
const showIcloudTargetMailboxType = useIcloudProvider;
|
const showIcloudTargetMailboxType = useIcloudProvider;
|
||||||
const showIcloudForwardMailProvider = useIcloudProvider && icloudTargetMailboxType === 'forward-mailbox';
|
const showIcloudForwardMailProvider = useIcloudProvider && icloudTargetMailboxType === 'forward-mailbox';
|
||||||
const showCloudflareTempEmailRandomSubdomainToggle = useEmailGenerator && useCloudflareTempEmailGenerator;
|
const showCloudflareTempEmailSubdomainMode = useEmailGenerator && useCloudflareTempEmailGenerator;
|
||||||
|
const cloudflareTempEmailSubdomainMode = getSelectedCloudflareTempEmailSubdomainMode();
|
||||||
|
syncCloudflareTempEmailSubdomainModeButtons(cloudflareTempEmailSubdomainMode);
|
||||||
|
const showCloudflareTempEmailFixedSubdomainPrefix = showCloudflareTempEmailSubdomainMode
|
||||||
|
&& cloudflareTempEmailSubdomainMode === CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED;
|
||||||
const showCloudflareTempEmailDomain = useEmailGenerator && useCloudflareTempEmailGenerator;
|
const showCloudflareTempEmailDomain = useEmailGenerator && useCloudflareTempEmailGenerator;
|
||||||
|
const { domains: tempEmailDomains, activeDomain: tempEmailActiveDomain } = getCloudflareTempEmailDomainsFromState();
|
||||||
|
const selectedTempEmailDomain = normalizeCloudflareTempEmailDomainValue(
|
||||||
|
selectTempEmailDomain?.value || tempEmailActiveDomain
|
||||||
|
) || tempEmailActiveDomain;
|
||||||
|
const fixedSubdomainValidation = getCloudflareTempEmailSubdomainPrefixValidation(
|
||||||
|
inputTempEmailSubdomainPrefix?.value || ''
|
||||||
|
);
|
||||||
|
const fixedSubdomainConfigInvalid = showCloudflareTempEmailFixedSubdomainPrefix
|
||||||
|
&& !fixedSubdomainValidation.valid;
|
||||||
|
const tempEmailEffectiveDomain = buildCloudflareTempEmailEffectiveDomainValue(
|
||||||
|
selectedTempEmailDomain,
|
||||||
|
fixedSubdomainValidation.normalized,
|
||||||
|
{ requirePrefix: true }
|
||||||
|
);
|
||||||
if (rowEmailGenerator) {
|
if (rowEmailGenerator) {
|
||||||
rowEmailGenerator.style.display = useEmailGenerator ? '' : 'none';
|
rowEmailGenerator.style.display = useEmailGenerator ? '' : 'none';
|
||||||
}
|
}
|
||||||
@@ -13015,11 +13151,38 @@ function updateMailProviderUI() {
|
|||||||
rowTempEmailLookupMode.style.display = showCloudflareTempEmailLookupMode ? '' : 'none';
|
rowTempEmailLookupMode.style.display = showCloudflareTempEmailLookupMode ? '' : 'none';
|
||||||
}
|
}
|
||||||
rowTempEmailReceiveMailbox.style.display = showCloudflareTempEmailReceiveMailbox ? '' : 'none';
|
rowTempEmailReceiveMailbox.style.display = showCloudflareTempEmailReceiveMailbox ? '' : 'none';
|
||||||
if (rowTempEmailRandomSubdomainToggle) {
|
if (rowTempEmailSubdomainMode) {
|
||||||
rowTempEmailRandomSubdomainToggle.style.display = showCloudflareTempEmailRandomSubdomainToggle ? '' : 'none';
|
rowTempEmailSubdomainMode.style.display = showCloudflareTempEmailSubdomainMode ? '' : 'none';
|
||||||
|
}
|
||||||
|
if (tempEmailSubdomainModeCaption) {
|
||||||
|
tempEmailSubdomainModeCaption.textContent = cloudflareTempEmailSubdomainMode === CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM
|
||||||
|
? '需后端、DNS、Email Routing/MX 覆盖随机子域'
|
||||||
|
: (cloudflareTempEmailSubdomainMode === CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED
|
||||||
|
? '需后端、DNS、Email Routing/MX 覆盖固定子域'
|
||||||
|
: '按基础域名直接生成');
|
||||||
|
}
|
||||||
|
if (rowTempEmailFixedSubdomainPrefix) {
|
||||||
|
rowTempEmailFixedSubdomainPrefix.style.display = showCloudflareTempEmailFixedSubdomainPrefix ? '' : 'none';
|
||||||
|
}
|
||||||
|
if (inputTempEmailSubdomainPrefix) {
|
||||||
|
inputTempEmailSubdomainPrefix.classList.toggle('is-invalid', fixedSubdomainConfigInvalid);
|
||||||
|
inputTempEmailSubdomainPrefix.setAttribute('aria-invalid', String(fixedSubdomainConfigInvalid));
|
||||||
|
}
|
||||||
|
if (tempEmailSubdomainPrefixFeedback) {
|
||||||
|
tempEmailSubdomainPrefixFeedback.textContent = fixedSubdomainConfigInvalid
|
||||||
|
? fixedSubdomainValidation.message
|
||||||
|
: '';
|
||||||
|
tempEmailSubdomainPrefixFeedback.classList.toggle('is-error', fixedSubdomainConfigInvalid);
|
||||||
|
}
|
||||||
|
if (tempEmailEffectiveDomainPreview) {
|
||||||
|
tempEmailEffectiveDomainPreview.textContent = showCloudflareTempEmailFixedSubdomainPrefix && tempEmailEffectiveDomain
|
||||||
|
? `最终域名:${tempEmailEffectiveDomain}`
|
||||||
|
: '';
|
||||||
}
|
}
|
||||||
rowTempEmailDomain.style.display = showCloudflareTempEmailDomain ? '' : 'none';
|
rowTempEmailDomain.style.display = showCloudflareTempEmailDomain ? '' : 'none';
|
||||||
const { domains: tempEmailDomains } = getCloudflareTempEmailDomainsFromState();
|
if (labelTempEmailDomain) {
|
||||||
|
labelTempEmailDomain.textContent = showCloudflareTempEmailFixedSubdomainPrefix ? '基础域名' : 'Temp 域名';
|
||||||
|
}
|
||||||
if (showCloudflareTempEmailDomain) {
|
if (showCloudflareTempEmailDomain) {
|
||||||
setCloudflareTempEmailDomainEditMode(cloudflareTempEmailDomainEditMode || tempEmailDomains.length === 0, { clearInput: false });
|
setCloudflareTempEmailDomainEditMode(cloudflareTempEmailDomainEditMode || tempEmailDomains.length === 0, { clearInput: false });
|
||||||
} else {
|
} else {
|
||||||
@@ -13079,7 +13242,7 @@ function updateMailProviderUI() {
|
|||||||
if (useCustomEmail && useCustomMailProviderPool) {
|
if (useCustomEmail && useCustomMailProviderPool) {
|
||||||
inputEmail.placeholder = '号池会按顺序自动回填当前轮邮箱,也可以手动覆盖';
|
inputEmail.placeholder = '号池会按顺序自动回填当前轮邮箱,也可以手动覆盖';
|
||||||
}
|
}
|
||||||
btnFetchEmail.disabled = useLuckmail || useCustomEmail || useCustomEmailPool || isAutoRunLockedPhase();
|
btnFetchEmail.disabled = useLuckmail || useCustomEmail || useCustomEmailPool || fixedSubdomainConfigInvalid || isAutoRunLockedPhase();
|
||||||
if (!btnFetchEmail.disabled) {
|
if (!btnFetchEmail.disabled) {
|
||||||
btnFetchEmail.textContent = uiCopy.buttonLabel;
|
btnFetchEmail.textContent = uiCopy.buttonLabel;
|
||||||
}
|
}
|
||||||
@@ -13116,8 +13279,17 @@ function updateMailProviderUI() {
|
|||||||
if (autoHintText && showCloudflareTempEmailReceiveMailbox && !useCustomEmailPool) {
|
if (autoHintText && showCloudflareTempEmailReceiveMailbox && !useCustomEmailPool) {
|
||||||
autoHintText.textContent = '若注册邮箱会转发到 Cloudflare Temp Email,请在“邮件接收”中填写实际接收转发邮件的邮箱。';
|
autoHintText.textContent = '若注册邮箱会转发到 Cloudflare Temp Email,请在“邮件接收”中填写实际接收转发邮件的邮箱。';
|
||||||
}
|
}
|
||||||
if (autoHintText && showCloudflareTempEmailRandomSubdomainToggle && inputTempEmailUseRandomSubdomain?.checked) {
|
if (
|
||||||
autoHintText.textContent = '已启用随机子域名:扩展会按当前选中的 Temp 域名提交,并额外携带 enableRandomSubdomain;是否生效取决于后端 RANDOM_SUBDOMAIN_DOMAINS 配置。';
|
autoHintText
|
||||||
|
&& showCloudflareTempEmailSubdomainMode
|
||||||
|
&& cloudflareTempEmailSubdomainMode === CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM
|
||||||
|
) {
|
||||||
|
autoHintText.textContent = '已启用随机子域名:扩展会按当前选中的基础域名提交,并额外携带 enableRandomSubdomain;后端 RANDOM_SUBDOMAIN_DOMAINS、DNS、Email Routing/MX 都需要覆盖对应子域。';
|
||||||
|
}
|
||||||
|
if (autoHintText && showCloudflareTempEmailFixedSubdomainPrefix) {
|
||||||
|
autoHintText.textContent = tempEmailEffectiveDomain
|
||||||
|
? `已启用固定子域名:本次会向后端提交 ${tempEmailEffectiveDomain};后端 ENABLE_CREATE_ADDRESS_SUBDOMAIN_MATCH、DNS、Email Routing/MX 都需要覆盖该子域。`
|
||||||
|
: `已启用固定子域名:${fixedSubdomainValidation.message};后端、DNS、Email Routing/MX 都需要覆盖该子域。`;
|
||||||
}
|
}
|
||||||
if (autoHintText && useIcloudProvider && showIcloudForwardMailProvider) {
|
if (autoHintText && useIcloudProvider && showIcloudForwardMailProvider) {
|
||||||
const forwardProvider = normalizeIcloudForwardMailProvider(icloudForwardMailProviderValue);
|
const forwardProvider = normalizeIcloudForwardMailProvider(icloudForwardMailProviderValue);
|
||||||
@@ -16507,12 +16679,32 @@ inputTempEmailReceiveMailbox.addEventListener('blur', () => {
|
|||||||
saveSettings({ silent: true }).catch(() => { });
|
saveSettings({ silent: true }).catch(() => { });
|
||||||
});
|
});
|
||||||
|
|
||||||
inputTempEmailUseRandomSubdomain?.addEventListener('change', () => {
|
tempEmailSubdomainModeButtons.forEach((button) => {
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
const nextMode = normalizeCloudflareTempEmailSubdomainMode(button.dataset.tempEmailSubdomainMode);
|
||||||
|
const previousMode = getSelectedCloudflareTempEmailSubdomainMode();
|
||||||
|
if (nextMode === previousMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setCloudflareTempEmailSubdomainMode(nextMode);
|
||||||
updateMailProviderUI();
|
updateMailProviderUI();
|
||||||
clearRegistrationEmail({ silent: true }).catch(() => { });
|
clearRegistrationEmail({ silent: true }).catch(() => { });
|
||||||
markSettingsDirty(true);
|
markSettingsDirty(true);
|
||||||
saveSettings({ silent: true }).catch(() => { });
|
saveSettings({ silent: true }).catch(() => { });
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
inputTempEmailSubdomainPrefix?.addEventListener('input', () => {
|
||||||
|
updateMailProviderUI();
|
||||||
|
clearRegistrationEmail({ silent: true }).catch(() => { });
|
||||||
|
markSettingsDirty(true);
|
||||||
|
scheduleSettingsAutoSave();
|
||||||
|
});
|
||||||
|
inputTempEmailSubdomainPrefix?.addEventListener('blur', () => {
|
||||||
|
inputTempEmailSubdomainPrefix.value = normalizeCloudflareTempEmailSubdomainPrefixValue(inputTempEmailSubdomainPrefix.value);
|
||||||
|
updateMailProviderUI();
|
||||||
|
saveSettings({ silent: true }).catch(() => { });
|
||||||
|
});
|
||||||
|
|
||||||
inputAutoSkipFailuresThreadIntervalMinutes.addEventListener('input', () => {
|
inputAutoSkipFailuresThreadIntervalMinutes.addEventListener('input', () => {
|
||||||
markSettingsDirty(true);
|
markSettingsDirty(true);
|
||||||
@@ -17688,14 +17880,38 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|||||||
if (message.payload.cloudflareTempEmailReceiveMailbox !== undefined) {
|
if (message.payload.cloudflareTempEmailReceiveMailbox !== undefined) {
|
||||||
inputTempEmailReceiveMailbox.value = message.payload.cloudflareTempEmailReceiveMailbox || '';
|
inputTempEmailReceiveMailbox.value = message.payload.cloudflareTempEmailReceiveMailbox || '';
|
||||||
}
|
}
|
||||||
if (message.payload.cloudflareTempEmailUseRandomSubdomain !== undefined && inputTempEmailUseRandomSubdomain) {
|
if (
|
||||||
inputTempEmailUseRandomSubdomain.checked = Boolean(message.payload.cloudflareTempEmailUseRandomSubdomain);
|
message.payload.cloudflareTempEmailUseRandomSubdomain !== undefined
|
||||||
|
|| message.payload.cloudflareTempEmailUseFixedSubdomain !== undefined
|
||||||
|
) {
|
||||||
|
const useFixedSubdomain = Boolean(
|
||||||
|
message.payload.cloudflareTempEmailUseFixedSubdomain
|
||||||
|
?? latestState?.cloudflareTempEmailUseFixedSubdomain
|
||||||
|
);
|
||||||
|
const useRandomSubdomain = Boolean(
|
||||||
|
message.payload.cloudflareTempEmailUseRandomSubdomain
|
||||||
|
?? latestState?.cloudflareTempEmailUseRandomSubdomain
|
||||||
|
);
|
||||||
|
setCloudflareTempEmailSubdomainMode(
|
||||||
|
useFixedSubdomain
|
||||||
|
? CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED
|
||||||
|
: (useRandomSubdomain
|
||||||
|
? CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM
|
||||||
|
: CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_NONE)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (message.payload.cloudflareTempEmailSubdomainPrefix !== undefined && inputTempEmailSubdomainPrefix) {
|
||||||
|
inputTempEmailSubdomainPrefix.value = normalizeCloudflareTempEmailSubdomainPrefixValue(
|
||||||
|
message.payload.cloudflareTempEmailSubdomainPrefix || ''
|
||||||
|
);
|
||||||
}
|
}
|
||||||
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 || '');
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
message.payload.cloudflareTempEmailUseRandomSubdomain !== undefined
|
message.payload.cloudflareTempEmailUseRandomSubdomain !== undefined
|
||||||
|
|| message.payload.cloudflareTempEmailUseFixedSubdomain !== undefined
|
||||||
|
|| message.payload.cloudflareTempEmailSubdomainPrefix !== undefined
|
||||||
|| message.payload.cloudflareTempEmailLookupMode !== undefined
|
|| message.payload.cloudflareTempEmailLookupMode !== undefined
|
||||||
|| message.payload.cloudflareTempEmailDomain !== undefined
|
|| message.payload.cloudflareTempEmailDomain !== undefined
|
||||||
|| message.payload.cloudflareTempEmailDomains !== undefined
|
|| message.payload.cloudflareTempEmailDomains !== undefined
|
||||||
@@ -18300,6 +18516,7 @@ updateConfigMenuControls();
|
|||||||
setLocalCpaStep9Mode(DEFAULT_LOCAL_CPA_STEP9_MODE);
|
setLocalCpaStep9Mode(DEFAULT_LOCAL_CPA_STEP9_MODE);
|
||||||
setMail2925Mode(DEFAULT_MAIL_2925_MODE);
|
setMail2925Mode(DEFAULT_MAIL_2925_MODE);
|
||||||
setCloudflareTempEmailLookupMode(DEFAULT_CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE);
|
setCloudflareTempEmailLookupMode(DEFAULT_CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE);
|
||||||
|
setCloudflareTempEmailSubdomainMode(DEFAULT_CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE);
|
||||||
initializeReleaseInfo().catch((err) => {
|
initializeReleaseInfo().catch((err) => {
|
||||||
console.error('Failed to initialize release info:', err);
|
console.error('Failed to initialize release info:', err);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ const PERSISTED_SETTING_DEFAULTS = {
|
|||||||
accountRunHistoryTextEnabled: false,
|
accountRunHistoryTextEnabled: false,
|
||||||
cloudflareTempEmailLookupMode: 'receive-mailbox',
|
cloudflareTempEmailLookupMode: 'receive-mailbox',
|
||||||
cloudflareTempEmailUseRandomSubdomain: false,
|
cloudflareTempEmailUseRandomSubdomain: false,
|
||||||
|
cloudflareTempEmailUseFixedSubdomain: false,
|
||||||
|
cloudflareTempEmailSubdomainPrefix: '',
|
||||||
cloudflareTempEmailDomain: '',
|
cloudflareTempEmailDomain: '',
|
||||||
cloudflareTempEmailDomains: [],
|
cloudflareTempEmailDomains: [],
|
||||||
};
|
};
|
||||||
@@ -97,6 +99,16 @@ function normalizeCloudflareDomains(value) { return Array.isArray(value) ? value
|
|||||||
function normalizeCloudflareTempEmailBaseUrl(value) { return String(value || '').trim(); }
|
function normalizeCloudflareTempEmailBaseUrl(value) { return String(value || '').trim(); }
|
||||||
function normalizeCloudflareTempEmailAddress(value = '') { return String(value || '').trim().toLowerCase(); }
|
function normalizeCloudflareTempEmailAddress(value = '') { return String(value || '').trim().toLowerCase(); }
|
||||||
function normalizeCloudflareTempEmailDomain(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) {
|
function normalizeCloudflareTempEmailDomains(value) {
|
||||||
const seen = new Set();
|
const seen = new Set();
|
||||||
const domains = [];
|
const domains = [];
|
||||||
@@ -120,17 +132,24 @@ return {
|
|||||||
`)();
|
`)();
|
||||||
|
|
||||||
assert.equal(api.normalizePersistentSettingValue('cloudflareTempEmailUseRandomSubdomain', 1), true);
|
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', 'registration-email'), 'registration-email');
|
||||||
assert.equal(api.normalizePersistentSettingValue('cloudflareTempEmailLookupMode', 'bad'), 'receive-mailbox');
|
assert.equal(api.normalizePersistentSettingValue('cloudflareTempEmailLookupMode', 'bad'), 'receive-mailbox');
|
||||||
|
|
||||||
const payload = api.buildPersistentSettingsPayload({
|
const payload = api.buildPersistentSettingsPayload({
|
||||||
cloudflareTempEmailLookupMode: 'registration-email',
|
cloudflareTempEmailLookupMode: 'registration-email',
|
||||||
cloudflareTempEmailUseRandomSubdomain: true,
|
cloudflareTempEmailUseRandomSubdomain: true,
|
||||||
|
cloudflareTempEmailUseFixedSubdomain: true,
|
||||||
|
cloudflareTempEmailSubdomainPrefix: 'Team',
|
||||||
cloudflareTempEmailDomain: 'mail.example.com',
|
cloudflareTempEmailDomain: 'mail.example.com',
|
||||||
cloudflareTempEmailDomains: ['mail.example.com', 'alt.example.com'],
|
cloudflareTempEmailDomains: ['mail.example.com', 'alt.example.com'],
|
||||||
});
|
});
|
||||||
assert.equal(payload.cloudflareTempEmailLookupMode, 'registration-email');
|
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.equal(payload.cloudflareTempEmailDomain, 'mail.example.com');
|
||||||
assert.deepEqual(payload.cloudflareTempEmailDomains, ['mail.example.com', 'alt.example.com']);
|
assert.deepEqual(payload.cloudflareTempEmailDomains, ['mail.example.com', 'alt.example.com']);
|
||||||
|
|
||||||
@@ -141,6 +160,8 @@ return {
|
|||||||
cloudflareTempEmailLookupMode: 'registration-email',
|
cloudflareTempEmailLookupMode: 'registration-email',
|
||||||
cloudflareTempEmailReceiveMailbox: 'Forward@Example.com',
|
cloudflareTempEmailReceiveMailbox: 'Forward@Example.com',
|
||||||
cloudflareTempEmailUseRandomSubdomain: true,
|
cloudflareTempEmailUseRandomSubdomain: true,
|
||||||
|
cloudflareTempEmailUseFixedSubdomain: true,
|
||||||
|
cloudflareTempEmailSubdomainPrefix: 'Team',
|
||||||
cloudflareTempEmailDomain: 'mail.example.com',
|
cloudflareTempEmailDomain: 'mail.example.com',
|
||||||
cloudflareTempEmailDomains: ['mail.example.com'],
|
cloudflareTempEmailDomains: ['mail.example.com'],
|
||||||
});
|
});
|
||||||
@@ -150,9 +171,12 @@ return {
|
|||||||
customAuth: 'custom-secret',
|
customAuth: 'custom-secret',
|
||||||
lookupMode: 'registration-email',
|
lookupMode: 'registration-email',
|
||||||
receiveMailbox: 'forward@example.com',
|
receiveMailbox: 'forward@example.com',
|
||||||
useRandomSubdomain: true,
|
useRandomSubdomain: false,
|
||||||
|
useFixedSubdomain: true,
|
||||||
|
subdomainPrefix: 'team',
|
||||||
domain: 'mail.example.com',
|
domain: 'mail.example.com',
|
||||||
domains: ['mail.example.com'],
|
domains: ['mail.example.com'],
|
||||||
|
effectiveDomain: 'team.mail.example.com',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -169,6 +193,8 @@ const PERSISTED_SETTING_DEFAULTS = {
|
|||||||
autoDeleteUsedIcloudAlias: false,
|
autoDeleteUsedIcloudAlias: false,
|
||||||
accountRunHistoryTextEnabled: false,
|
accountRunHistoryTextEnabled: false,
|
||||||
cloudflareTempEmailUseRandomSubdomain: false,
|
cloudflareTempEmailUseRandomSubdomain: false,
|
||||||
|
cloudflareTempEmailUseFixedSubdomain: false,
|
||||||
|
cloudflareTempEmailSubdomainPrefix: '',
|
||||||
cloudflareTempEmailDomain: '',
|
cloudflareTempEmailDomain: '',
|
||||||
cloudflareTempEmailDomains: [],
|
cloudflareTempEmailDomains: [],
|
||||||
};
|
};
|
||||||
@@ -200,6 +226,7 @@ function normalizeCloudflareTempEmailBaseUrl(value) { return String(value || '')
|
|||||||
function normalizeCloudflareTempEmailAddress(value = '') { return String(value || '').trim().toLowerCase(); }
|
function normalizeCloudflareTempEmailAddress(value = '') { return String(value || '').trim().toLowerCase(); }
|
||||||
function normalizeCloudflareTempEmailReceiveMailbox(value = '') { return String(value || '').trim().toLowerCase(); }
|
function normalizeCloudflareTempEmailReceiveMailbox(value = '') { return String(value || '').trim().toLowerCase(); }
|
||||||
function normalizeCloudflareTempEmailDomain(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 normalizeCloudflareTempEmailDomains(value) { return Array.isArray(value) ? value.map((item) => String(item || '').trim().toLowerCase()).filter(Boolean) : []; }
|
||||||
function normalizeHotmailAccounts(value) { return Array.isArray(value) ? value : []; }
|
function normalizeHotmailAccounts(value) { return Array.isArray(value) ? value : []; }
|
||||||
function normalizeMail2925Accounts(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 () => {
|
test('generated email helper honors iCloud always-new fetch mode', async () => {
|
||||||
const api = loadGeneratedEmailHelpersApi();
|
const api = loadGeneratedEmailHelpersApi();
|
||||||
const icloudOptions = [];
|
const icloudOptions = [];
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ const test = require('node:test');
|
|||||||
const assert = require('node:assert/strict');
|
const assert = require('node:assert/strict');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
buildCloudflareTempEmailEffectiveDomain,
|
||||||
buildCloudflareTempEmailHeaders,
|
buildCloudflareTempEmailHeaders,
|
||||||
getCloudflareTempEmailAddressFromResponse,
|
getCloudflareTempEmailAddressFromResponse,
|
||||||
normalizeCloudflareTempEmailBaseUrl,
|
normalizeCloudflareTempEmailBaseUrl,
|
||||||
normalizeCloudflareTempEmailDomain,
|
normalizeCloudflareTempEmailDomain,
|
||||||
normalizeCloudflareTempEmailDomains,
|
normalizeCloudflareTempEmailDomains,
|
||||||
normalizeCloudflareTempEmailMailApiMessages,
|
normalizeCloudflareTempEmailMailApiMessages,
|
||||||
|
normalizeCloudflareTempEmailSubdomainPrefix,
|
||||||
} = require('../cloudflare-temp-email-utils.js');
|
} = require('../cloudflare-temp-email-utils.js');
|
||||||
const {
|
const {
|
||||||
pickVerificationMessageWithTimeFallback,
|
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', () => {
|
test('buildCloudflareTempEmailHeaders includes auth headers and content type when needed', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
buildCloudflareTempEmailHeaders(
|
buildCloudflareTempEmailHeaders(
|
||||||
|
|||||||
@@ -58,6 +58,31 @@ function createRow(initialDisplay = 'none') {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createClassList(initial = []) {
|
||||||
|
const values = new Set(initial);
|
||||||
|
return {
|
||||||
|
toggle(name, force) {
|
||||||
|
if (force === undefined) {
|
||||||
|
if (values.has(name)) {
|
||||||
|
values.delete(name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
values.add(name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (force) {
|
||||||
|
values.add(name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
values.delete(name);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
contains(name) {
|
||||||
|
return values.has(name);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
test('sidepanel html places cloudflare temp email controls in a standalone section', () => {
|
test('sidepanel html places cloudflare temp email controls in a standalone section', () => {
|
||||||
const html = fs.readFileSync('sidepanel/sidepanel.html', 'utf8');
|
const html = fs.readFileSync('sidepanel/sidepanel.html', 'utf8');
|
||||||
assert.match(html, /id="cloudflare-temp-email-section"/);
|
assert.match(html, /id="cloudflare-temp-email-section"/);
|
||||||
@@ -67,9 +92,20 @@ test('sidepanel html places cloudflare temp email controls in a standalone secti
|
|||||||
assert.match(html, /id="row-temp-email-lookup-mode"/);
|
assert.match(html, /id="row-temp-email-lookup-mode"/);
|
||||||
assert.match(html, /data-temp-email-lookup-mode="receive-mailbox"/);
|
assert.match(html, /data-temp-email-lookup-mode="receive-mailbox"/);
|
||||||
assert.match(html, /data-temp-email-lookup-mode="registration-email"/);
|
assert.match(html, /data-temp-email-lookup-mode="registration-email"/);
|
||||||
assert.match(html, /id="row-temp-email-random-subdomain-toggle"/);
|
assert.match(html, /id="row-temp-email-subdomain-mode"/);
|
||||||
|
assert.match(html, /data-temp-email-subdomain-mode="none"/);
|
||||||
|
assert.match(html, /data-temp-email-subdomain-mode="random"/);
|
||||||
|
assert.match(html, /data-temp-email-subdomain-mode="fixed"/);
|
||||||
assert.match(html, /id="input-temp-email-use-random-subdomain"/);
|
assert.match(html, /id="input-temp-email-use-random-subdomain"/);
|
||||||
|
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="temp-email-subdomain-prefix-feedback"/);
|
||||||
|
assert.match(html, /id="temp-email-effective-domain-preview"/);
|
||||||
|
assert.match(html, /id="label-temp-email-domain"/);
|
||||||
assert.match(html, /id="btn-temp-email-domain-mode"[^>]*>更新</);
|
assert.match(html, /id="btn-temp-email-domain-mode"[^>]*>更新</);
|
||||||
|
assert.doesNotMatch(html, /id="row-temp-email-random-subdomain-toggle"/);
|
||||||
|
assert.doesNotMatch(html, /id="row-temp-email-fixed-subdomain-toggle"/);
|
||||||
assert.doesNotMatch(html, /id="row-temp-email-random-subdomain-domain"/);
|
assert.doesNotMatch(html, /id="row-temp-email-random-subdomain-domain"/);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -142,6 +178,15 @@ const inputTempEmailAdminAuth = { value: '' };
|
|||||||
const inputTempEmailCustomAuth = { value: '' };
|
const inputTempEmailCustomAuth = { value: '' };
|
||||||
const inputTempEmailReceiveMailbox = { value: '' };
|
const inputTempEmailReceiveMailbox = { value: '' };
|
||||||
const inputTempEmailUseRandomSubdomain = { checked: false };
|
const inputTempEmailUseRandomSubdomain = { checked: false };
|
||||||
|
const inputTempEmailUseFixedSubdomain = { checked: false };
|
||||||
|
const inputTempEmailSubdomainPrefix = { value: '' };
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_NONE = 'none';
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM = 'random';
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED = 'fixed';
|
||||||
|
function setCloudflareTempEmailSubdomainMode(mode) {
|
||||||
|
inputTempEmailUseFixedSubdomain.checked = mode === CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED;
|
||||||
|
inputTempEmailUseRandomSubdomain.checked = mode === CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM;
|
||||||
|
}
|
||||||
const calls = {
|
const calls = {
|
||||||
domainOptions: [],
|
domainOptions: [],
|
||||||
domainEditMode: [],
|
domainEditMode: [],
|
||||||
@@ -150,6 +195,10 @@ const calls = {
|
|||||||
function renderCloudflareTempEmailDomainOptions(value) { calls.domainOptions.push(value); }
|
function renderCloudflareTempEmailDomainOptions(value) { calls.domainOptions.push(value); }
|
||||||
function setCloudflareTempEmailDomainEditMode(editing, options) { calls.domainEditMode.push({ editing, options }); }
|
function setCloudflareTempEmailDomainEditMode(editing, options) { calls.domainEditMode.push({ editing, options }); }
|
||||||
function setCloudflareTempEmailLookupMode(value) { calls.lookupModes.push(value); }
|
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}
|
${bundle}
|
||||||
return {
|
return {
|
||||||
applyCloudflareTempEmailSettingsState,
|
applyCloudflareTempEmailSettingsState,
|
||||||
@@ -159,6 +208,8 @@ return {
|
|||||||
inputTempEmailCustomAuth,
|
inputTempEmailCustomAuth,
|
||||||
inputTempEmailReceiveMailbox,
|
inputTempEmailReceiveMailbox,
|
||||||
inputTempEmailUseRandomSubdomain,
|
inputTempEmailUseRandomSubdomain,
|
||||||
|
inputTempEmailUseFixedSubdomain,
|
||||||
|
inputTempEmailSubdomainPrefix,
|
||||||
};
|
};
|
||||||
`)();
|
`)();
|
||||||
|
|
||||||
@@ -169,6 +220,8 @@ return {
|
|||||||
cloudflareTempEmailLookupMode: 'registration-email',
|
cloudflareTempEmailLookupMode: 'registration-email',
|
||||||
cloudflareTempEmailReceiveMailbox: 'relay@example.com',
|
cloudflareTempEmailReceiveMailbox: 'relay@example.com',
|
||||||
cloudflareTempEmailUseRandomSubdomain: true,
|
cloudflareTempEmailUseRandomSubdomain: true,
|
||||||
|
cloudflareTempEmailUseFixedSubdomain: true,
|
||||||
|
cloudflareTempEmailSubdomainPrefix: 'Team',
|
||||||
cloudflareTempEmailDomain: 'mail.example.com',
|
cloudflareTempEmailDomain: 'mail.example.com',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -176,7 +229,9 @@ return {
|
|||||||
assert.equal(api.inputTempEmailAdminAuth.value, 'admin-secret');
|
assert.equal(api.inputTempEmailAdminAuth.value, 'admin-secret');
|
||||||
assert.equal(api.inputTempEmailCustomAuth.value, 'custom-secret');
|
assert.equal(api.inputTempEmailCustomAuth.value, 'custom-secret');
|
||||||
assert.equal(api.inputTempEmailReceiveMailbox.value, 'relay@example.com');
|
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.lookupModes, ['registration-email']);
|
||||||
assert.deepEqual(api.calls.domainOptions, ['mail.example.com']);
|
assert.deepEqual(api.calls.domainOptions, ['mail.example.com']);
|
||||||
assert.deepEqual(api.calls.domainEditMode, [{ editing: false, options: { clearInput: true } }]);
|
assert.deepEqual(api.calls.domainEditMode, [{ editing: false, options: { clearInput: true } }]);
|
||||||
@@ -415,8 +470,55 @@ const rowTempEmailAdminAuth = ${JSON.stringify(createRow('none'))};
|
|||||||
const rowTempEmailCustomAuth = ${JSON.stringify(createRow('none'))};
|
const rowTempEmailCustomAuth = ${JSON.stringify(createRow('none'))};
|
||||||
const rowTempEmailLookupMode = ${JSON.stringify(createRow('none'))};
|
const rowTempEmailLookupMode = ${JSON.stringify(createRow('none'))};
|
||||||
const rowTempEmailReceiveMailbox = ${JSON.stringify(createRow('none'))};
|
const rowTempEmailReceiveMailbox = ${JSON.stringify(createRow('none'))};
|
||||||
const rowTempEmailRandomSubdomainToggle = ${JSON.stringify(createRow('none'))};
|
const rowTempEmailSubdomainMode = ${JSON.stringify(createRow('none'))};
|
||||||
|
function createClassList(initial = []) {
|
||||||
|
const values = new Set(initial);
|
||||||
|
return {
|
||||||
|
toggle(name, force) {
|
||||||
|
if (force === undefined) {
|
||||||
|
if (values.has(name)) {
|
||||||
|
values.delete(name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
values.add(name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (force) {
|
||||||
|
values.add(name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
values.delete(name);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
contains(name) {
|
||||||
|
return values.has(name);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const tempEmailSubdomainModeButtons = [
|
||||||
|
{
|
||||||
|
dataset: { tempEmailSubdomainMode: 'none' },
|
||||||
|
attributes: {},
|
||||||
|
classList: createClassList(['is-active']),
|
||||||
|
setAttribute(name, value) { this.attributes[name] = String(value); },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataset: { tempEmailSubdomainMode: 'random' },
|
||||||
|
attributes: {},
|
||||||
|
classList: createClassList(),
|
||||||
|
setAttribute(name, value) { this.attributes[name] = String(value); },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataset: { tempEmailSubdomainMode: 'fixed' },
|
||||||
|
attributes: {},
|
||||||
|
classList: createClassList(),
|
||||||
|
setAttribute(name, value) { this.attributes[name] = String(value); },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const tempEmailSubdomainModeCaption = { textContent: '' };
|
||||||
|
const rowTempEmailFixedSubdomainPrefix = ${JSON.stringify(createRow('none'))};
|
||||||
const rowTempEmailDomain = ${JSON.stringify(createRow('none'))};
|
const rowTempEmailDomain = ${JSON.stringify(createRow('none'))};
|
||||||
|
const labelTempEmailDomain = { textContent: '' };
|
||||||
const cloudflareTempEmailSection = ${JSON.stringify(createRow('none'))};
|
const cloudflareTempEmailSection = ${JSON.stringify(createRow('none'))};
|
||||||
const hotmailSection = ${JSON.stringify(createRow('none'))};
|
const hotmailSection = ${JSON.stringify(createRow('none'))};
|
||||||
const mail2925Section = ${JSON.stringify(createRow('none'))};
|
const mail2925Section = ${JSON.stringify(createRow('none'))};
|
||||||
@@ -436,7 +538,21 @@ const rowHotmailLocalBaseUrl = ${JSON.stringify(createRow('none'))};
|
|||||||
const inputMail2925UseAccountPool = { checked: false };
|
const inputMail2925UseAccountPool = { checked: false };
|
||||||
const selectMailProvider = { value: '163' };
|
const selectMailProvider = { value: '163' };
|
||||||
const selectEmailGenerator = { value: 'cloudflare-temp-email', disabled: false };
|
const selectEmailGenerator = { value: 'cloudflare-temp-email', disabled: false };
|
||||||
|
const selectTempEmailDomain = { value: 'mail.example.com' };
|
||||||
const inputTempEmailUseRandomSubdomain = { checked: false };
|
const inputTempEmailUseRandomSubdomain = { checked: false };
|
||||||
|
const inputTempEmailUseFixedSubdomain = { checked: false };
|
||||||
|
const inputTempEmailSubdomainPrefix = {
|
||||||
|
value: 'team',
|
||||||
|
attributes: {},
|
||||||
|
classList: createClassList(),
|
||||||
|
setAttribute(name, value) { this.attributes[name] = String(value); },
|
||||||
|
};
|
||||||
|
const tempEmailSubdomainPrefixFeedback = { textContent: '', classList: createClassList() };
|
||||||
|
const tempEmailEffectiveDomainPreview = { textContent: '' };
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_NONE = 'none';
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM = 'random';
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED = 'fixed';
|
||||||
|
const DEFAULT_CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE = 'none';
|
||||||
const calls = {
|
const calls = {
|
||||||
tempDomainEditMode: [],
|
tempDomainEditMode: [],
|
||||||
};
|
};
|
||||||
@@ -447,6 +563,31 @@ function usesGeneratedAliasMailProvider() { return false; }
|
|||||||
function getSelectedMail2925Mode() { return 'provide'; }
|
function getSelectedMail2925Mode() { return 'provide'; }
|
||||||
let selectedCloudflareTempEmailLookupMode = 'receive-mailbox';
|
let selectedCloudflareTempEmailLookupMode = 'receive-mailbox';
|
||||||
function getSelectedCloudflareTempEmailLookupMode() { return selectedCloudflareTempEmailLookupMode; }
|
function getSelectedCloudflareTempEmailLookupMode() { return selectedCloudflareTempEmailLookupMode; }
|
||||||
|
function normalizeCloudflareTempEmailSubdomainMode(value = '') {
|
||||||
|
const normalized = String(value || '').trim().toLowerCase();
|
||||||
|
return ['random', 'fixed'].includes(normalized) ? normalized : 'none';
|
||||||
|
}
|
||||||
|
function syncCloudflareTempEmailSubdomainModeButtons(mode) {
|
||||||
|
const resolvedMode = normalizeCloudflareTempEmailSubdomainMode(mode);
|
||||||
|
tempEmailSubdomainModeButtons.forEach((button) => {
|
||||||
|
const active = button.dataset.tempEmailSubdomainMode === resolvedMode;
|
||||||
|
button.classList.toggle('is-active', active);
|
||||||
|
button.setAttribute('aria-pressed', String(active));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function getSelectedCloudflareTempEmailSubdomainMode() {
|
||||||
|
if (inputTempEmailUseFixedSubdomain.checked) return 'fixed';
|
||||||
|
if (inputTempEmailUseRandomSubdomain.checked) return 'random';
|
||||||
|
return 'none';
|
||||||
|
}
|
||||||
|
function getCloudflareTempEmailSubdomainPrefixValidation(value = '') {
|
||||||
|
const raw = String(value || '').trim();
|
||||||
|
if (!raw) return { raw, normalized: '', valid: false, message: '请填写子域前缀' };
|
||||||
|
const normalized = normalizeCloudflareTempEmailSubdomainPrefixValue(raw);
|
||||||
|
return normalized
|
||||||
|
? { raw, normalized, valid: true, message: '' }
|
||||||
|
: { raw, normalized: '', valid: false, message: '仅支持 1-63 位字母、数字或中划线,且不能以中划线开头或结尾' };
|
||||||
|
}
|
||||||
function getManagedAliasProviderUiCopy() { return null; }
|
function getManagedAliasProviderUiCopy() { return null; }
|
||||||
function getCurrentRegistrationEmailUiCopy() {
|
function getCurrentRegistrationEmailUiCopy() {
|
||||||
return {
|
return {
|
||||||
@@ -460,6 +601,17 @@ function getSelectedHotmailServiceMode() { return 'local'; }
|
|||||||
function getCloudflareDomainsFromState() { return { domains: [], activeDomain: '' }; }
|
function getCloudflareDomainsFromState() { return { domains: [], activeDomain: '' }; }
|
||||||
function setCloudflareDomainEditMode() {}
|
function setCloudflareDomainEditMode() {}
|
||||||
function getCloudflareTempEmailDomainsFromState() { return { domains: ['mail.example.com'], activeDomain: 'mail.example.com' }; }
|
function getCloudflareTempEmailDomainsFromState() { return { domains: ['mail.example.com'], activeDomain: 'mail.example.com' }; }
|
||||||
|
function normalizeCloudflareTempEmailDomainValue(value = '') { return String(value || '').trim().toLowerCase(); }
|
||||||
|
function normalizeCloudflareTempEmailSubdomainPrefixValue(value = '') {
|
||||||
|
const normalized = String(value || '').trim().toLowerCase();
|
||||||
|
return /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(normalized) ? normalized : '';
|
||||||
|
}
|
||||||
|
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 setCloudflareTempEmailDomainEditMode(editing) { calls.tempDomainEditMode.push(editing); }
|
||||||
function queueIcloudAliasRefresh() {}
|
function queueIcloudAliasRefresh() {}
|
||||||
function hideIcloudLoginHelp() {}
|
function hideIcloudLoginHelp() {}
|
||||||
@@ -476,9 +628,17 @@ return {
|
|||||||
cloudflareTempEmailSection,
|
cloudflareTempEmailSection,
|
||||||
rowTempEmailLookupMode,
|
rowTempEmailLookupMode,
|
||||||
rowTempEmailReceiveMailbox,
|
rowTempEmailReceiveMailbox,
|
||||||
rowTempEmailRandomSubdomainToggle,
|
rowTempEmailSubdomainMode,
|
||||||
|
rowTempEmailFixedSubdomainPrefix,
|
||||||
rowTempEmailDomain,
|
rowTempEmailDomain,
|
||||||
|
labelTempEmailDomain,
|
||||||
inputTempEmailUseRandomSubdomain,
|
inputTempEmailUseRandomSubdomain,
|
||||||
|
inputTempEmailUseFixedSubdomain,
|
||||||
|
inputTempEmailSubdomainPrefix,
|
||||||
|
tempEmailSubdomainModeCaption,
|
||||||
|
tempEmailSubdomainPrefixFeedback,
|
||||||
|
tempEmailEffectiveDomainPreview,
|
||||||
|
btnFetchEmail,
|
||||||
selectMailProvider,
|
selectMailProvider,
|
||||||
selectEmailGenerator,
|
selectEmailGenerator,
|
||||||
setLookupMode(value) {
|
setLookupMode(value) {
|
||||||
@@ -491,8 +651,10 @@ return {
|
|||||||
|
|
||||||
api.updateMailProviderUI();
|
api.updateMailProviderUI();
|
||||||
assert.equal(api.cloudflareTempEmailSection.style.display, '');
|
assert.equal(api.cloudflareTempEmailSection.style.display, '');
|
||||||
assert.equal(api.rowTempEmailRandomSubdomainToggle.style.display, '');
|
assert.equal(api.rowTempEmailSubdomainMode.style.display, '');
|
||||||
|
assert.equal(api.rowTempEmailFixedSubdomainPrefix.style.display, 'none');
|
||||||
assert.equal(api.rowTempEmailDomain.style.display, '');
|
assert.equal(api.rowTempEmailDomain.style.display, '');
|
||||||
|
assert.equal(api.labelTempEmailDomain.textContent, 'Temp 域名');
|
||||||
|
|
||||||
api.selectMailProvider.value = 'cloudflare-temp-email';
|
api.selectMailProvider.value = 'cloudflare-temp-email';
|
||||||
api.selectEmailGenerator.value = 'duck';
|
api.selectEmailGenerator.value = 'duck';
|
||||||
@@ -513,4 +675,29 @@ return {
|
|||||||
assert.equal(api.cloudflareTempEmailSection.style.display, '');
|
assert.equal(api.cloudflareTempEmailSection.style.display, '');
|
||||||
assert.equal(api.rowTempEmailDomain.style.display, '');
|
assert.equal(api.rowTempEmailDomain.style.display, '');
|
||||||
assert.match(api.autoHintText.textContent, /RANDOM_SUBDOMAIN_DOMAINS/);
|
assert.match(api.autoHintText.textContent, /RANDOM_SUBDOMAIN_DOMAINS/);
|
||||||
|
assert.match(api.autoHintText.textContent, /Email Routing\/MX/);
|
||||||
|
assert.match(api.tempEmailSubdomainModeCaption.textContent, /随机子域/);
|
||||||
|
|
||||||
|
api.inputTempEmailUseRandomSubdomain.checked = false;
|
||||||
|
api.inputTempEmailUseFixedSubdomain.checked = true;
|
||||||
|
api.inputTempEmailSubdomainPrefix.value = 'team';
|
||||||
|
api.updateMailProviderUI();
|
||||||
|
assert.equal(api.rowTempEmailFixedSubdomainPrefix.style.display, '');
|
||||||
|
assert.equal(api.labelTempEmailDomain.textContent, '基础域名');
|
||||||
|
assert.equal(api.tempEmailEffectiveDomainPreview.textContent, '最终域名:team.mail.example.com');
|
||||||
|
assert.equal(api.tempEmailSubdomainPrefixFeedback.textContent, '');
|
||||||
|
assert.equal(api.inputTempEmailSubdomainPrefix.attributes['aria-invalid'], 'false');
|
||||||
|
assert.equal(api.btnFetchEmail.disabled, false);
|
||||||
|
assert.match(api.autoHintText.textContent, /team\.mail\.example\.com/);
|
||||||
|
assert.match(api.autoHintText.textContent, /ENABLE_CREATE_ADDRESS_SUBDOMAIN_MATCH/);
|
||||||
|
assert.match(api.autoHintText.textContent, /Email Routing\/MX/);
|
||||||
|
|
||||||
|
api.inputTempEmailSubdomainPrefix.value = '';
|
||||||
|
api.updateMailProviderUI();
|
||||||
|
assert.equal(api.btnFetchEmail.disabled, true);
|
||||||
|
assert.equal(api.tempEmailEffectiveDomainPreview.textContent, '');
|
||||||
|
assert.equal(api.tempEmailSubdomainPrefixFeedback.textContent, '请填写子域前缀');
|
||||||
|
assert.equal(api.tempEmailSubdomainPrefixFeedback.classList.contains('is-error'), true);
|
||||||
|
assert.equal(api.inputTempEmailSubdomainPrefix.attributes['aria-invalid'], 'true');
|
||||||
|
assert.match(api.autoHintText.textContent, /请填写子域前缀/);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -245,6 +245,15 @@ const inputTempEmailAdminAuth = { value: 'admin-secret' };
|
|||||||
const inputTempEmailCustomAuth = { value: 'custom-secret' };
|
const inputTempEmailCustomAuth = { value: 'custom-secret' };
|
||||||
const inputTempEmailReceiveMailbox = { value: 'relay@example.com' };
|
const inputTempEmailReceiveMailbox = { value: 'relay@example.com' };
|
||||||
const inputTempEmailUseRandomSubdomain = { checked: true };
|
const inputTempEmailUseRandomSubdomain = { checked: true };
|
||||||
|
const inputTempEmailUseFixedSubdomain = { checked: false };
|
||||||
|
const inputTempEmailSubdomainPrefix = { value: '' };
|
||||||
|
function getSelectedCloudflareTempEmailSubdomainMode() {
|
||||||
|
if (inputTempEmailUseFixedSubdomain.checked) return 'fixed';
|
||||||
|
if (inputTempEmailUseRandomSubdomain.checked) return 'random';
|
||||||
|
return 'none';
|
||||||
|
}
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM = 'random';
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED = 'fixed';
|
||||||
const inputAutoSkipFailures = { checked: false };
|
const inputAutoSkipFailures = { checked: false };
|
||||||
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '5' };
|
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '5' };
|
||||||
const inputAutoStepDelaySeconds = { value: '10' };
|
const inputAutoStepDelaySeconds = { value: '10' };
|
||||||
@@ -293,6 +302,7 @@ function normalizeLuckmailBaseUrl(value) { return String(value || '').trim(); }
|
|||||||
function normalizeLuckmailEmailType(value) { return String(value || '').trim(); }
|
function normalizeLuckmailEmailType(value) { return String(value || '').trim(); }
|
||||||
function normalizeCloudflareTempEmailBaseUrlValue(value) { return String(value || '').trim(); }
|
function normalizeCloudflareTempEmailBaseUrlValue(value) { return String(value || '').trim(); }
|
||||||
function normalizeCloudflareTempEmailReceiveMailboxValue(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 normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) || 0; }
|
||||||
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
|
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
|
||||||
function normalizeVerificationResendCount(value, fallback) { return Number.isFinite(Number(value)) ? Number(value) : fallback; }
|
function normalizeVerificationResendCount(value, fallback) { return Number.isFinite(Number(value)) ? Number(value) : fallback; }
|
||||||
|
|||||||
@@ -130,6 +130,15 @@ const inputTempEmailAdminAuth = { value: '' };
|
|||||||
const inputTempEmailCustomAuth = { value: '' };
|
const inputTempEmailCustomAuth = { value: '' };
|
||||||
const inputTempEmailReceiveMailbox = { value: '' };
|
const inputTempEmailReceiveMailbox = { value: '' };
|
||||||
const inputTempEmailUseRandomSubdomain = { checked: false };
|
const inputTempEmailUseRandomSubdomain = { checked: false };
|
||||||
|
const inputTempEmailUseFixedSubdomain = { checked: false };
|
||||||
|
const inputTempEmailSubdomainPrefix = { value: '' };
|
||||||
|
function getSelectedCloudflareTempEmailSubdomainMode() {
|
||||||
|
if (inputTempEmailUseFixedSubdomain.checked) return 'fixed';
|
||||||
|
if (inputTempEmailUseRandomSubdomain.checked) return 'random';
|
||||||
|
return 'none';
|
||||||
|
}
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM = 'random';
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED = 'fixed';
|
||||||
const inputAutoSkipFailures = { checked: false };
|
const inputAutoSkipFailures = { checked: false };
|
||||||
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '0' };
|
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '0' };
|
||||||
const inputAutoStepDelaySeconds = { value: '' };
|
const inputAutoStepDelaySeconds = { value: '' };
|
||||||
@@ -215,6 +224,7 @@ function normalizeLuckmailBaseUrl(value) { return String(value || '').trim(); }
|
|||||||
function normalizeLuckmailEmailType(value) { return String(value || '').trim() || 'ms_graph'; }
|
function normalizeLuckmailEmailType(value) { return String(value || '').trim() || 'ms_graph'; }
|
||||||
function normalizeCloudflareTempEmailBaseUrlValue(value) { return String(value || '').trim(); }
|
function normalizeCloudflareTempEmailBaseUrlValue(value) { return String(value || '').trim(); }
|
||||||
function normalizeCloudflareTempEmailReceiveMailboxValue(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 normalizeAccountRunHistoryHelperBaseUrlValue(value) { return String(value || '').trim(); }
|
||||||
function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) || 0; }
|
function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) || 0; }
|
||||||
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
|
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
|
||||||
@@ -272,8 +282,13 @@ const rowTempEmailBaseUrl = createRow();
|
|||||||
const rowTempEmailAdminAuth = createRow();
|
const rowTempEmailAdminAuth = createRow();
|
||||||
const rowTempEmailCustomAuth = createRow();
|
const rowTempEmailCustomAuth = createRow();
|
||||||
const rowTempEmailReceiveMailbox = createRow();
|
const rowTempEmailReceiveMailbox = createRow();
|
||||||
const rowTempEmailRandomSubdomainToggle = createRow();
|
const rowTempEmailLookupMode = createRow();
|
||||||
|
const rowTempEmailSubdomainMode = createRow();
|
||||||
|
const tempEmailSubdomainModeButtons = [];
|
||||||
|
const tempEmailSubdomainModeCaption = { textContent: '' };
|
||||||
|
const rowTempEmailFixedSubdomainPrefix = createRow();
|
||||||
const rowTempEmailDomain = createRow();
|
const rowTempEmailDomain = createRow();
|
||||||
|
const labelTempEmailDomain = { textContent: '' };
|
||||||
const cloudflareTempEmailSection = createRow();
|
const cloudflareTempEmailSection = createRow();
|
||||||
const hotmailSection = createRow();
|
const hotmailSection = createRow();
|
||||||
const mail2925Section = createRow();
|
const mail2925Section = createRow();
|
||||||
@@ -295,14 +310,30 @@ const rowHotmailLocalBaseUrl = createRow();
|
|||||||
const inputMail2925UseAccountPool = { checked: false };
|
const inputMail2925UseAccountPool = { checked: false };
|
||||||
const selectMailProvider = { value: 'icloud' };
|
const selectMailProvider = { value: 'icloud' };
|
||||||
const selectEmailGenerator = { value: 'duck', disabled: false, options: [] };
|
const selectEmailGenerator = { value: 'duck', disabled: false, options: [] };
|
||||||
|
const selectTempEmailDomain = { value: '' };
|
||||||
const selectIcloudTargetMailboxType = { value: 'icloud-inbox' };
|
const selectIcloudTargetMailboxType = { value: 'icloud-inbox' };
|
||||||
const selectIcloudForwardMailProvider = { value: 'gmail' };
|
const selectIcloudForwardMailProvider = { value: 'gmail' };
|
||||||
const selectIcloudHostPreference = { value: 'icloud.com.cn' };
|
const selectIcloudHostPreference = { value: 'icloud.com.cn' };
|
||||||
const inputTempEmailUseRandomSubdomain = { checked: false };
|
const inputTempEmailUseRandomSubdomain = { checked: false };
|
||||||
|
const inputTempEmailUseFixedSubdomain = { checked: false };
|
||||||
|
const inputTempEmailSubdomainPrefix = {
|
||||||
|
value: '',
|
||||||
|
classList: { toggle() {} },
|
||||||
|
setAttribute() {},
|
||||||
|
};
|
||||||
|
const tempEmailSubdomainPrefixFeedback = {
|
||||||
|
textContent: '',
|
||||||
|
classList: { toggle() {} },
|
||||||
|
};
|
||||||
|
const tempEmailEffectiveDomainPreview = { textContent: '' };
|
||||||
const inputRunCount = { disabled: false };
|
const inputRunCount = { disabled: false };
|
||||||
const currentAutoRun = { autoRunning: false };
|
const currentAutoRun = { autoRunning: false };
|
||||||
const MAIL_PROVIDER_LOGIN_CONFIGS = { gmail: { label: 'Gmail 邮箱' } };
|
const MAIL_PROVIDER_LOGIN_CONFIGS = { gmail: { label: 'Gmail 邮箱' } };
|
||||||
const ICLOUD_FORWARD_MAIL_PROVIDER_LABELS = { gmail: 'Gmail 邮箱' };
|
const ICLOUD_FORWARD_MAIL_PROVIDER_LABELS = { gmail: 'Gmail 邮箱' };
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_LOOKUP_MODE_REGISTRATION_EMAIL = 'registration-email';
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_NONE = 'none';
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM = 'random';
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED = 'fixed';
|
||||||
function normalizeIcloudHost(value) { return String(value || '').trim().toLowerCase(); }
|
function normalizeIcloudHost(value) { return String(value || '').trim().toLowerCase(); }
|
||||||
function normalizeIcloudTargetMailboxType(value) { return String(value || '').trim().toLowerCase() === 'forward-mailbox' ? 'forward-mailbox' : 'icloud-inbox'; }
|
function normalizeIcloudTargetMailboxType(value) { return String(value || '').trim().toLowerCase() === 'forward-mailbox' ? 'forward-mailbox' : 'icloud-inbox'; }
|
||||||
function normalizeIcloudForwardMailProvider(value) { return String(value || '').trim().toLowerCase() === 'gmail' ? 'gmail' : 'qq'; }
|
function normalizeIcloudForwardMailProvider(value) { return String(value || '').trim().toLowerCase() === 'gmail' ? 'gmail' : 'qq'; }
|
||||||
@@ -313,6 +344,27 @@ function isIcloudMailProvider() { return selectMailProvider.value === ICLOUD_PRO
|
|||||||
function usesCustomMailProviderPool() { return false; }
|
function usesCustomMailProviderPool() { return false; }
|
||||||
function usesGeneratedAliasMailProvider() { return false; }
|
function usesGeneratedAliasMailProvider() { return false; }
|
||||||
function getSelectedMail2925Mode() { return 'provide'; }
|
function getSelectedMail2925Mode() { return 'provide'; }
|
||||||
|
function getSelectedCloudflareTempEmailLookupMode() { return 'receive-mailbox'; }
|
||||||
|
function syncCloudflareTempEmailSubdomainModeButtons() {}
|
||||||
|
function getSelectedCloudflareTempEmailSubdomainMode() {
|
||||||
|
if (inputTempEmailUseFixedSubdomain.checked) return 'fixed';
|
||||||
|
if (inputTempEmailUseRandomSubdomain.checked) return 'random';
|
||||||
|
return 'none';
|
||||||
|
}
|
||||||
|
function normalizeCloudflareTempEmailDomainValue(value = '') { return String(value || '').trim().toLowerCase(); }
|
||||||
|
function normalizeCloudflareTempEmailSubdomainPrefixValue(value = '') { return String(value || '').trim().toLowerCase(); }
|
||||||
|
function getCloudflareTempEmailSubdomainPrefixValidation(value = '') {
|
||||||
|
const raw = String(value || '').trim();
|
||||||
|
return raw
|
||||||
|
? { raw, normalized: raw.toLowerCase(), valid: true, message: '' }
|
||||||
|
: { raw, normalized: '', valid: false, message: '请填写子域前缀' };
|
||||||
|
}
|
||||||
|
function buildCloudflareTempEmailEffectiveDomainValue(domain = '', subdomainPrefix = '', options = {}) {
|
||||||
|
const normalizedDomain = normalizeCloudflareTempEmailDomainValue(domain);
|
||||||
|
const normalizedPrefix = normalizeCloudflareTempEmailSubdomainPrefixValue(subdomainPrefix);
|
||||||
|
if (options.requirePrefix && !normalizedPrefix) return '';
|
||||||
|
return normalizedPrefix && normalizedDomain ? \`\${normalizedPrefix}.\${normalizedDomain}\` : normalizedDomain;
|
||||||
|
}
|
||||||
function getManagedAliasProviderUiCopy() { return null; }
|
function getManagedAliasProviderUiCopy() { return null; }
|
||||||
function getCurrentRegistrationEmailUiCopy() { return { buttonLabel: '获取邮箱', placeholder: '邮箱', label: '邮箱' }; }
|
function getCurrentRegistrationEmailUiCopy() { return { buttonLabel: '获取邮箱', placeholder: '邮箱', label: '邮箱' }; }
|
||||||
function updateMailLoginButtonState() {}
|
function updateMailLoginButtonState() {}
|
||||||
|
|||||||
@@ -201,6 +201,15 @@ const inputTempEmailAdminAuth = { value: '' };
|
|||||||
const inputTempEmailCustomAuth = { value: '' };
|
const inputTempEmailCustomAuth = { value: '' };
|
||||||
const inputTempEmailReceiveMailbox = { value: '' };
|
const inputTempEmailReceiveMailbox = { value: '' };
|
||||||
const inputTempEmailUseRandomSubdomain = { checked: false };
|
const inputTempEmailUseRandomSubdomain = { checked: false };
|
||||||
|
const inputTempEmailUseFixedSubdomain = { checked: false };
|
||||||
|
const inputTempEmailSubdomainPrefix = { value: '' };
|
||||||
|
function getSelectedCloudflareTempEmailSubdomainMode() {
|
||||||
|
if (inputTempEmailUseFixedSubdomain.checked) return 'fixed';
|
||||||
|
if (inputTempEmailUseRandomSubdomain.checked) return 'random';
|
||||||
|
return 'none';
|
||||||
|
}
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM = 'random';
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED = 'fixed';
|
||||||
const inputAutoSkipFailures = { checked: false };
|
const inputAutoSkipFailures = { checked: false };
|
||||||
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '0' };
|
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '0' };
|
||||||
const inputAutoStepDelaySeconds = { value: '' };
|
const inputAutoStepDelaySeconds = { value: '' };
|
||||||
@@ -253,6 +262,7 @@ function normalizeLuckmailBaseUrl(value) { return String(value || '').trim(); }
|
|||||||
function normalizeLuckmailEmailType(value) { return String(value || '').trim() || 'ms_graph'; }
|
function normalizeLuckmailEmailType(value) { return String(value || '').trim() || 'ms_graph'; }
|
||||||
function normalizeCloudflareTempEmailBaseUrlValue(value) { return String(value || '').trim(); }
|
function normalizeCloudflareTempEmailBaseUrlValue(value) { return String(value || '').trim(); }
|
||||||
function normalizeCloudflareTempEmailReceiveMailboxValue(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 normalizeAccountRunHistoryHelperBaseUrlValue(value) { return String(value || '').trim(); }
|
||||||
function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) || 0; }
|
function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) || 0; }
|
||||||
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
|
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
|
||||||
|
|||||||
@@ -976,6 +976,15 @@ const inputTempEmailAdminAuth = { value: '' };
|
|||||||
const inputTempEmailCustomAuth = { value: '' };
|
const inputTempEmailCustomAuth = { value: '' };
|
||||||
const inputTempEmailReceiveMailbox = { value: '' };
|
const inputTempEmailReceiveMailbox = { value: '' };
|
||||||
const inputTempEmailUseRandomSubdomain = { checked: false };
|
const inputTempEmailUseRandomSubdomain = { checked: false };
|
||||||
|
const inputTempEmailUseFixedSubdomain = { checked: false };
|
||||||
|
const inputTempEmailSubdomainPrefix = { value: '' };
|
||||||
|
function getSelectedCloudflareTempEmailSubdomainMode() {
|
||||||
|
if (inputTempEmailUseFixedSubdomain.checked) return 'fixed';
|
||||||
|
if (inputTempEmailUseRandomSubdomain.checked) return 'random';
|
||||||
|
return 'none';
|
||||||
|
}
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_RANDOM = 'random';
|
||||||
|
const CLOUDFLARE_TEMP_EMAIL_SUBDOMAIN_MODE_FIXED = 'fixed';
|
||||||
const inputAutoSkipFailures = { checked: false };
|
const inputAutoSkipFailures = { checked: false };
|
||||||
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '0' };
|
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '0' };
|
||||||
const inputAutoStepDelaySeconds = { value: '' };
|
const inputAutoStepDelaySeconds = { value: '' };
|
||||||
@@ -1067,6 +1076,7 @@ function normalizeLuckmailBaseUrl(value) { return String(value || '').trim(); }
|
|||||||
function normalizeLuckmailEmailType(value) { return String(value || '').trim() || 'ms_graph'; }
|
function normalizeLuckmailEmailType(value) { return String(value || '').trim() || 'ms_graph'; }
|
||||||
function normalizeCloudflareTempEmailBaseUrlValue(value) { return String(value || '').trim(); }
|
function normalizeCloudflareTempEmailBaseUrlValue(value) { return String(value || '').trim(); }
|
||||||
function normalizeCloudflareTempEmailReceiveMailboxValue(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 normalizeAccountRunHistoryHelperBaseUrlValue(value) { return String(value || '').trim(); }
|
||||||
function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) || 0; }
|
function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) || 0; }
|
||||||
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
|
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
|
||||||
|
|||||||
+2
-3
@@ -59,7 +59,7 @@
|
|||||||
- 展示 `Plus 模式` 开关、`账号接入策略` 与 `Plus 支付` 配置;`账号接入策略` 固定放在 `Plus 支付` 上方,只提供 `OAuth / 使用会话 JSON 导入` 两种接入方式,会话导入的 CPA / SUB2API 目标由上方 `来源` 自动决定,不支持会话导入的来源会直接禁用为仅 OAuth;支付方式支持 PayPal / GoPay / GPC,PayPal 展示账号池下拉与添加按钮,GoPay 展示手机号和 PIN,GPC 展示只读 API 地址、API Key、专用手机号、OTP 渠道、本地 OTP helper 开关与 URL、PIN;GPC 的 `购买卡密` 按钮打开卡密购买页,`转换 API Key` 按钮打开 `https://gpc.qlhazycoder.top/`;步骤列表会按支付方式和账号接入策略动态切换,普通模式的注册成功等待步骤不再显示或执行;Plus 模式下手机号注册不可用,只允许邮箱注册
|
- 展示 `Plus 模式` 开关、`账号接入策略` 与 `Plus 支付` 配置;`账号接入策略` 固定放在 `Plus 支付` 上方,只提供 `OAuth / 使用会话 JSON 导入` 两种接入方式,会话导入的 CPA / SUB2API 目标由上方 `来源` 自动决定,不支持会话导入的来源会直接禁用为仅 OAuth;支付方式支持 PayPal / GoPay / GPC,PayPal 展示账号池下拉与添加按钮,GoPay 展示手机号和 PIN,GPC 展示只读 API 地址、API Key、专用手机号、OTP 渠道、本地 OTP helper 开关与 URL、PIN;GPC 的 `购买卡密` 按钮打开卡密购买页,`转换 API Key` 按钮打开 `https://gpc.qlhazycoder.top/`;步骤列表会按支付方式和账号接入策略动态切换,普通模式的注册成功等待步骤不再显示或执行;Plus 模式下手机号注册不可用,只允许邮箱注册
|
||||||
- 展示 `执行范围` 配置;当前 UI 只在 codex/openai flow 显示,保存为通用的 `stepExecutionRangeByFlow`,用于指定允许执行的起止步骤。开启后,范围外节点在侧栏中显示为禁用态,手动按钮、手动跳过入口与进度计数只按允许节点计算。
|
- 展示 `执行范围` 配置;当前 UI 只在 codex/openai flow 显示,保存为通用的 `stepExecutionRangeByFlow`,用于指定允许执行的起止步骤。开启后,范围外节点在侧栏中显示为禁用态,手动按钮、手动跳过入口与进度计数只按允许节点计算。
|
||||||
- 为 Hotmail / 2925 账号池复用同一套“添加账号 / 取消添加 / 批量导入 / 收起列表”表单交互;共享的显隐控制放在 `sidepanel/account-pool-ui.js`,各自 manager 只保留 provider 相关字段校验与业务操作
|
- 为 Hotmail / 2925 账号池复用同一套“添加账号 / 取消添加 / 批量导入 / 收起列表”表单交互;共享的显隐控制放在 `sidepanel/account-pool-ui.js`,各自 manager 只保留 provider 相关字段校验与业务操作
|
||||||
- `Cloudflare Temp Email` 在侧栏中有独立区域,支持“按注册邮箱查信 / 按接收邮箱查信”切换、可编辑域名列表、随机子域名开关,以及教程/部署入口;域名选择由 `sidepanel/editable-list-picker.js` 统一承接
|
- `Cloudflare Temp Email` 在侧栏中有独立区域,支持“按注册邮箱查信 / 按接收邮箱查信”切换、可编辑域名列表、随机子域名开关、固定子域名开关与子域前缀输入,以及教程/部署入口;域名选择由 `sidepanel/editable-list-picker.js` 统一承接
|
||||||
- `SUB2API` 目标在分组配置下方额外暴露 `账号优先级`;该值会随设置一起持久化,并在后台直连创建账号时原样透传给 SUB2API 管理接口
|
- `SUB2API` 目标在分组配置下方额外暴露 `账号优先级`;该值会随设置一起持久化,并在后台直连创建账号时原样透传给 SUB2API 管理接口
|
||||||
- 点击“自动”或其他自动化入口时,sidepanel 会附带当前浏览器窗口 ID;后台后续查找、复用和接管标签页时优先锁定在这一个 automation window 内,避免串到其他窗口
|
- 点击“自动”或其他自动化入口时,sidepanel 会附带当前浏览器窗口 ID;后台后续查找、复用和接管标签页时优先锁定在这一个 automation window 内,避免串到其他窗口
|
||||||
|
|
||||||
@@ -273,7 +273,7 @@
|
|||||||
- 2925 是否启用号池模式 `mail2925UseAccountPool`
|
- 2925 是否启用号池模式 `mail2925UseAccountPool`
|
||||||
- 2925 当前选中的号池账号 ID `currentMail2925AccountId`
|
- 2925 当前选中的号池账号 ID `currentMail2925AccountId`
|
||||||
- Cloudflare / Temp Email 设置
|
- Cloudflare / Temp Email 设置
|
||||||
- Cloudflare Temp Email 细分配置:`cloudflareTempEmailLookupMode / cloudflareTempEmailUseRandomSubdomain / cloudflareTempEmailDomain / cloudflareTempEmailDomains`
|
- Cloudflare Temp Email 细分配置:`cloudflareTempEmailLookupMode / cloudflareTempEmailUseRandomSubdomain / cloudflareTempEmailUseFixedSubdomain / cloudflareTempEmailSubdomainPrefix / cloudflareTempEmailDomain / cloudflareTempEmailDomains`
|
||||||
- 注册方式 `signupMethod`
|
- 注册方式 `signupMethod`
|
||||||
- 接码开关、接码平台 `phoneSmsProvider`,以及 HeroSMS / 5sim 各自的 API Key、国家/地区、价格上限和平台扩展设置
|
- 接码开关、接码平台 `phoneSmsProvider`,以及 HeroSMS / 5sim 各自的 API Key、国家/地区、价格上限和平台扩展设置
|
||||||
- iCloud 相关偏好
|
- iCloud 相关偏好
|
||||||
@@ -1251,4 +1251,3 @@ Hide My Email 获取与管理链路:
|
|||||||
- `2925` 在 Step 4 / Step 8 现在会携带固定的步骤开始时间窗口,实际筛选下限为“步骤开始时间向前回看 10 分钟”。
|
- `2925` 在 Step 4 / Step 8 现在会携带固定的步骤开始时间窗口,实际筛选下限为“步骤开始时间向前回看 10 分钟”。
|
||||||
- 为了保留这段固定时间窗内已经到达的验证码邮件,后台不再在轮询开始前预先清空 2925 邮箱。
|
- 为了保留这段固定时间窗内已经到达的验证码邮件,后台不再在轮询开始前预先清空 2925 邮箱。
|
||||||
- `2925` 验证码最终提交成功后,后台仍会异步发送 `DELETE_ALL_EMAILS` 做收尾清理。
|
- `2925` 验证码最终提交成功后,后台仍会异步发送 `DELETE_ALL_EMAILS` 做收尾清理。
|
||||||
|
|
||||||
|
|||||||
+4
-5
@@ -23,7 +23,7 @@
|
|||||||
- `README.md`:面向使用者的精简说明文档,主要介绍项目用途、功能范围、快速开始与文档入口;不再承载过多技术实现细节。
|
- `README.md`:面向使用者的精简说明文档,主要介绍项目用途、功能范围、快速开始与文档入口;不再承载过多技术实现细节。
|
||||||
- `background.js`:扩展后台 Service Worker 入口壳,负责模块装配、初始化、全局常量、少量保留的领域函数与运行入口;当前已按 `activeFlowId` 装配 flow-aware 的步骤定义、执行注册表、自动运行与状态同步,OAuth 后链 5 分钟总预算只由 `openai + cpa` target capability 自动启用,其他来源与 flow 不启用该预算;`openai` flow 继续承接 `stepExecutionRangeByFlow`,`kiro` flow 走独立的“注册页 1-6 步 -> 桌面授权 7-8 步 -> `kiro.rs` 上传 9 步”链路,`grok` flow 走独立的“注册页 1-4 步 -> SSO Cookie 提取 5 步 -> `webchat2api` 上传 6 步”链路。
|
- `background.js`:扩展后台 Service Worker 入口壳,负责模块装配、初始化、全局常量、少量保留的领域函数与运行入口;当前已按 `activeFlowId` 装配 flow-aware 的步骤定义、执行注册表、自动运行与状态同步,OAuth 后链 5 分钟总预算只由 `openai + cpa` target capability 自动启用,其他来源与 flow 不启用该预算;`openai` flow 继续承接 `stepExecutionRangeByFlow`,`kiro` flow 走独立的“注册页 1-6 步 -> 桌面授权 7-8 步 -> `kiro.rs` 上传 9 步”链路,`grok` flow 走独立的“注册页 1-4 步 -> SSO Cookie 提取 5 步 -> `webchat2api` 上传 6 步”链路。
|
||||||
- `cloudmail-utils.js`:Cloud Mail / SkyMail 相关的纯工具函数,负责 API 地址、域名、鉴权头、邮件列表响应与邮件正文归一化。
|
- `cloudmail-utils.js`:Cloud Mail / SkyMail 相关的纯工具函数,负责 API 地址、域名、鉴权头、邮件列表响应与邮件正文归一化。
|
||||||
- `cloudflare-temp-email-utils.js`:Cloudflare Temp Email 相关的纯工具函数,负责 URL、域名、邮件内容与 MIME 数据归一化。
|
- `cloudflare-temp-email-utils.js`:Cloudflare Temp Email 相关的纯工具函数,负责 URL、基础域名、固定子域有效域名、邮件内容与 MIME 数据归一化。
|
||||||
- `gopay-utils.js`:GoPay / GPC Plus 支付相关纯工具函数,负责支付方式归一化、GoPay 手机号/OTP/PIN 归一化、GPC API 地址归一化、API Key 请求头、任务创建/查询/OTP/PIN/停止 URL 与余额响应解析。
|
- `gopay-utils.js`:GoPay / GPC Plus 支付相关纯工具函数,负责支付方式归一化、GoPay 手机号/OTP/PIN 归一化、GPC API 地址归一化、API Key 请求头、任务创建/查询/OTP/PIN/停止 URL 与余额响应解析。
|
||||||
- `hotmail-utils.js`:Hotmail 账号与验证码提取相关的纯工具函数,负责账号筛选、验证码匹配、第三方接口数据归一化。
|
- `hotmail-utils.js`:Hotmail 账号与验证码提取相关的纯工具函数,负责账号筛选、验证码匹配、第三方接口数据归一化。
|
||||||
- `icloud-utils.js`:iCloud 隐私邮箱相关的纯工具函数,负责 host、别名列表、保留状态、已用状态等归一化。
|
- `icloud-utils.js`:iCloud 隐私邮箱相关的纯工具函数,负责 host、别名列表、保留状态、已用状态等归一化。
|
||||||
@@ -255,7 +255,7 @@
|
|||||||
- `tests/background-account-history-settings.test.js`:测试账号运行历史的独立配置项归一化,不再复用 Hotmail 模式作为启停条件。
|
- `tests/background-account-history-settings.test.js`:测试账号运行历史的独立配置项归一化,不再复用 Hotmail 模式作为启停条件。
|
||||||
- `tests/background-auth-chain-guard.test.js`:测试认证顶层链路的去重、Stop 重抛、OAuth 总预算窗口和 `fetch-signup-code` 网络重试边界。
|
- `tests/background-auth-chain-guard.test.js`:测试认证顶层链路的去重、Stop 重抛、OAuth 总预算窗口和 `fetch-signup-code` 网络重试边界。
|
||||||
- `tests/background-auth-tab-snapshot.test.js`:测试认证标签快照在脚本执行失败时会回退到标签页 URL 做页面状态判断。
|
- `tests/background-auth-tab-snapshot.test.js`:测试认证标签快照在脚本执行失败时会回退到标签页 URL 做页面状态判断。
|
||||||
- `tests/background-cloudflare-temp-email-settings.test.js`:测试 Cloudflare Temp Email 随机子域名设置与 OAuth 总超时配置的持久化归一化。
|
- `tests/background-cloudflare-temp-email-settings.test.js`:测试 Cloudflare Temp Email 随机/固定子域名设置与 OAuth 总超时配置的持久化归一化。
|
||||||
- `tests/background-cpa-api.test.js`:测试 CPA 管理接口模块的地址归一化、OAuth 地址获取、callback 提交,以及 ChatGPT 会话导入 payload 构建与返回结果。
|
- `tests/background-cpa-api.test.js`:测试 CPA 管理接口模块的地址归一化、OAuth 地址获取、callback 提交,以及 ChatGPT 会话导入 payload 构建与返回结果。
|
||||||
- `tests/background-cpa-session-import.test.js`:测试 CPA 会话导入尾节点的标签页选择、会话读取、日志上报、结果透传和后台接线约束。
|
- `tests/background-cpa-session-import.test.js`:测试 CPA 会话导入尾节点的标签页选择、会话读取、日志上报、结果透传和后台接线约束。
|
||||||
- `tests/background-cpa-state-plumbing.test.js`:测试步骤 1 与消息路由对 CPA OAuth 运行态字段的保存、回写和 reset 接线。
|
- `tests/background-cpa-state-plumbing.test.js`:测试步骤 1 与消息路由对 CPA OAuth 运行态字段的保存、回写和 reset 接线。
|
||||||
@@ -338,7 +338,7 @@
|
|||||||
- `tests/qq-mail-content.test.js`:测试 QQ 邮箱内容脚本会把 runtime mail rule 的验证码模式转发到新邮件匹配链路。
|
- `tests/qq-mail-content.test.js`:测试 QQ 邮箱内容脚本会把 runtime mail rule 的验证码模式转发到新邮件匹配链路。
|
||||||
- `tests/run-count-unlimited.test.js`:测试自动运行轮数不再被 50 封顶,且旧 active 状态不会把手动输入轮数重置回去。
|
- `tests/run-count-unlimited.test.js`:测试自动运行轮数不再被 50 封顶,且旧 active 状态不会把手动输入轮数重置回去。
|
||||||
- `tests/cloudflare-temp-email-provider.test.js`:测试 Cloudflare Temp Email provider 的轮询与目标邮箱选择逻辑。
|
- `tests/cloudflare-temp-email-provider.test.js`:测试 Cloudflare Temp Email provider 的轮询与目标邮箱选择逻辑。
|
||||||
- `tests/cloudflare-temp-email-utils.test.js`:测试 Cloudflare Temp Email 工具层的 URL、域名、邮件解析逻辑。
|
- `tests/cloudflare-temp-email-utils.test.js`:测试 Cloudflare Temp Email 工具层的 URL、域名、固定子域有效域名与邮件解析逻辑。
|
||||||
- `tests/cloudmail-provider.test.js`:测试 Cloud Mail provider 的验证码轮询和生成/转发收件目标邮箱选择逻辑,并覆盖生成邮箱时对共享注册邮箱状态持久化的接入。
|
- `tests/cloudmail-provider.test.js`:测试 Cloud Mail provider 的验证码轮询和生成/转发收件目标邮箱选择逻辑,并覆盖生成邮箱时对共享注册邮箱状态持久化的接入。
|
||||||
- `tests/cloudmail-utils.test.js`:测试 Cloud Mail 工具层的 URL、域名、鉴权头、Token 与邮件响应归一化逻辑。
|
- `tests/cloudmail-utils.test.js`:测试 Cloud Mail 工具层的 URL、域名、鉴权头、Token 与邮件响应归一化逻辑。
|
||||||
- `tests/content-operation-delay.test.js`:测试内容脚本操作间延迟层的执行顺序、默认启用、排除步骤、悬挂恢复和 stop-aware sleep。
|
- `tests/content-operation-delay.test.js`:测试内容脚本操作间延迟层的执行顺序、默认启用、排除步骤、悬挂恢复和 stop-aware sleep。
|
||||||
@@ -382,7 +382,7 @@
|
|||||||
- `tests/grok-runner.test.js`:测试 Grok 注册页执行器对邮箱提交、验证码轮询、资料提交、SSO Cookie 提取、账号记录收尾和完成状态持久化的关键链路。
|
- `tests/grok-runner.test.js`:测试 Grok 注册页执行器对邮箱提交、验证码轮询、资料提交、SSO Cookie 提取、账号记录收尾和完成状态持久化的关键链路。
|
||||||
- `tests/sidepanel-auto-run-content-refresh.test.js`:测试点击“自动”时会先冻结当前轮数并刷新贡献内容更新摘要,且刷新失败或启动前状态回灌不会阻塞或改写自动流程启动目标。
|
- `tests/sidepanel-auto-run-content-refresh.test.js`:测试点击“自动”时会先冻结当前轮数并刷新贡献内容更新摘要,且刷新失败或启动前状态回灌不会阻塞或改写自动流程启动目标。
|
||||||
- `tests/sidepanel-auto-run-risk-warning.test.js`:测试自动运行在高轮数且未配置节点轮询时会弹出风险提醒。
|
- `tests/sidepanel-auto-run-risk-warning.test.js`:测试自动运行在高轮数且未配置节点轮询时会弹出风险提醒。
|
||||||
- `tests/sidepanel-cloudflare-temp-email-random-subdomain.test.js`:测试 Cloudflare Temp Email 独立区域、随机子域名开关、域名列表恢复与提示文案联动。
|
- `tests/sidepanel-cloudflare-temp-email-random-subdomain.test.js`:测试 Cloudflare Temp Email 独立区域、随机/固定子域名开关、域名列表恢复与提示文案联动。
|
||||||
- `tests/sidepanel-header-links.test.js`:测试侧边栏头部仓库首页与 Releases 入口的 HTML 接线与链接解析。
|
- `tests/sidepanel-header-links.test.js`:测试侧边栏头部仓库首页与 Releases 入口的 HTML 接线与链接解析。
|
||||||
- `tests/sidepanel-icloud-manager.test.js`:测试侧边栏 iCloud 管理器模块接线与空态渲染。
|
- `tests/sidepanel-icloud-manager.test.js`:测试侧边栏 iCloud 管理器模块接线与空态渲染。
|
||||||
- `tests/sidepanel-icloud-provider.test.js`:测试侧边栏 iCloud 登录地址解析、目标邮箱类型 / 转发邮箱 provider 保存、回显和显隐联动。
|
- `tests/sidepanel-icloud-provider.test.js`:测试侧边栏 iCloud 登录地址解析、目标邮箱类型 / 转发邮箱 provider 保存、回显和显隐联动。
|
||||||
@@ -433,4 +433,3 @@
|
|||||||
- `tests/verification-stop-propagation.test.js`:测试验证码流程在 Stop 场景下的错误传播与不中途降级。
|
- `tests/verification-stop-propagation.test.js`:测试验证码流程在 Stop 场景下的错误传播与不中途降级。
|
||||||
- `tests/verification-flow-polling.test.js`:测试 2925 长轮询参数、验证码提交流程中的 `beforeSubmit` 钩子执行顺序,以及步骤 8 提交验证码后进入手机号页时会把“继续手机号验证”状态交给步骤 9 处理。
|
- `tests/verification-flow-polling.test.js`:测试 2925 长轮询参数、验证码提交流程中的 `beforeSubmit` 钩子执行顺序,以及步骤 8 提交验证码后进入手机号页时会把“继续手机号验证”状态交给步骤 9 处理。
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user