收敛邮件通知页面为SMTP系统账户

This commit is contained in:
xuans 2026-09-27 08:50:22 +08:00
parent e72aa9e80d
commit 77419c8552
4 changed files with 53 additions and 81 deletions

View File

@ -1,19 +1,9 @@
.mail-common-fields,
.mail-channels,
.mail-smtp-fields {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px 16px;
}
.mail-common-fields {
margin-bottom: 14px;
}
.mail-channels {
grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
}
.mail-channel {
min-width: 0;
margin: 0;
@ -42,6 +32,10 @@
margin-top: 12px;
}
.mail-recipient-field {
margin-top: 14px;
}
.mail-field > span {
display: flex;
align-items: center;
@ -83,8 +77,6 @@
}
@media (max-width: 700px) {
.mail-common-fields,
.mail-channels,
.mail-smtp-fields {
grid-template-columns: minmax(0, 1fr);
}

View File

@ -6,45 +6,14 @@ defineProps({ notification: { type: Object, required: true } });
<template>
<div class="mail-notification-settings">
<div class="mail-common-fields">
<label class="mail-field">
<span>发件人邮箱</span>
<input v-model="notification.sender_email" type="email" />
<fieldset class="mail-channel">
<legend>SMTP 服务</legend>
<label class="mail-switch">
<input v-model="notification.smtp_enabled" type="checkbox" />
<span>启用 SMTP 发送</span>
<HelpTip>默认使用 Smail 系统通知账户发信,发件人地址由系统自动生成。</HelpTip>
</label>
<label class="mail-field">
<span>收件人 <HelpTip>多个地址用逗号分隔,两种发送方式共用此配置。</HelpTip></span>
<input
:value="notification.recipients.join(', ')"
@input="notification.recipients = $event.target.value.split(/[,,]/).map((item) => item.trim()).filter(Boolean)"
placeholder="多个地址用逗号分隔"
/>
</label>
</div>
<div class="mail-channels">
<fieldset class="mail-channel">
<legend>HTTP 接口</legend>
<label class="mail-switch">
<input v-model="notification.http_enabled" type="checkbox" />
<span>启用接口发送</span>
<HelpTip>通过邮件服务接口发送通知,保留现有接口配置。</HelpTip>
</label>
<label class="mail-field">
<span>通知服务商</span>
<input v-model="notification.provider" placeholder="例如 temporary-mail" />
</label>
<label class="mail-field">
<span>通知接口地址</span>
<input v-model="notification.endpoint" placeholder="https://..." />
</label>
</fieldset>
<fieldset class="mail-channel">
<legend>SMTP 服务</legend>
<label class="mail-switch">
<input v-model="notification.smtp_enabled" type="checkbox" />
<span>启用 SMTP 发送</span>
<HelpTip>通过 SMTP 服务发送邮件,保留现有通道启用状态。</HelpTip>
</label>
<div class="mail-smtp-fields">
<div class="mail-smtp-fields">
<label class="mail-field">
<span>SMTP 主机</span>
<input v-model="notification.smtp_host" placeholder="例如 smtp.example.com" />
@ -76,9 +45,16 @@ defineProps({ notification: { type: Object, required: true } });
<span>允许明文认证</span>
<HelpTip>仅在明确确认 SMTP 网络受保护时开启。</HelpTip>
</label>
</div>
</fieldset>
</div>
</div>
<label class="mail-field mail-recipient-field">
<span>收件人 <HelpTip>多个地址用逗号分隔。</HelpTip></span>
<input
:value="notification.recipients.join(', ')"
@input="notification.recipients = $event.target.value.split(/[,,]/).map((item) => item.trim()).filter(Boolean)"
placeholder="多个地址用逗号分隔"
/>
</label>
</fieldset>
</div>
</template>

View File

@ -7,7 +7,7 @@ import { settingsPayload } from "./SettingsPayload.js";
const source = readFileSync(new URL("./SettingsModal.vue", import.meta.url), "utf8");
test("邮件通知组件保留两种通道且公共字段只出现一次", () => {
test("邮件通知组件只保留 SMTP 通道和收件人配置", () => {
const mailSource = readFileSync(new URL("./MailNotificationSettings.vue", import.meta.url), "utf8");
const { descriptor, errors } = parse(mailSource);
assert.deepEqual(errors, []);
@ -19,36 +19,41 @@ test("邮件通知组件保留两种通道且公共字段只出现一次", () =>
compilerOptions: { bindingMetadata: script.bindings },
});
assert.deepEqual(compiled.errors, []);
for (const field of ["http_enabled", "smtp_enabled", "sender_email", "smtp_password"]) {
for (const field of ["smtp_enabled", "smtp_password"]) {
assert.equal(mailSource.split(`v-model="notification.${field}"`).length - 1, 1);
}
assert.doesNotMatch(mailSource, /HTTP 接口|sender_email|notification\.http_enabled/);
assert.equal(mailSource.split(':value="notification.recipients.join').length - 1, 1);
assert.match(source, /<MailNotificationSettings :notification="settingsForm.notification"/);
assert.doesNotMatch(mailSource, /role="tab"/);
});
test("合并通知页面不改变通道开关和已保存配置", () => {
for (const http of [false, true]) {
for (const smtp of [false, true]) {
const notification = {
http_enabled: http,
smtp_enabled: smtp,
endpoint: "https://mail.example.com",
sender_email: "sender@example.com",
recipients: ["recipient@example.com"],
smtp_host: "smtp.example.com",
smtp_port: 587,
smtp_username: "sender",
smtp_password: "",
smtp_mode: "starttls",
smtp_credential_configured: true,
};
const payload = settingsPayload({ notification }).notification;
const { smtp_credential_configured, ...expected } = notification;
assert.deepEqual(payload, expected);
assert.equal(notification.smtp_credential_configured, true);
}
}
test("邮件设置只提交 SMTP 配置,不提交 HTTP 和自定义发件人", () => {
const notification = {
http_enabled: true,
smtp_enabled: true,
endpoint: "https://mail.example.com",
sender_email: "sender@example.com",
recipients: ["recipient@example.com"],
smtp_host: "smtp.example.com",
smtp_port: 587,
smtp_username: "notify:system@example.com",
smtp_password: "",
smtp_mode: "starttls",
smtp_credential_configured: true,
};
const payload = settingsPayload({ notification }).notification;
assert.deepEqual(payload, {
smtp_enabled: true,
smtp_host: "smtp.example.com",
smtp_port: 587,
smtp_username: "notify:system@example.com",
smtp_password: "",
smtp_mode: "starttls",
recipients: ["recipient@example.com"],
});
assert.equal(notification.http_enabled, true);
assert.equal(notification.sender_email, "sender@example.com");
});
test("通知字段校验失败时切换到合并后的邮件通知页", async () => {

View File

@ -10,12 +10,11 @@ const requestFields = {
"propagation_polling_interval_secs",
],
notification: [
"http_enabled", "smtp_enabled", "smtp_host", "smtp_port",
"smtp_enabled", "smtp_host", "smtp_port",
"smtp_username", "smtp_password", "smtp_mode", "smtp_allow_plaintext_auth",
"http_credentials", "provider", "endpoint", "http_path", "http_login_path",
"http_auth_mode", "event_mode", "include_deployment_details",
"event_mode", "include_deployment_details",
"include_certificate_serial", "include_management_url", "sender_name",
"sender_email", "recipients", "timeout_secs", "retry_count",
"recipients", "timeout_secs", "retry_count",
"retry_intervals_secs",
],
};