feat: 支持强制使用 AUTH LOGIN 以解决 outlook 等邮箱的发件问题 (#4112)
* feat: 支持强制使用 AUTH LOGIN 以解决 outlook 等邮箱的发件问题 * fix: 修复通过 SSL 发送邮件时绕过 AUTH LOGIN 的问题 * fix: remove redundant branch, delete test file, add i18n translations - Remove redundant else-if branch in SendEmail since auth is already computed via getSMTPAuth() - Delete option_smtp_auth_test.go as requested - Add i18n translations for '强制使用 AUTH LOGIN' checkbox
This commit is contained in:
parent
aafbd78887
commit
a18ea3cc16
@ -80,6 +80,7 @@ var InsecureTLSConfig = &tls.Config{InsecureSkipVerify: true}
|
|||||||
var SMTPServer = ""
|
var SMTPServer = ""
|
||||||
var SMTPPort = 587
|
var SMTPPort = 587
|
||||||
var SMTPSSLEnabled = false
|
var SMTPSSLEnabled = false
|
||||||
|
var SMTPForceAuthLogin = false
|
||||||
var SMTPAccount = ""
|
var SMTPAccount = ""
|
||||||
var SMTPFrom = ""
|
var SMTPFrom = ""
|
||||||
var SMTPToken = ""
|
var SMTPToken = ""
|
||||||
|
|||||||
@ -19,6 +19,20 @@ func generateMessageID() (string, error) {
|
|||||||
return fmt.Sprintf("<%d.%s@%s>", time.Now().UnixNano(), GetRandomString(12), domain), nil
|
return fmt.Sprintf("<%d.%s@%s>", time.Now().UnixNano(), GetRandomString(12), domain), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func shouldUseSMTPLoginAuth() bool {
|
||||||
|
if SMTPForceAuthLogin {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return isOutlookServer(SMTPAccount) || slices.Contains(EmailLoginAuthServerList, SMTPServer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSMTPAuth() smtp.Auth {
|
||||||
|
if shouldUseSMTPLoginAuth() {
|
||||||
|
return LoginAuth(SMTPAccount, SMTPToken)
|
||||||
|
}
|
||||||
|
return smtp.PlainAuth("", SMTPAccount, SMTPToken, SMTPServer)
|
||||||
|
}
|
||||||
|
|
||||||
func SendEmail(subject string, receiver string, content string) error {
|
func SendEmail(subject string, receiver string, content string) error {
|
||||||
if SMTPFrom == "" { // for compatibility
|
if SMTPFrom == "" { // for compatibility
|
||||||
SMTPFrom = SMTPAccount
|
SMTPFrom = SMTPAccount
|
||||||
@ -38,7 +52,7 @@ func SendEmail(subject string, receiver string, content string) error {
|
|||||||
"Message-ID: %s\r\n"+ // 添加 Message-ID 头
|
"Message-ID: %s\r\n"+ // 添加 Message-ID 头
|
||||||
"Content-Type: text/html; charset=UTF-8\r\n\r\n%s\r\n",
|
"Content-Type: text/html; charset=UTF-8\r\n\r\n%s\r\n",
|
||||||
receiver, SystemName, SMTPFrom, encodedSubject, time.Now().Format(time.RFC1123Z), id, content))
|
receiver, SystemName, SMTPFrom, encodedSubject, time.Now().Format(time.RFC1123Z), id, content))
|
||||||
auth := smtp.PlainAuth("", SMTPAccount, SMTPToken, SMTPServer)
|
auth := getSMTPAuth()
|
||||||
addr := fmt.Sprintf("%s:%d", SMTPServer, SMTPPort)
|
addr := fmt.Sprintf("%s:%d", SMTPServer, SMTPPort)
|
||||||
to := strings.Split(receiver, ";")
|
to := strings.Split(receiver, ";")
|
||||||
var err error
|
var err error
|
||||||
@ -80,9 +94,6 @@ func SendEmail(subject string, receiver string, content string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if isOutlookServer(SMTPAccount) || slices.Contains(EmailLoginAuthServerList, SMTPServer) {
|
|
||||||
auth = LoginAuth(SMTPAccount, SMTPToken)
|
|
||||||
err = smtp.SendMail(addr, auth, SMTPFrom, to, mail)
|
|
||||||
} else {
|
} else {
|
||||||
err = smtp.SendMail(addr, auth, SMTPFrom, to, mail)
|
err = smtp.SendMail(addr, auth, SMTPFrom, to, mail)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,6 +62,7 @@ func InitOptionMap() {
|
|||||||
common.OptionMap["SMTPAccount"] = ""
|
common.OptionMap["SMTPAccount"] = ""
|
||||||
common.OptionMap["SMTPToken"] = ""
|
common.OptionMap["SMTPToken"] = ""
|
||||||
common.OptionMap["SMTPSSLEnabled"] = strconv.FormatBool(common.SMTPSSLEnabled)
|
common.OptionMap["SMTPSSLEnabled"] = strconv.FormatBool(common.SMTPSSLEnabled)
|
||||||
|
common.OptionMap["SMTPForceAuthLogin"] = strconv.FormatBool(common.SMTPForceAuthLogin)
|
||||||
common.OptionMap["Notice"] = ""
|
common.OptionMap["Notice"] = ""
|
||||||
common.OptionMap["About"] = ""
|
common.OptionMap["About"] = ""
|
||||||
common.OptionMap["HomePageContent"] = ""
|
common.OptionMap["HomePageContent"] = ""
|
||||||
@ -233,7 +234,7 @@ func updateOptionMap(key string, value string) (err error) {
|
|||||||
common.ImageDownloadPermission = intValue
|
common.ImageDownloadPermission = intValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if strings.HasSuffix(key, "Enabled") || key == "DefaultCollapseSidebar" || key == "DefaultUseAutoGroup" {
|
if strings.HasSuffix(key, "Enabled") || key == "DefaultCollapseSidebar" || key == "DefaultUseAutoGroup" || key == "SMTPForceAuthLogin" {
|
||||||
boolValue := value == "true"
|
boolValue := value == "true"
|
||||||
switch key {
|
switch key {
|
||||||
case "PasswordRegisterEnabled":
|
case "PasswordRegisterEnabled":
|
||||||
@ -308,6 +309,8 @@ func updateOptionMap(key string, value string) (err error) {
|
|||||||
setting.StopOnSensitiveEnabled = boolValue
|
setting.StopOnSensitiveEnabled = boolValue
|
||||||
case "SMTPSSLEnabled":
|
case "SMTPSSLEnabled":
|
||||||
common.SMTPSSLEnabled = boolValue
|
common.SMTPSSLEnabled = boolValue
|
||||||
|
case "SMTPForceAuthLogin":
|
||||||
|
common.SMTPForceAuthLogin = boolValue
|
||||||
case "WorkerAllowHttpImageRequestEnabled":
|
case "WorkerAllowHttpImageRequestEnabled":
|
||||||
system_setting.WorkerAllowHttpImageRequestEnabled = boolValue
|
system_setting.WorkerAllowHttpImageRequestEnabled = boolValue
|
||||||
case "DefaultUseAutoGroup":
|
case "DefaultUseAutoGroup":
|
||||||
|
|||||||
9
web/bun.lock
vendored
9
web/bun.lock
vendored
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
|
"configVersion": 0,
|
||||||
"workspaces": {
|
"workspaces": {
|
||||||
"": {
|
"": {
|
||||||
"name": "react-template",
|
"name": "react-template",
|
||||||
@ -10,7 +11,7 @@
|
|||||||
"@visactor/react-vchart": "~1.8.8",
|
"@visactor/react-vchart": "~1.8.8",
|
||||||
"@visactor/vchart": "~1.8.8",
|
"@visactor/vchart": "~1.8.8",
|
||||||
"@visactor/vchart-semi-theme": "~1.8.8",
|
"@visactor/vchart-semi-theme": "~1.8.8",
|
||||||
"axios": "1.12.0",
|
"axios": "1.13.5",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.11",
|
||||||
"history": "^5.3.0",
|
"history": "^5.3.0",
|
||||||
@ -776,7 +777,7 @@
|
|||||||
|
|
||||||
"autoprefixer": ["autoprefixer@10.4.21", "", { "dependencies": { "browserslist": "^4.24.4", "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ=="],
|
"autoprefixer": ["autoprefixer@10.4.21", "", { "dependencies": { "browserslist": "^4.24.4", "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ=="],
|
||||||
|
|
||||||
"axios": ["axios@1.12.0", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg=="],
|
"axios": ["axios@1.13.5", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q=="],
|
||||||
|
|
||||||
"babel-plugin-macros": ["babel-plugin-macros@3.1.0", "", { "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", "resolve": "^1.19.0" } }, "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg=="],
|
"babel-plugin-macros": ["babel-plugin-macros@3.1.0", "", { "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", "resolve": "^1.19.0" } }, "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg=="],
|
||||||
|
|
||||||
@ -1104,13 +1105,13 @@
|
|||||||
|
|
||||||
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
|
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
|
||||||
|
|
||||||
"follow-redirects": ["follow-redirects@1.15.9", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="],
|
"follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="],
|
||||||
|
|
||||||
"for-in": ["for-in@1.0.2", "", {}, "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ=="],
|
"for-in": ["for-in@1.0.2", "", {}, "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ=="],
|
||||||
|
|
||||||
"foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
|
"foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
|
||||||
|
|
||||||
"form-data": ["form-data@4.0.4", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="],
|
"form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],
|
||||||
|
|
||||||
"fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="],
|
"fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="],
|
||||||
|
|
||||||
|
|||||||
@ -91,6 +91,7 @@ const SystemSetting = () => {
|
|||||||
EmailDomainRestrictionEnabled: '',
|
EmailDomainRestrictionEnabled: '',
|
||||||
EmailAliasRestrictionEnabled: '',
|
EmailAliasRestrictionEnabled: '',
|
||||||
SMTPSSLEnabled: '',
|
SMTPSSLEnabled: '',
|
||||||
|
SMTPForceAuthLogin: '',
|
||||||
EmailDomainWhitelist: [],
|
EmailDomainWhitelist: [],
|
||||||
TelegramOAuthEnabled: '',
|
TelegramOAuthEnabled: '',
|
||||||
TelegramBotToken: '',
|
TelegramBotToken: '',
|
||||||
@ -182,6 +183,7 @@ const SystemSetting = () => {
|
|||||||
case 'EmailDomainRestrictionEnabled':
|
case 'EmailDomainRestrictionEnabled':
|
||||||
case 'EmailAliasRestrictionEnabled':
|
case 'EmailAliasRestrictionEnabled':
|
||||||
case 'SMTPSSLEnabled':
|
case 'SMTPSSLEnabled':
|
||||||
|
case 'SMTPForceAuthLogin':
|
||||||
case 'LinuxDOOAuthEnabled':
|
case 'LinuxDOOAuthEnabled':
|
||||||
case 'discord.enabled':
|
case 'discord.enabled':
|
||||||
case 'oidc.enabled':
|
case 'oidc.enabled':
|
||||||
@ -1335,6 +1337,15 @@ const SystemSetting = () => {
|
|||||||
>
|
>
|
||||||
{t('启用SMTP SSL')}
|
{t('启用SMTP SSL')}
|
||||||
</Form.Checkbox>
|
</Form.Checkbox>
|
||||||
|
<Form.Checkbox
|
||||||
|
field='SMTPForceAuthLogin'
|
||||||
|
noLabel
|
||||||
|
onChange={(e) =>
|
||||||
|
handleCheckboxChange('SMTPForceAuthLogin', e)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t('强制使用 AUTH LOGIN')}
|
||||||
|
</Form.Checkbox>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Button onClick={submitSMTP}>{t('保存 SMTP 设置')}</Button>
|
<Button onClick={submitSMTP}>{t('保存 SMTP 设置')}</Button>
|
||||||
|
|||||||
1
web/src/i18n/locales/en.json
vendored
1
web/src/i18n/locales/en.json
vendored
@ -925,6 +925,7 @@
|
|||||||
"启用Gemini思考后缀适配": "Enable Gemini thinking suffix adaptation",
|
"启用Gemini思考后缀适配": "Enable Gemini thinking suffix adaptation",
|
||||||
"启用Ping间隔": "Enable Ping interval",
|
"启用Ping间隔": "Enable Ping interval",
|
||||||
"启用SMTP SSL": "Enable SMTP SSL",
|
"启用SMTP SSL": "Enable SMTP SSL",
|
||||||
|
"强制使用 AUTH LOGIN": "Force AUTH LOGIN",
|
||||||
"启用SSRF防护(推荐开启以保护服务器安全)": "Enable SSRF Protection (Recommended for server security)",
|
"启用SSRF防护(推荐开启以保护服务器安全)": "Enable SSRF Protection (Recommended for server security)",
|
||||||
"启用供应商": "Enable Provider",
|
"启用供应商": "Enable Provider",
|
||||||
"启用全部": "Enable all",
|
"启用全部": "Enable all",
|
||||||
|
|||||||
1
web/src/i18n/locales/fr.json
vendored
1
web/src/i18n/locales/fr.json
vendored
@ -920,6 +920,7 @@
|
|||||||
"启用Gemini思考后缀适配": "Activer l'adaptation du suffixe de la pensée Gemini",
|
"启用Gemini思考后缀适配": "Activer l'adaptation du suffixe de la pensée Gemini",
|
||||||
"启用Ping间隔": "Activer l'intervalle de ping",
|
"启用Ping间隔": "Activer l'intervalle de ping",
|
||||||
"启用SMTP SSL": "Activer SMTP SSL",
|
"启用SMTP SSL": "Activer SMTP SSL",
|
||||||
|
"强制使用 AUTH LOGIN": "Forcer AUTH LOGIN",
|
||||||
"启用SSRF防护(推荐开启以保护服务器安全)": "Activer la protection SSRF (recommandé pour la sécurité du serveur)",
|
"启用SSRF防护(推荐开启以保护服务器安全)": "Activer la protection SSRF (recommandé pour la sécurité du serveur)",
|
||||||
"启用供应商": "Activer le fournisseur",
|
"启用供应商": "Activer le fournisseur",
|
||||||
"启用全部": "Activer tout",
|
"启用全部": "Activer tout",
|
||||||
|
|||||||
1
web/src/i18n/locales/ja.json
vendored
1
web/src/i18n/locales/ja.json
vendored
@ -911,6 +911,7 @@
|
|||||||
"启用Gemini思考后缀适配": "Gemini思考サフィックスモードを有効にする",
|
"启用Gemini思考后缀适配": "Gemini思考サフィックスモードを有効にする",
|
||||||
"启用Ping间隔": "Ping間隔を有効にする",
|
"启用Ping间隔": "Ping間隔を有効にする",
|
||||||
"启用SMTP SSL": "SMTP SSLを有効にする",
|
"启用SMTP SSL": "SMTP SSLを有効にする",
|
||||||
|
"强制使用 AUTH LOGIN": "AUTH LOGINを強制する",
|
||||||
"启用SSRF防护(推荐开启以保护服务器安全)": "SSRF保護を有効にする(サーバーを保護するため、有効化を推奨します)",
|
"启用SSRF防护(推荐开启以保护服务器安全)": "SSRF保護を有効にする(サーバーを保護するため、有効化を推奨します)",
|
||||||
"启用供应商": "プロバイダーを有効化",
|
"启用供应商": "プロバイダーを有効化",
|
||||||
"启用全部": "すべてを有効にする",
|
"启用全部": "すべてを有効にする",
|
||||||
|
|||||||
1
web/src/i18n/locales/ru.json
vendored
1
web/src/i18n/locales/ru.json
vendored
@ -926,6 +926,7 @@
|
|||||||
"启用Gemini思考后缀适配": "Включить адаптацию суффикса мышления Gemini",
|
"启用Gemini思考后缀适配": "Включить адаптацию суффикса мышления Gemini",
|
||||||
"启用Ping间隔": "Включить интервал Ping",
|
"启用Ping间隔": "Включить интервал Ping",
|
||||||
"启用SMTP SSL": "Включить SMTP SSL",
|
"启用SMTP SSL": "Включить SMTP SSL",
|
||||||
|
"强制使用 AUTH LOGIN": "Принудительно AUTH LOGIN",
|
||||||
"启用SSRF防护(推荐开启以保护服务器安全)": "Включить защиту SSRF (рекомендуется включить для защиты безопасности сервера)",
|
"启用SSRF防护(推荐开启以保护服务器安全)": "Включить защиту SSRF (рекомендуется включить для защиты безопасности сервера)",
|
||||||
"启用供应商": "Включить поставщика",
|
"启用供应商": "Включить поставщика",
|
||||||
"启用全部": "Включить все",
|
"启用全部": "Включить все",
|
||||||
|
|||||||
1
web/src/i18n/locales/vi.json
vendored
1
web/src/i18n/locales/vi.json
vendored
@ -912,6 +912,7 @@
|
|||||||
"启用Gemini思考后缀适配": "Bật thích ứng hậu tố tư duy Gemini",
|
"启用Gemini思考后缀适配": "Bật thích ứng hậu tố tư duy Gemini",
|
||||||
"启用Ping间隔": "Bật khoảng thời gian Ping",
|
"启用Ping间隔": "Bật khoảng thời gian Ping",
|
||||||
"启用SMTP SSL": "Bật SMTP SSL",
|
"启用SMTP SSL": "Bật SMTP SSL",
|
||||||
|
"强制使用 AUTH LOGIN": "Buộc AUTH LOGIN",
|
||||||
"启用SSRF防护(推荐开启以保护服务器安全)": "Bật bảo vệ SSRF (Khuyên dùng để bảo mật máy chủ)",
|
"启用SSRF防护(推荐开启以保护服务器安全)": "Bật bảo vệ SSRF (Khuyên dùng để bảo mật máy chủ)",
|
||||||
"启用供应商": "Bật nhà cung cấp",
|
"启用供应商": "Bật nhà cung cấp",
|
||||||
"启用全部": "Bật tất cả",
|
"启用全部": "Bật tất cả",
|
||||||
|
|||||||
1
web/src/i18n/locales/zh-CN.json
vendored
1
web/src/i18n/locales/zh-CN.json
vendored
@ -680,6 +680,7 @@
|
|||||||
"启用Gemini思考后缀适配": "启用Gemini思考后缀适配",
|
"启用Gemini思考后缀适配": "启用Gemini思考后缀适配",
|
||||||
"启用Ping间隔": "启用Ping间隔",
|
"启用Ping间隔": "启用Ping间隔",
|
||||||
"启用SMTP SSL": "启用SMTP SSL",
|
"启用SMTP SSL": "启用SMTP SSL",
|
||||||
|
"强制使用 AUTH LOGIN": "强制使用 AUTH LOGIN",
|
||||||
"启用SSRF防护(推荐开启以保护服务器安全)": "启用SSRF防护(推荐开启以保护服务器安全)",
|
"启用SSRF防护(推荐开启以保护服务器安全)": "启用SSRF防护(推荐开启以保护服务器安全)",
|
||||||
"启用全部": "启用全部",
|
"启用全部": "启用全部",
|
||||||
"启用后可接入 io.net GPU 资源": "启用后可接入 io.net GPU 资源",
|
"启用后可接入 io.net GPU 资源": "启用后可接入 io.net GPU 资源",
|
||||||
|
|||||||
1
web/src/i18n/locales/zh-TW.json
vendored
1
web/src/i18n/locales/zh-TW.json
vendored
@ -797,6 +797,7 @@
|
|||||||
"启用Gemini思考后缀适配": "啟用Gemini思考後綴相容",
|
"启用Gemini思考后缀适配": "啟用Gemini思考後綴相容",
|
||||||
"启用Ping间隔": "啟用Ping間隔",
|
"启用Ping间隔": "啟用Ping間隔",
|
||||||
"启用SMTP SSL": "啟用SMTP SSL",
|
"启用SMTP SSL": "啟用SMTP SSL",
|
||||||
|
"强制使用 AUTH LOGIN": "強制使用 AUTH LOGIN",
|
||||||
"启用SSRF防护(推荐开启以保护服务器安全)": "啟用SSRF防護(推薦開啟以保護伺服器安全)",
|
"启用SSRF防护(推荐开启以保护服务器安全)": "啟用SSRF防護(推薦開啟以保護伺服器安全)",
|
||||||
"启用全部": "啟用全部",
|
"启用全部": "啟用全部",
|
||||||
"启用后可接入 io.net GPU 资源": "啟用後可接入 io.net GPU 資源",
|
"启用后可接入 io.net GPU 资源": "啟用後可接入 io.net GPU 資源",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user