diff --git a/README.md b/README.md index 1c2ac1e..52598a6 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,9 @@ - **多邮箱服务支持** - Tempmail.lol(临时邮箱,无需配置) - Outlook(IMAP + XOAUTH2,支持批量导入) - - 自定义域名(REST API) + - 自定义域名(两种子类型) + - **MoeMail**:标准 REST API,配置 API 地址 + API 密钥 + - **TempMail**:自部署 Cloudflare Worker 临时邮箱,配置 Worker 地址 + Admin 密码 - **注册模式** - 单次注册 @@ -278,7 +280,8 @@ docker-compose build --no-cache - CPA 上传始终直连,不经过代理 - Team Manager 上传始终直连,不经过代理 - 支付链接生成使用账号 access_token 鉴权,走全局代理配置 -- 无痕浏览器依次尝试 Chrome、Edge,未找到时返回失败提示 +- 无痕浏览器优先使用 playwright(注入 cookie 直达支付页);未安装时降级为系统 Chrome/Edge 无痕模式 +- 安装完整支付功能:`pip install playwright && playwright install chromium`(可选) - 订阅状态自动检测调用 `chatgpt.com/backend-api/me`,走全局代理 - 批量注册并发数上限为 50,线程池大小已相应调整 diff --git a/static/js/email_services.js b/static/js/email_services.js index 69abb4e..e142480 100644 --- a/static/js/email_services.js +++ b/static/js/email_services.js @@ -4,7 +4,7 @@ // 状态 let outlookServices = []; -let customServices = []; +let customServices = []; // 合并 custom_domain + temp_mail let selectedOutlook = new Set(); let selectedCustom = new Set(); @@ -31,7 +31,7 @@ const elements = { selectAllOutlook: document.getElementById('select-all-outlook'), batchDeleteOutlookBtn: document.getElementById('batch-delete-outlook-btn'), - // 自定义域名 + // 自定义域名(合并) customTable: document.getElementById('custom-services-table'), addCustomBtn: document.getElementById('add-custom-btn'), selectAllCustom: document.getElementById('select-all-custom'), @@ -47,30 +47,25 @@ const elements = { addCustomForm: document.getElementById('add-custom-form'), closeCustomModal: document.getElementById('close-custom-modal'), cancelAddCustom: document.getElementById('cancel-add-custom'), + customSubType: document.getElementById('custom-sub-type'), + addMoemailFields: document.getElementById('add-moemail-fields'), + addTempmailFields: document.getElementById('add-tempmail-fields'), // 编辑自定义域名模态框 editCustomModal: document.getElementById('edit-custom-modal'), editCustomForm: document.getElementById('edit-custom-form'), closeEditCustomModal: document.getElementById('close-edit-custom-modal'), cancelEditCustom: document.getElementById('cancel-edit-custom'), + editMoemailFields: document.getElementById('edit-moemail-fields'), + editTempmailFields: document.getElementById('edit-tempmail-fields'), + editCustomTypeBadge: document.getElementById('edit-custom-type-badge'), + editCustomSubTypeHidden: document.getElementById('edit-custom-sub-type-hidden'), // 编辑 Outlook 模态框 editOutlookModal: document.getElementById('edit-outlook-modal'), editOutlookForm: document.getElementById('edit-outlook-form'), closeEditOutlookModal: document.getElementById('close-edit-outlook-modal'), cancelEditOutlook: document.getElementById('cancel-edit-outlook'), - - // Temp-Mail 服务 - tempMailTable: document.getElementById('tempmail-services-table'), - addTempMailBtn: document.getElementById('add-tempmail-btn'), - addTempMailModal: document.getElementById('add-tempmail-modal'), - addTempMailForm: document.getElementById('add-tempmail-form'), - closeAddTempMailModal: document.getElementById('close-add-tempmail-modal'), - cancelAddTempMail: document.getElementById('cancel-add-tempmail'), - editTempMailModal: document.getElementById('edit-tempmail-modal'), - editTempMailForm: document.getElementById('edit-tempmail-form'), - closeEditTempMailModal: document.getElementById('close-edit-tempmail-modal'), - cancelEditTempMail: document.getElementById('cancel-edit-tempmail') }; // 初始化 @@ -78,7 +73,6 @@ document.addEventListener('DOMContentLoaded', () => { loadStats(); loadOutlookServices(); loadCustomServices(); - loadTempMailServices(); loadTempmailConfig(); initEventListeners(); }); @@ -105,11 +99,8 @@ function initEventListeners() { checkboxes.forEach(cb => { cb.checked = e.target.checked; const id = parseInt(cb.dataset.id); - if (e.target.checked) { - selectedOutlook.add(id); - } else { - selectedOutlook.delete(id); - } + if (e.target.checked) selectedOutlook.add(id); + else selectedOutlook.delete(id); }); updateBatchButtons(); }); @@ -117,80 +108,64 @@ function initEventListeners() { // Outlook 批量删除 elements.batchDeleteOutlookBtn.addEventListener('click', handleBatchDeleteOutlook); - // 添加自定义域名 - elements.addCustomBtn.addEventListener('click', () => { - elements.addCustomModal.classList.add('active'); - }); - - elements.closeCustomModal.addEventListener('click', () => { - elements.addCustomModal.classList.remove('active'); - }); - - elements.cancelAddCustom.addEventListener('click', () => { - elements.addCustomModal.classList.remove('active'); - }); - - elements.addCustomForm.addEventListener('submit', handleAddCustom); - - // 编辑自定义域名模态框 - elements.closeEditCustomModal.addEventListener('click', () => { - elements.editCustomModal.classList.remove('active'); - }); - - elements.cancelEditCustom.addEventListener('click', () => { - elements.editCustomModal.classList.remove('active'); - }); - - elements.editCustomForm.addEventListener('submit', handleEditCustom); - - // 编辑 Outlook 模态框 - elements.closeEditOutlookModal.addEventListener('click', () => { - elements.editOutlookModal.classList.remove('active'); - }); - - elements.cancelEditOutlook.addEventListener('click', () => { - elements.editOutlookModal.classList.remove('active'); - }); - - elements.editOutlookForm.addEventListener('submit', handleEditOutlook); - // 自定义域名全选 elements.selectAllCustom.addEventListener('change', (e) => { const checkboxes = elements.customTable.querySelectorAll('input[type="checkbox"][data-id]'); checkboxes.forEach(cb => { cb.checked = e.target.checked; const id = parseInt(cb.dataset.id); - if (e.target.checked) { - selectedCustom.add(id); - } else { - selectedCustom.delete(id); - } + if (e.target.checked) selectedCustom.add(id); + else selectedCustom.delete(id); }); }); + // 添加自定义域名 + elements.addCustomBtn.addEventListener('click', () => { + elements.addCustomForm.reset(); + switchAddSubType('moemail'); + elements.addCustomModal.classList.add('active'); + }); + elements.closeCustomModal.addEventListener('click', () => elements.addCustomModal.classList.remove('active')); + elements.cancelAddCustom.addEventListener('click', () => elements.addCustomModal.classList.remove('active')); + elements.addCustomForm.addEventListener('submit', handleAddCustom); + + // 类型切换(添加表单) + elements.customSubType.addEventListener('change', (e) => switchAddSubType(e.target.value)); + + // 编辑自定义域名 + elements.closeEditCustomModal.addEventListener('click', () => elements.editCustomModal.classList.remove('active')); + elements.cancelEditCustom.addEventListener('click', () => elements.editCustomModal.classList.remove('active')); + elements.editCustomForm.addEventListener('submit', handleEditCustom); + + // 编辑 Outlook + elements.closeEditOutlookModal.addEventListener('click', () => elements.editOutlookModal.classList.remove('active')); + elements.cancelEditOutlook.addEventListener('click', () => elements.editOutlookModal.classList.remove('active')); + elements.editOutlookForm.addEventListener('submit', handleEditOutlook); + // 临时邮箱配置 elements.tempmailForm.addEventListener('submit', handleSaveTempmail); elements.testTempmailBtn.addEventListener('click', handleTestTempmail); +} - // Temp-Mail 服务 - elements.addTempMailBtn.addEventListener('click', () => { - elements.addTempMailModal.classList.add('active'); - }); - elements.closeAddTempMailModal.addEventListener('click', () => { - elements.addTempMailModal.classList.remove('active'); - }); - elements.cancelAddTempMail.addEventListener('click', () => { - elements.addTempMailModal.classList.remove('active'); - }); - elements.addTempMailForm.addEventListener('submit', handleAddTempMail); +// 切换添加表单子类型 +function switchAddSubType(subType) { + elements.customSubType.value = subType; + if (subType === 'moemail') { + elements.addMoemailFields.style.display = ''; + elements.addTempmailFields.style.display = 'none'; + } else { + elements.addMoemailFields.style.display = 'none'; + elements.addTempmailFields.style.display = ''; + } +} - elements.closeEditTempMailModal.addEventListener('click', () => { - elements.editTempMailModal.classList.remove('active'); - }); - elements.cancelEditTempMail.addEventListener('click', () => { - elements.editTempMailModal.classList.remove('active'); - }); - elements.editTempMailForm.addEventListener('submit', handleEditTempMail); +// 切换编辑表单子类型显示 +function switchEditSubType(subType) { + elements.editCustomSubTypeHidden.value = subType; + const isMoe = subType === 'moemail'; + elements.editMoemailFields.style.display = isMoe ? '' : 'none'; + elements.editTempmailFields.style.display = isMoe ? 'none' : ''; + elements.editCustomTypeBadge.textContent = isMoe ? '🔗 MoeMail(自定义域名 API)' : '📮 TempMail(自部署 Cloudflare Worker)'; } // 加载统计信息 @@ -198,7 +173,7 @@ async function loadStats() { try { const data = await api.get('/email-services/stats'); elements.outlookCount.textContent = data.outlook_count || 0; - elements.customCount.textContent = data.custom_count || 0; + elements.customCount.textContent = (data.custom_count || 0) + (data.temp_mail_count || 0); elements.tempmailStatus.textContent = data.tempmail_available ? '可用' : '不可用'; elements.totalEnabled.textContent = data.enabled_count || 0; } catch (error) { @@ -229,10 +204,7 @@ async function loadOutlookServices() { elements.outlookTable.innerHTML = outlookServices.map(service => ` - - - + ${escapeHtml(service.config?.email || service.name)} @@ -248,65 +220,50 @@ async function loadOutlookServices() { ${format.date(service.last_used)}
- - - - + + + +
`).join(''); - // 绑定复选框事件 elements.outlookTable.querySelectorAll('input[type="checkbox"][data-id]').forEach(cb => { cb.addEventListener('change', (e) => { const id = parseInt(e.target.dataset.id); - if (e.target.checked) { - selectedOutlook.add(id); - } else { - selectedOutlook.delete(id); - } + if (e.target.checked) selectedOutlook.add(id); + else selectedOutlook.delete(id); updateBatchButtons(); }); }); } catch (error) { console.error('加载 Outlook 服务失败:', error); - elements.outlookTable.innerHTML = ` - - -
-
-
加载失败
-
- - - `; + elements.outlookTable.innerHTML = `
加载失败
`; } } -// 加载自定义域名服务 +// 加载自定义域名服务(custom_domain + temp_mail 合并) async function loadCustomServices() { try { - const data = await api.get('/email-services?service_type=custom_domain'); - customServices = data.services || []; + const [r1, r2] = await Promise.all([ + api.get('/email-services?service_type=custom_domain'), + api.get('/email-services?service_type=temp_mail') + ]); + customServices = [ + ...(r1.services || []).map(s => ({ ...s, _subType: 'moemail' })), + ...(r2.services || []).map(s => ({ ...s, _subType: 'tempmail' })) + ]; if (customServices.length === 0) { elements.customTable.innerHTML = ` - +
📭
暂无自定义域名服务
-
点击"添加服务"按钮创建新服务
+
点击「添加服务」按钮创建新服务
@@ -314,49 +271,35 @@ async function loadCustomServices() { return; } - elements.customTable.innerHTML = customServices.map(service => ` + elements.customTable.innerHTML = customServices.map(service => { + const isMoe = service._subType === 'moemail'; + const typeLabel = isMoe ? 'MoeMail' : 'TempMail'; + const addr = isMoe ? (service.config?.base_url || '-') : (service.config?.base_url || '-'); + return ` - - - + ${escapeHtml(service.name)} - ${escapeHtml(service.config?.base_url || '-')} - - - ${service.enabled ? '启用' : '禁用'} - - + ${typeLabel} + ${escapeHtml(addr)} + ${service.enabled ? '启用' : '禁用'} ${service.priority} ${format.date(service.last_used)}
- - - - + + + +
- - `).join(''); + `; + }).join(''); - // 绑定复选框事件 elements.customTable.querySelectorAll('input[type="checkbox"][data-id]').forEach(cb => { cb.addEventListener('change', (e) => { const id = parseInt(e.target.dataset.id); - if (e.target.checked) { - selectedCustom.add(id); - } else { - selectedCustom.delete(id); - } + if (e.target.checked) selectedCustom.add(id); + else selectedCustom.delete(id); }); }); @@ -381,10 +324,7 @@ async function loadTempmailConfig() { // Outlook 导入 async function handleOutlookImport() { const data = elements.outlookImportData.value.trim(); - if (!data) { - toast.error('请输入导入数据'); - return; - } + if (!data) { toast.error('请输入导入数据'); return; } elements.outlookImportBtn.disabled = true; elements.outlookImportBtn.textContent = '导入中...'; @@ -402,14 +342,7 @@ async function handleOutlookImport() { ✅ 成功导入: ${result.success || 0} ❌ 失败: ${result.failed || 0} - ${result.errors?.length ? ` -
- 错误详情: - -
- ` : ''} + ${result.errors?.length ? `
错误详情:
` : ''} `; if (result.success > 0) { @@ -418,7 +351,6 @@ async function handleOutlookImport() { loadStats(); elements.outlookImportData.value = ''; } - } catch (error) { toast.error('导入失败: ' + error.message); } finally { @@ -427,19 +359,34 @@ async function handleOutlookImport() { } } -// 添加自定义域名服务 +// 添加自定义域名服务(根据子类型区分) async function handleAddCustom(e) { e.preventDefault(); - const formData = new FormData(e.target); - const data = { - service_type: 'custom_domain', - name: formData.get('name'), - config: { + const subType = formData.get('sub_type'); + + let serviceType, config; + if (subType === 'moemail') { + serviceType = 'custom_domain'; + config = { base_url: formData.get('api_url'), api_key: formData.get('api_key'), default_domain: formData.get('domain') - }, + }; + } else { + serviceType = 'temp_mail'; + config = { + base_url: formData.get('tm_base_url'), + admin_password: formData.get('tm_admin_password'), + domain: formData.get('tm_domain'), + enable_prefix: true + }; + } + + const data = { + service_type: serviceType, + name: formData.get('name'), + config, enabled: formData.get('enabled') === 'on', priority: parseInt(formData.get('priority')) || 0 }; @@ -473,11 +420,8 @@ async function toggleService(id, enabled) { async function testService(id) { try { const result = await api.post(`/email-services/${id}/test`); - if (result.success) { - toast.success('测试成功'); - } else { - toast.error('测试失败: ' + (result.error || '未知错误')); - } + if (result.success) toast.success('测试成功'); + else toast.error('测试失败: ' + (result.error || '未知错误')); } catch (error) { toast.error('测试失败: ' + error.message); } @@ -487,7 +431,6 @@ async function testService(id) { async function deleteService(id, name) { const confirmed = await confirm(`确定要删除 "${name}" 吗?`); if (!confirmed) return; - try { await api.delete(`/email-services/${id}`); toast.success('已删除'); @@ -504,10 +447,8 @@ async function deleteService(id, name) { // 批量删除 Outlook async function handleBatchDeleteOutlook() { if (selectedOutlook.size === 0) return; - const confirmed = await confirm(`确定要删除选中的 ${selectedOutlook.size} 个账户吗?`); if (!confirmed) return; - try { const result = await api.request('/email-services/outlook/batch', { method: 'DELETE', @@ -525,7 +466,6 @@ async function handleBatchDeleteOutlook() { // 保存临时邮箱配置 async function handleSaveTempmail(e) { e.preventDefault(); - try { await api.post('/settings/tempmail', { api_url: elements.tempmailApi.value, @@ -541,17 +481,12 @@ async function handleSaveTempmail(e) { async function handleTestTempmail() { elements.testTempmailBtn.disabled = true; elements.testTempmailBtn.textContent = '测试中...'; - try { const result = await api.post('/email-services/test-tempmail', { api_url: elements.tempmailApi.value }); - - if (result.success) { - toast.success('临时邮箱连接正常'); - } else { - toast.error('连接失败: ' + (result.error || '未知错误')); - } + if (result.success) toast.success('临时邮箱连接正常'); + else toast.error('连接失败: ' + (result.error || '未知错误')); } catch (error) { toast.error('测试失败: ' + error.message); } finally { @@ -577,27 +512,32 @@ function escapeHtml(text) { // ============== 编辑功能 ============== -// 编辑自定义域名服务 -async function editCustomService(id) { +// 编辑自定义域名服务(支持 moemail / tempmail) +async function editCustomService(id, subType) { try { - // 获取完整的服务详情 const service = await api.get(`/email-services/${id}/full`); + const resolvedSubType = subType || (service.service_type === 'temp_mail' ? 'tempmail' : 'moemail'); - // 填充表单 document.getElementById('edit-custom-id').value = service.id; document.getElementById('edit-custom-name').value = service.name || ''; - document.getElementById('edit-custom-api-url').value = service.config?.base_url || ''; - document.getElementById('edit-custom-api-key').value = service.config?.api_key || ''; - document.getElementById('edit-custom-domain').value = service.config?.domain || ''; document.getElementById('edit-custom-priority').value = service.priority || 0; document.getElementById('edit-custom-enabled').checked = service.enabled; - // 清空密码提示 - document.getElementById('edit-custom-api-key').placeholder = service.config?.has_api_key ? '已设置,留空保持不变' : 'API Key'; + switchEditSubType(resolvedSubType); + + if (resolvedSubType === 'moemail') { + document.getElementById('edit-custom-api-url').value = service.config?.base_url || ''; + document.getElementById('edit-custom-api-key').value = ''; + document.getElementById('edit-custom-api-key').placeholder = service.config?.has_api_key ? '已设置,留空保持不变' : 'API Key'; + document.getElementById('edit-custom-domain').value = service.config?.default_domain || service.config?.domain || ''; + } else { + document.getElementById('edit-tm-base-url').value = service.config?.base_url || ''; + document.getElementById('edit-tm-admin-password').value = ''; + document.getElementById('edit-tm-admin-password').placeholder = service.config?.admin_password ? '已设置,留空保持不变' : '请输入 Admin 密码'; + document.getElementById('edit-tm-domain').value = service.config?.domain || ''; + } - // 显示模态框 elements.editCustomModal.classList.add('active'); - } catch (error) { toast.error('获取服务信息失败: ' + error.message); } @@ -606,31 +546,35 @@ async function editCustomService(id) { // 保存编辑自定义域名服务 async function handleEditCustom(e) { e.preventDefault(); - const id = document.getElementById('edit-custom-id').value; const formData = new FormData(e.target); + const subType = formData.get('sub_type'); + + let config; + if (subType === 'moemail') { + config = { + base_url: formData.get('api_url'), + default_domain: formData.get('domain') + }; + const apiKey = formData.get('api_key'); + if (apiKey && apiKey.trim()) config.api_key = apiKey.trim(); + } else { + config = { + base_url: formData.get('tm_base_url'), + domain: formData.get('tm_domain'), + enable_prefix: true + }; + const pwd = formData.get('tm_admin_password'); + if (pwd && pwd.trim()) config.admin_password = pwd.trim(); + } - // 构建更新数据 const updateData = { name: formData.get('name'), priority: parseInt(formData.get('priority')) || 0, - enabled: formData.get('enabled') === 'on' + enabled: formData.get('enabled') === 'on', + config }; - // 构建配置 - const config = { - base_url: formData.get('api_url'), - default_domain: formData.get('domain') - }; - - // 只有在填写了 API Key 时才更新 - const apiKey = formData.get('api_key'); - if (apiKey && apiKey.trim()) { - config.api_key = apiKey.trim(); - } - - updateData.config = config; - try { await api.patch(`/email-services/${id}`, updateData); toast.success('服务更新成功'); @@ -645,10 +589,7 @@ async function handleEditCustom(e) { // 编辑 Outlook 服务 async function editOutlookService(id) { try { - // 获取完整的服务详情 const service = await api.get(`/email-services/${id}/full`); - - // 填充表单 document.getElementById('edit-outlook-id').value = service.id; document.getElementById('edit-outlook-email').value = service.config?.email || service.name || ''; document.getElementById('edit-outlook-password').value = ''; @@ -658,10 +599,7 @@ async function editOutlookService(id) { document.getElementById('edit-outlook-refresh-token').placeholder = service.config?.refresh_token ? '已设置,留空保持不变' : 'OAuth Refresh Token'; document.getElementById('edit-outlook-priority').value = service.priority || 0; document.getElementById('edit-outlook-enabled').checked = service.enabled; - - // 显示模态框 elements.editOutlookModal.classList.add('active'); - } catch (error) { toast.error('获取服务信息失败: ' + error.message); } @@ -670,11 +608,9 @@ async function editOutlookService(id) { // 保存编辑 Outlook 服务 async function handleEditOutlook(e) { e.preventDefault(); - const id = document.getElementById('edit-outlook-id').value; const formData = new FormData(e.target); - // 获取当前服务信息以保留未修改的敏感字段 let currentService; try { currentService = await api.get(`/email-services/${id}/full`); @@ -683,23 +619,18 @@ async function handleEditOutlook(e) { return; } - // 构建更新数据 const updateData = { - name: formData.get('email'), // 使用邮箱作为名称 + name: formData.get('email'), priority: parseInt(formData.get('priority')) || 0, - enabled: formData.get('enabled') === 'on' + enabled: formData.get('enabled') === 'on', + config: { + email: formData.get('email'), + password: formData.get('password')?.trim() || currentService.config?.password || '', + client_id: formData.get('client_id')?.trim() || currentService.config?.client_id || '', + refresh_token: formData.get('refresh_token')?.trim() || currentService.config?.refresh_token || '' + } }; - // 构建配置,保留未修改的敏感字段 - const config = { - email: formData.get('email'), - password: formData.get('password')?.trim() || currentService.config?.password || '', - client_id: formData.get('client_id')?.trim() || currentService.config?.client_id || '', - refresh_token: formData.get('refresh_token')?.trim() || currentService.config?.refresh_token || '' - }; - - updateData.config = config; - try { await api.patch(`/email-services/${id}`, updateData); toast.success('账户更新成功'); @@ -710,134 +641,3 @@ async function handleEditOutlook(e) { toast.error('更新失败: ' + error.message); } } - - -// ============== Temp-Mail 服务功能 ============== - -// 加载 Temp-Mail 服务列表 -async function loadTempMailServices() { - try { - const data = await api.get('/email-services?service_type=temp_mail'); - const services = data.services || []; - - if (services.length === 0) { - elements.tempMailTable.innerHTML = ` - -
-
📮
-
暂无 Temp-Mail 服务
-
点击「添加服务」配置自部署 Cloudflare Worker 临时邮箱
-
- - `; - return; - } - - elements.tempMailTable.innerHTML = services.map(service => { - const config = service.config || {}; - return ` - - ${escapeHtml(service.name)} - ${escapeHtml(config.base_url || '-')} - ${escapeHtml(config.domain || '-')} - - - ${service.enabled ? '已启用' : '已禁用'} - - - ${service.priority || 0} - -
- - - - -
- - - `; - }).join(''); - } catch (error) { - console.error('加载 Temp-Mail 服务失败:', error); - } -} - -// 添加 Temp-Mail 服务 -async function handleAddTempMail(e) { - e.preventDefault(); - const formData = new FormData(e.target); - const data = { - service_type: 'temp_mail', - name: formData.get('name'), - config: { - base_url: formData.get('base_url'), - admin_password: formData.get('admin_password'), - domain: formData.get('domain'), - enable_prefix: true - }, - enabled: formData.get('enabled') === 'on', - priority: parseInt(formData.get('priority')) || 0 - }; - try { - await api.post('/email-services', data); - toast.success('服务添加成功'); - elements.addTempMailModal.classList.remove('active'); - e.target.reset(); - loadTempMailServices(); - loadStats(); - } catch (error) { - toast.error('添加失败: ' + error.message); - } -} - -// 编辑 Temp-Mail 服务 -async function editTempMailService(id) { - try { - const service = await api.get(`/email-services/${id}/full`); - document.getElementById('edit-tm-id').value = service.id; - document.getElementById('edit-tm-name').value = service.name || ''; - document.getElementById('edit-tm-base-url').value = service.config?.base_url || ''; - document.getElementById('edit-tm-admin-password').value = ''; - document.getElementById('edit-tm-admin-password').placeholder = service.config?.admin_password ? '已设置,留空保持不变' : '请输入 Admin 密码'; - document.getElementById('edit-tm-domain').value = service.config?.domain || ''; - document.getElementById('edit-tm-priority').value = service.priority || 0; - document.getElementById('edit-tm-enabled').checked = service.enabled; - elements.editTempMailModal.classList.add('active'); - } catch (error) { - toast.error('获取服务信息失败: ' + error.message); - } -} - -// 保存编辑 Temp-Mail 服务 -async function handleEditTempMail(e) { - e.preventDefault(); - const id = document.getElementById('edit-tm-id').value; - const formData = new FormData(e.target); - const config = { - base_url: formData.get('base_url'), - domain: formData.get('domain'), - enable_prefix: true - }; - // 只有填写了密码才更新 - const pwd = formData.get('admin_password'); - if (pwd && pwd.trim()) { - config.admin_password = pwd.trim(); - } - const updateData = { - name: formData.get('name'), - priority: parseInt(formData.get('priority')) || 0, - enabled: formData.get('enabled') === 'on', - config - }; - try { - await api.patch(`/email-services/${id}`, updateData); - toast.success('服务更新成功'); - elements.editTempMailModal.classList.remove('active'); - loadTempMailServices(); - loadStats(); - } catch (error) { - toast.error('更新失败: ' + error.message); - } -} diff --git a/templates/email_services.html b/templates/email_services.html index dce1c41..dbe4e9c 100644 --- a/templates/email_services.html +++ b/templates/email_services.html @@ -92,7 +92,7 @@ - +

🔗 自定义域名服务

@@ -105,7 +105,8 @@ 名称 - API 地址 + 类型 + 地址 状态 优先级 最后使用 @@ -114,41 +115,7 @@ - -
-
-
-
- - - - -
-
- - - -
-
-

📮 Temp-Mail 服务(自部署)

- -
-
-
- - - - - - - - - - - - - -
名称Worker 地址邮箱域名状态优先级操作
+
@@ -223,7 +190,7 @@
- +