更新邮件页面和管理API

This commit is contained in:
2025-12-15 17:16:56 +08:00
parent 49897081b6
commit 8846945208
19 changed files with 170 additions and 37 deletions

View File

@@ -102,10 +102,120 @@ const smtpForm = reactive({
priority: 0,
})
const SMTP_TEMPLATES = [
{
key: 'custom',
label: '自定义(手动填写)',
defaults: null,
note: '适用于其他邮箱/自建SMTP',
links: [],
},
{
key: 'gmail',
label: 'Gmail',
defaults: { host: 'smtp.gmail.com', port: 465, use_ssl: true, use_tls: false },
note: '通常需要开启两步验证并创建应用专用密码App Password',
links: [
{ label: 'SMTP 设置说明', url: 'https://support.google.com/mail/answer/7126229?hl=zh-Hans' },
{ label: 'App Password', url: 'https://myaccount.google.com/apppasswords' },
],
},
{
key: 'qq',
label: 'QQ 邮箱',
defaults: { host: 'smtp.qq.com', port: 465, use_ssl: true, use_tls: false },
note: '需要在邮箱设置中开启 SMTP 并获取授权码不是QQ登录密码',
links: [{ label: 'QQ邮箱 SMTP 帮助', url: 'https://service.mail.qq.com/cgi-bin/help?subtype=1&id=28&no=1001256' }],
},
{
key: '163',
label: '163 邮箱',
defaults: { host: 'smtp.163.com', port: 465, use_ssl: true, use_tls: false },
note: '需要在邮箱设置中开启 SMTP 并使用授权码/客户端授权密码',
links: [{ label: '网易邮箱 SMTP 帮助', url: 'https://help.mail.163.com/faqDetail.do?code=d7a5dc8471a22b76' }],
},
{
key: '126',
label: '126 邮箱',
defaults: { host: 'smtp.126.com', port: 465, use_ssl: true, use_tls: false },
note: '需要在邮箱设置中开启 SMTP 并使用授权码/客户端授权密码',
links: [{ label: '网易邮箱帮助', url: 'https://help.mail.163.com/' }],
},
{
key: 'outlook',
label: 'Outlook/Hotmail',
defaults: { host: 'smtp-mail.outlook.com', port: 587, use_ssl: false, use_tls: true },
note: '建议使用 TLS 587部分账号需开启 SMTP AUTH',
links: [
{
label: '微软 SMTP 设置',
url: 'https://support.microsoft.com/office/pop-imap-and-smtp-settings-for-outlook-com-d088b0b7-0d38-4f9a-bc5d-509f9e4c6d3d',
},
],
},
{
key: 'office365',
label: 'Microsoft 365/Exchange',
defaults: { host: 'smtp.office365.com', port: 587, use_ssl: false, use_tls: true },
note: '企业邮箱常用配置(需启用 SMTP AUTH',
links: [{ label: '微软官方说明', url: 'https://learn.microsoft.com/exchange/clients-and-mobile-in-exchange-online/authenticated-client-smtp-submission' }],
},
{
key: 'icloud',
label: 'iCloud',
defaults: { host: 'smtp.mail.me.com', port: 587, use_ssl: false, use_tls: true },
note: '需要在 Apple ID 中生成“App 专用密码”',
links: [{ label: 'Apple 邮件服务器设置', url: 'https://support.apple.com/zh-cn/HT202304' }],
},
{
key: 'tencent_exmail',
label: '腾讯企业邮箱',
defaults: { host: 'smtp.exmail.qq.com', port: 465, use_ssl: true, use_tls: false },
note: '企业邮箱常用配置',
links: [{ label: '腾讯企业邮箱帮助', url: 'https://service.exmail.qq.com/cgi-bin/help?subtype=1&id=23&no=1001068' }],
},
{
key: 'aliyun_exmail',
label: '阿里企业邮箱',
defaults: { host: 'smtp.mxhichina.com', port: 465, use_ssl: true, use_tls: false },
note: '企业邮箱常用配置',
links: [{ label: '阿里云文档', url: 'https://help.aliyun.com/document_detail/50652.html' }],
},
]
const smtpTemplateKey = ref('custom')
const currentSmtpTemplate = computed(() => SMTP_TEMPLATES.find((t) => t.key === smtpTemplateKey.value) || SMTP_TEMPLATES[0])
const smtpPasswordPlaceholder = computed(() =>
smtpEditMode.value && smtpHasPassword.value ? '留空保持不变' : 'SMTP密码或授权码',
)
function inferSmtpTemplateKey(row) {
const host = String(row?.host || '').trim().toLowerCase()
if (!host) return 'custom'
const byHost = {
'smtp.gmail.com': 'gmail',
'smtp.qq.com': 'qq',
'smtp.163.com': '163',
'smtp.126.com': '126',
'smtp-mail.outlook.com': 'outlook',
'smtp.office365.com': 'office365',
'smtp.mail.me.com': 'icloud',
'smtp.exmail.qq.com': 'tencent_exmail',
'smtp.mxhichina.com': 'aliyun_exmail',
}
return byHost[host] || 'custom'
}
function applySmtpTemplate(key) {
const tpl = SMTP_TEMPLATES.find((t) => t.key === key)
if (!tpl || !tpl.defaults) return
smtpForm.host = tpl.defaults.host
smtpForm.port = tpl.defaults.port
smtpForm.use_ssl = tpl.defaults.use_ssl
smtpForm.use_tls = tpl.defaults.use_tls
}
function resetSmtpForm() {
smtpForm.id = null
smtpForm.name = '默认配置'
@@ -121,6 +231,7 @@ function resetSmtpForm() {
smtpForm.daily_limit = 0
smtpForm.priority = 0
smtpHasPassword.value = false
smtpTemplateKey.value = 'custom'
}
async function loadSmtpConfigs() {
@@ -137,6 +248,7 @@ async function loadSmtpConfigs() {
function openCreateSmtp() {
smtpEditMode.value = false
resetSmtpForm()
smtpTemplateKey.value = 'custom'
smtpDialogOpen.value = true
}
@@ -158,6 +270,7 @@ function openEditSmtp(row) {
smtpForm.daily_limit = row.daily_limit ?? 0
smtpForm.priority = row.priority ?? 0
smtpHasPassword.value = Boolean(row.has_password)
smtpTemplateKey.value = inferSmtpTemplateKey(row)
smtpDialogOpen.value = true
}
@@ -613,6 +726,26 @@ onMounted(refreshAll)
<el-form-item label="启用">
<el-switch v-model="smtpForm.enabled" />
</el-form-item>
<el-form-item label="邮箱模板">
<div style="width: 100%">
<el-select v-model="smtpTemplateKey" placeholder="选择常用邮箱模板" style="width: 100%" @change="applySmtpTemplate">
<el-option v-for="t in SMTP_TEMPLATES" :key="t.key" :label="t.label" :value="t.key" />
</el-select>
<div
v-if="currentSmtpTemplate.note || (currentSmtpTemplate.links && currentSmtpTemplate.links.length)"
class="help"
>
<span v-if="currentSmtpTemplate.note">{{ currentSmtpTemplate.note }}</span>
<template v-if="currentSmtpTemplate.links && currentSmtpTemplate.links.length">
<span v-if="currentSmtpTemplate.note"> · </span>
<span v-for="(l, idx) in currentSmtpTemplate.links" :key="l.url">
<el-link :href="l.url" target="_blank" type="primary" :underline="false">{{ l.label }}</el-link>
<span v-if="idx < currentSmtpTemplate.links.length - 1"> · </span>
</span>
</template>
</div>
</div>
</el-form-item>
<el-form-item label="服务器">
<el-input v-model="smtpForm.host" placeholder="smtp.example.com" />
</el-form-item>