From 9bd31c38201dfdce014cf9590255cffacad4cbe0 Mon Sep 17 00:00:00 2001 From: luekongbai Date: Tue, 13 Jan 2026 22:19:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=B4=E6=97=B6=E9=82=AE?= =?UTF-8?q?=E7=AE=B1=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 42 +++- templates/index.html | 497 ++++++++++++++++++++++++++++++++++++--- web_outlook_app.py | 541 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 1043 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 4615d26..ea1b0ec 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ - 📤 **导出功能** - 支持按分组导出邮箱账号信息 - 🎨 **现代化 UI** - 简洁美观的四栏式界面布局 - ⚡ **性能优化** - 邮箱列表缓存,快速切换分组 +- 🔥 **临时邮箱** - 集成 GPTMail API,一键生成临时邮箱 +- ⚙️ **系统设置** - 支持在线修改登录密码和 API Key ### 界面布局 Web 应用采用四栏式布局设计: @@ -48,7 +50,7 @@ python web_outlook_app.py 启动后访问:http://127.0.0.1:5001 -默认登录密码:`admin123`(可在 [`web_outlook_app.py`](web_outlook_app.py:27) 中修改 `LOGIN_PASSWORD` 变量) +默认登录密码:`admin123`(可在 Web 界面的「设置」中修改) ### 3. 运行命令行测试工具 @@ -112,16 +114,50 @@ Web 应用提供以下 API 端点: | `/api/email//` | GET | 获取邮件详情 | | `/api/groups//export` | GET | 导出分组邮箱 | | `/api/accounts/export` | GET | 导出所有邮箱 | +| `/api/temp-emails` | GET | 获取所有临时邮箱 | +| `/api/temp-emails/generate` | POST | 生成新的临时邮箱 | +| `/api/temp-emails/` | DELETE | 删除临时邮箱 | +| `/api/temp-emails//messages` | GET | 获取临时邮箱邮件列表 | +| `/api/temp-emails//messages/` | GET | 获取临时邮件详情 | +| `/api/temp-emails//clear` | DELETE | 清空临时邮箱所有邮件 | +| `/api/settings` | GET | 获取系统设置 | +| `/api/settings` | PUT | 更新系统设置 | + +### 临时邮箱功能 + +系统集成了 GPTMail API 提供临时邮箱服务: + +1. **生成临时邮箱** - 点击「临时邮箱」分组,然后点击「生成临时邮箱」按钮 +2. **查看邮件** - 选择临时邮箱后点击「获取邮件」按钮 +3. **清空邮件** - 点击临时邮箱旁的「清空」按钮,清空该邮箱的所有邮件 +4. **删除邮箱** - 点击临时邮箱旁的「删除」按钮,删除邮箱及其所有邮件 + +临时邮箱数据会存储在本地数据库中,方便后续查看。 + +### 系统设置 + +点击导航栏的「⚙️ 设置」按钮,可以修改以下配置: + +1. **登录密码** - 修改 Web 界面的登录密码 +2. **GPTMail API Key** - 设置临时邮箱功能所需的 API Key + +设置会保存在数据库中,重启应用后仍然有效。 ## ⚙️ 配置说明 ### Web 应用配置 -在 [`web_outlook_app.py`](web_outlook_app.py) 中可以修改以下配置: +以下配置可以在 Web 界面的「设置」中修改: + +| 配置项 | 默认值 | 说明 | +|--------|--------|------| +| 登录密码 | `admin123` | Web 界面登录密码 | +| GPTMail API Key | 空 | 临时邮箱功能的 API Key | + +以下配置需要在 [`web_outlook_app.py`](web_outlook_app.py) 中修改: | 配置项 | 默认值 | 说明 | |--------|--------|------| -| `LOGIN_PASSWORD` | `admin123` | 登录密码 | | `DATABASE` | `outlook_accounts.db` | SQLite 数据库文件 | | `IMAP_SERVER_OLD` | `outlook.office365.com` | 旧版 IMAP 服务器 | | `IMAP_SERVER_NEW` | `outlook.live.com` | 新版 IMAP 服务器 | diff --git a/templates/index.html b/templates/index.html index f49ca7e..7db6e1d 100644 --- a/templates/index.html +++ b/templates/index.html @@ -989,6 +989,7 @@ @@ -1219,6 +1220,32 @@ + + +
@@ -1233,6 +1260,8 @@ let accountsCache = {}; // 缓存各分组的邮箱列表 let editingGroupId = null; let selectedColor = '#1a1a1a'; + let isTempEmailGroup = false; // 是否是临时邮箱分组 + let tempEmailGroupId = null; // 临时邮箱分组 ID // 初始化 document.addEventListener('DOMContentLoaded', function() { @@ -1299,6 +1328,13 @@ if (data.success) { groups = data.groups; + + // 找到临时邮箱分组 + const tempGroup = groups.find(g => g.name === '临时邮箱'); + if (tempGroup) { + tempEmailGroupId = tempGroup.id; + } + renderGroupList(data.groups); updateGroupSelects(); @@ -1307,7 +1343,11 @@ const group = groups.find(g => g.id === currentGroupId); if (group) { // 刷新当前分组的邮箱列表 - loadAccountsByGroup(currentGroupId, true); + if (currentGroupId === tempEmailGroupId) { + loadTempEmails(true); + } else { + loadAccountsByGroup(currentGroupId, true); + } } } } @@ -1330,36 +1370,45 @@ return; } - container.innerHTML = groups.map(group => ` -
-
-
- ${escapeHtml(group.name)} -
-
- ${group.account_count || 0} 个邮箱 -
- - ${group.id !== 1 ? `` : ''} + container.innerHTML = groups.map(group => { + const isSystem = group.is_system === 1 || group.name === '临时邮箱'; + const isTempGroup = group.name === '临时邮箱'; + const isDefault = group.id === 1; + + return ` +
+
+
+ ${escapeHtml(group.name)}${isTempGroup ? ' ⚡' : ''} +
+
+ ${group.account_count || 0} 个邮箱 +
+ ${!isSystem ? `` : ''} + ${!isDefault && !isSystem ? `` : ''} +
-
- `).join(''); + `; + }).join(''); } // 选择分组 async function selectGroup(groupId) { currentGroupId = groupId; + // 检查是否是临时邮箱分组 + const group = groups.find(g => g.id === groupId); + isTempEmailGroup = group && group.name === '临时邮箱'; + // 更新分组列表 UI document.querySelectorAll('.group-item').forEach(item => { item.classList.toggle('active', parseInt(item.dataset.groupId) === groupId); }); // 更新邮箱面板标题 - const group = groups.find(g => g.id === groupId); if (group) { document.getElementById('currentGroupName').textContent = group.name; document.getElementById('currentGroupColor').style.backgroundColor = group.color || '#666'; @@ -1371,8 +1420,29 @@ } } + // 更新底部按钮 + updateAccountPanelFooter(); + // 加载该分组的邮箱 - await loadAccountsByGroup(groupId); + if (isTempEmailGroup) { + await loadTempEmails(); + } else { + await loadAccountsByGroup(groupId); + } + } + + // 更新账号面板底部按钮 + function updateAccountPanelFooter() { + const footer = document.querySelector('.account-panel-footer'); + if (isTempEmailGroup) { + footer.innerHTML = ` + + `; + } else { + footer.innerHTML = ` + + `; + } } // 加载分组下的账号 @@ -1568,25 +1638,318 @@ } } - // ==================== 账号相关 ==================== + // ==================== 临时邮箱相关 ==================== - // 选择账号 - function selectAccount(email) { + // 加载临时邮箱列表 + async function loadTempEmails(forceRefresh = false) { + const container = document.getElementById('accountList'); + + if (!forceRefresh && accountsCache['temp']) { + renderTempEmailList(accountsCache['temp']); + return; + } + + container.innerHTML = '
'; + + try { + const response = await fetch('/api/temp-emails'); + const data = await response.json(); + + if (data.success) { + accountsCache['temp'] = data.emails; + renderTempEmailList(data.emails); + + const group = groups.find(g => g.name === '临时邮箱'); + if (group) { + group.account_count = data.emails.length; + renderGroupList(groups); + } + } + } catch (error) { + container.innerHTML = '
加载失败
'; + } + } + + // 渲染临时邮箱列表 + function renderTempEmailList(emails) { + const container = document.getElementById('accountList'); + + if (emails.length === 0) { + container.innerHTML = ` +
+
⚡
+
暂无临时邮箱
点击下方按钮生成
+
+ `; + return; + } + + container.innerHTML = emails.map(email => ` + + `).join(''); + } + + // 生成临时邮箱 + async function generateTempEmail() { + // 获取按钮并显示加载状态 + const btn = document.querySelector('.account-panel-footer .add-account-btn'); + const originalText = btn.textContent; + btn.disabled = true; + btn.textContent = '⏳ 生成中...'; + btn.style.opacity = '0.7'; + btn.style.cursor = 'not-allowed'; + + try { + const response = await fetch('/api/temp-emails/generate', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({}) + }); + + const data = await response.json(); + + if (data.success) { + showToast(`临时邮箱已生成: ${data.email}`, 'success'); + delete accountsCache['temp']; + loadTempEmails(true); + loadGroups(); + } else { + showToast(data.error || '生成失败', 'error'); + } + } catch (error) { + showToast('生成临时邮箱失败', 'error'); + } finally { + // 恢复按钮状态 + btn.disabled = false; + btn.textContent = originalText; + btn.style.opacity = '1'; + btn.style.cursor = 'pointer'; + } + } + + // 选择临时邮箱 + function selectTempEmail(email) { currentAccount = email; + isTempEmailGroup = true; - // 更新顶部当前账号显示 document.getElementById('currentAccount').classList.add('show'); - document.getElementById('currentAccountEmail').textContent = email; + document.getElementById('currentAccountEmail').textContent = email + ' (临时)'; - // 更新邮箱列表 UI document.querySelectorAll('.account-item').forEach(item => { item.classList.remove('active'); - if (item.querySelector('.account-email').textContent === email) { + const emailEl = item.querySelector('.account-email'); + if (emailEl && emailEl.textContent.includes(email)) { + item.classList.add('active'); + } + }); + + document.getElementById('emailList').innerHTML = ` +
+
📬
+
点击"获取邮件"按钮获取邮件
+
+ `; + + document.getElementById('emailDetail').innerHTML = ` +
+
📄
+
选择一封邮件查看详情
+
+ `; + document.getElementById('emailDetailToolbar').style.display = 'none'; + document.getElementById('emailCount').textContent = ''; + document.getElementById('methodTag').style.display = 'none'; + } + + // 清空临时邮箱的所有邮件 + async function clearTempEmailMessages(email) { + if (!confirm(`确定要清空临时邮箱 ${email} 的所有邮件吗?`)) { + return; + } + + try { + const response = await fetch(`/api/temp-emails/${encodeURIComponent(email)}/clear`, { + method: 'DELETE' + }); + + const data = await response.json(); + + if (data.success) { + showToast('邮件已清空', 'success'); + + // 如果当前选中的就是这个邮箱,清空邮件列表 + if (currentAccount === email) { + currentEmails = []; + document.getElementById('emailCount').textContent = '(0)'; + document.getElementById('emailList').innerHTML = ` +
+
📭
+
收件箱为空
+
+ `; + document.getElementById('emailDetail').innerHTML = ` +
+
📄
+
选择一封邮件查看详情
+
+ `; + document.getElementById('emailDetailToolbar').style.display = 'none'; + } + } else { + showToast(data.error || '清空失败', 'error'); + } + } catch (error) { + showToast('清空失败', 'error'); + } + } + + // 删除临时邮箱 + async function deleteTempEmail(email) { + if (!confirm(`确定要删除临时邮箱 ${email} 吗?\n该邮箱的所有邮件也将被删除。`)) { + return; + } + + try { + const response = await fetch(`/api/temp-emails/${encodeURIComponent(email)}`, { + method: 'DELETE' + }); + + const data = await response.json(); + + if (data.success) { + showToast('临时邮箱已删除', 'success'); + delete accountsCache['temp']; + + if (currentAccount === email) { + currentAccount = null; + document.getElementById('currentAccount').classList.remove('show'); + document.getElementById('emailList').innerHTML = ` +
+
📬
+
请从左侧选择一个邮箱账号
+
+ `; + document.getElementById('emailDetail').innerHTML = ` +
+
📄
+
选择一封邮件查看详情
+
+ `; + } + + loadTempEmails(true); + loadGroups(); + } else { + showToast(data.error || '删除失败', 'error'); + } + } catch (error) { + showToast('删除失败', 'error'); + } + } + + // 加载临时邮箱的邮件 + async function loadTempEmailMessages(email) { + const container = document.getElementById('emailList'); + container.innerHTML = '
'; + + try { + const response = await fetch(`/api/temp-emails/${encodeURIComponent(email)}/messages`); + const data = await response.json(); + + if (data.success) { + currentEmails = data.emails; + currentMethod = 'gptmail'; + + const methodTag = document.getElementById('methodTag'); + methodTag.textContent = 'GPTMail'; + methodTag.style.display = 'inline'; + methodTag.style.backgroundColor = '#00bcf2'; + methodTag.style.color = 'white'; + + document.getElementById('emailCount').textContent = `(${data.count})`; + + renderEmailList(data.emails); + } else { + container.innerHTML = ` +
+
⚠️
+
${data.error || '加载失败'}
+
+ `; + } + } catch (error) { + container.innerHTML = ` +
+
⚠️
+
网络错误,请重试
+
+ `; + } + } + + // 获取临时邮件详情 + async function getTempEmailDetail(messageId, index) { + document.querySelectorAll('.email-item').forEach((item, i) => { + item.classList.toggle('active', i === index); + }); + + document.getElementById('emailDetailToolbar').style.display = 'flex'; + + const container = document.getElementById('emailDetail'); + container.innerHTML = '
'; + + try { + const response = await fetch(`/api/temp-emails/${encodeURIComponent(currentAccount)}/messages/${encodeURIComponent(messageId)}`); + const data = await response.json(); + + if (data.success) { + renderEmailDetail(data.email); + } else { + container.innerHTML = ` +
+
⚠️
+
${data.error || '加载失败'}
+
+ `; + } + } catch (error) { + container.innerHTML = ` +
+
⚠️
+
网络错误,请重试
+
+ `; + } + } + + // ==================== 账号相关 ==================== + + // 选择账号 + function selectAccount(email) { + currentAccount = email; + isTempEmailGroup = false; + + document.getElementById('currentAccount').classList.add('show'); + document.getElementById('currentAccountEmail').textContent = email; + + document.querySelectorAll('.account-item').forEach(item => { + item.classList.remove('active'); + const emailEl = item.querySelector('.account-email'); + if (emailEl && emailEl.textContent.includes(email)) { item.classList.add('active'); } }); - // 清空邮件列表,提示用户点击获取邮件 document.getElementById('emailList').innerHTML = `
📬
@@ -1594,7 +1957,6 @@
`; - // 清空邮件详情 document.getElementById('emailDetail').innerHTML = `
📄
@@ -2031,9 +2393,12 @@ return; } + // 根据是否是临时邮箱选择不同的点击处理函数 + const clickHandler = isTempEmailGroup ? 'getTempEmailDetail' : 'selectEmail'; + container.innerHTML = emails.map((email, index) => ` -