Skip to content

fix: support SMTP STARTTLS mode and NTLM auth - #5426

Merged
Calcium-Ion merged 3 commits into
QuantumNous:mainfrom
bensonfx:fix/smtp-starttls
Jun 24, 2026
Merged

fix: support SMTP STARTTLS mode and NTLM auth#5426
Calcium-Ion merged 3 commits into
QuantumNous:mainfrom
bensonfx:fix/smtp-starttls

Conversation

@bensonfx

@bensonfx bensonfx commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

⚠️ 提交说明 / PR Notice

Important

  • 请提供人工撰写的简洁摘要,避免直接粘贴未经整理的 AI 输出。

📝 变更描述 / Description

本 PR 完善 SMTP 邮件发送的 STARTTLS 连接模式,并补充 STARTTLS 后的 SMTP 认证机制兼容。

原先 SMTP 配置主要覆盖普通连接和隐式 SSL/TLS 连接,无法明确区分常见的 587 端口 STARTTLS 流程。本次改动新增 SMTPStartTLSEnabled 配置,并在发送邮件时根据配置选择连
接方式:

  • SMTPSSLEnabled=true:使用隐式 SSL/TLS 连接,适用于 465 等端口;
  • SMTPStartTLSEnabled=true:先建立普通 SMTP 连接,再通过 STARTTLS 升级到 TLS,适用于 587 等端口;
  • 两者都为 false:保持普通 SMTP 连接。

同时,本 PR 也处理了部分 Exchange / 微软系企业 SMTP 在 STARTTLS 成功后的认证兼容问题。

这类问题不是 STARTTLS 握手失败,而是 TLS 升级后 SMTP AUTH 机制不兼容。部分服务器不会提供可用的 AUTH PLAIN,而是只提供或要求 AUTH NTLM。因此本次改动在现有认证
逻辑中增加 NTLM 支持,认证选择顺序为:

  • 如配置强制 AUTH LOGIN,则使用 LOGIN
  • 否则优先使用服务端广告的 PLAIN
  • 其次使用 LOGIN
  • 最后在服务端仅提供/需要 NTLM 时使用 NTLM

该改动不会改变支持 AUTH PLAIN 的 SMTP 服务行为。对于 STARTTLS 后广告 PLAIN 的服务器,仍然优先使用 PLAIN

此外,新版前端和旧版前端的 SMTP 设置 UI 已调整为“无加密 / SSL/TLS / STARTTLS”互斥选项,避免同时启用 SSL/TLS 和 STARTTLS 导致误配置。

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix) - 请关联对应 Issue,避免将设计取舍、理解偏差或预期不一致直接归类为 bug
  • ✨ 新功能 (New feature) - 重大特性建议先通过 Issue 沟通
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

✅ 提交前检查项 / Checklist

  • 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • 非重复提交: 我已搜索现有的 IssuesPRs,确认不是重复提
    交。
  • Bug fix 说明: 若此 PR 标记为 Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。
  • 变更理解: 我已理解这些更改的工作原理及可能影响。
  • 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

本地验证结果:

go test ./common
# ok   github.com/QuantumNous/new-api/common

cd web/default
node scripts/sync-i18n.mjs
# i18n sync done. Report: .../web/default/src/i18n/locales/_reports/_sync-report.json

git diff --check HEAD~1..HEAD
# no output

i18n 同步报告中 en/fr/ja/ru/vi/zh 均为:

{
  "missingCount": 0,
  "extrasCount": 0,
  "untranslatedCount": 0
}

同时已检查:

- 新版前端 SMTP 设置页显示互斥选项:无加密 / SSL/TLS / STARTTLS;
- 旧版前端 SMTP 设置页显示互斥选项:无加密 / SSL/TLS / STARTTLS;
- locale JSON 文件解析正常;
- git diff --check HEAD~1..HEAD 无空白错误。

未完整运行前端构建,原因是当前本地环境缺少前端依赖:

- web/default npm run typecheck 失败:缺少 tsc
- web/classic npm run build 失败:缺少 rsbuild


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **New Features**
* Added STARTTLS as an SMTP transport security mode (SSL/TLS, STARTTLS, or no encryption)
* Added an option to skip SMTP TLS certificate verification
* Updated the SMTP settings UI to use a clearer encryption-mode selector and persist both STARTTLS-related settings
* **Bug Fixes**
* Improved SMTP delivery to negotiate TLS/STARTTLS correctly and authenticate using the best supported method (including NTLM when available)
* **Documentation**
* Added/updated translations for the new SMTP security and STARTTLS options across supported languages
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds STARTTLS support and TLS verification flags, centralizes SMTP client/TLS/STARTTLS handling with automatic auth mechanism selection (PLAIN/LOGIN/NTLM via AutoSMTPAuth), updates classic and default settings UIs to a mutually exclusive encryption mode selector, and adds comprehensive test coverage plus locale strings across eight classic and six default languages.

Changes

SMTP STARTTLS Support Feature

Layer / File(s) Summary
Backend configuration foundation
common/constants.go, common/init.go, model/option.go, web/default/src/features/system-settings/operations/index.tsx, web/default/src/features/system-settings/operations/section-registry.tsx, web/default/src/features/system-settings/types.ts
Adds SMTPStartTLSEnabled and SMTPInsecureSkipVerify, initializes them from env vars with backward-compatible fallback names, wires them into defaults and the options map, and exposes them to settings types/defaults.
SMTP client refactor and auth negotiation
common/email.go, common/email_ntlm_auth.go, go.mod
Refactors SendEmail to use a unified SMTP client with optional STARTTLS upgrade, central TLS config, and AutoSMTPAuth that automatically selects from PLAIN/LOGIN/NTLM based on server capabilities; adds github.com/Azure/go-ntlmssp v0.1.1 dependency.
Email delivery test suite
common/email_test.go
Introduces a fake in-memory SMTP server with STARTTLS upgrade, TLS support, and auth/command capture; includes tests for explicit STARTTLS with insecure certs, STARTTLS requirement validation, disabled STARTTLS behavior, auth skipping rules, NTLM-only auth, port 465 implicit TLS, and certificate trust enforcement.
Classic settings UI and handlers
web/classic/src/components/settings/SystemSetting.jsx
Replaces SMTP SSL checkbox with a mutually exclusive none/SSL-TLS/STARTTLS radio-group mode selector, derives target flags from selected mode, conditionally updates both flags on submit, and adds mode-change handler for immediate persistence.
Classic locale strings
web/classic/src/i18n/locales/en.json, fr.json, ja.json, ru.json, vi.json, zh-CN.json, zh-TW.json, zh.json
Adds encryption mode label, SSL/TLS/STARTTLS options, no-encryption option, and mode-selection prompt across all eight classic locale files.
Default settings schema, form, and handlers
web/default/src/features/system-settings/integrations/email-settings-section.tsx
Adds SMTPStartTLSEnabled and SMTPInsecureSkipVerify to Zod schema; introduces SmtpSecurityMode helper to derive unified mode; maps mode to flags during submit; includes new flags in change detection and mutation payloads; replaces SSL switch with radio-group encryption selector.
Default locale strings
web/default/src/i18n/locales/en.json, fr.json, ja.json, ru.json, vi.json, zh.json
Adds self-signed certificate allowance, transport mode prompt, STARTTLS label, no-encryption option, skip verification text, SMTP encryption labels, and STARTTLS upgrade guidance across all six default locale files.

Sequence Diagram(s)

sequenceDiagram
  participant User as Admin/User
  participant UI as Settings UI
  participant Backend as System
  participant SMTPServer as SMTP Server
  
  User->>UI: Select STARTTLS encryption mode
  UI->>Backend: Submit with SMTPStartTLSEnabled=true, SMTPSSLEnabled=false
  
  rect rgba(0, 100, 200, 0.5)
  note over Backend,SMTPServer: Email Send Flow
  Backend->>SMTPServer: Connect plaintext (port 587)
  SMTPServer->>Backend: EHLO response with STARTTLS capability
  Backend->>SMTPServer: STARTTLS command
  SMTPServer->>Backend: TLS upgrade handshake
  Backend->>SMTPServer: EHLO again (post-TLS)
  SMTPServer->>Backend: List AUTH mechanisms (PLAIN/LOGIN/NTLM)
  Backend->>Backend: AutoSMTPAuth: select best mechanism
  Backend->>SMTPServer: AUTH PLAIN/LOGIN/NTLM
  SMTPServer->>Backend: Auth success
  Backend->>SMTPServer: MAIL / RCPT / DATA / QUIT
  SMTPServer->>Backend: Message queued
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Possibly related PRs

  • QuantumNous/new-api#4112: Both modify SMTP authentication selection in SendEmail flow; related on auth negotiation mechanism and SendEmail refactoring.

Suggested reviewers

  • Calcium-Ion
  • seefs001

Poem

🐰 Through SMTP nights I hopped with care,
Found STARTTLS waiting there,
Modes switching: none, TLS, and more,
NTLM knocking at the door,
Mail secure forevermore!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: support SMTP STARTTLS mode and NTLM auth' accurately and concisely summarizes the main objective: adding STARTTLS support and NTLM authentication for SMTP connections.
Linked Issues check ✅ Passed The PR implementation fully addresses all coding objectives from issue #5425: adds explicit STARTTLS mode support via SMTPStartTLSEnabled flag, implements NTLM authentication with proper mechanism selection (PLAIN > LOGIN > NTLM), includes TLS verification controls (SMTPInsecureSkipVerify), provides mutually exclusive encryption UI (No encryption / SSL/TLS / STARTTLS), updates environment configuration, and maintains backward compatibility with existing PLAIN auth servers.
Out of Scope Changes check ✅ Passed All changes are within scope of the linked issue: backend SMTP configuration/auth (common/), go.mod dependency, model option mapping, and frontend UI updates for STARTTLS/NTLM across both classic and new web interfaces with i18n translations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
web/classic/src/i18n/locales/zh-CN.json (1)

224-224: Confirm i18n coverage for SMTP encryption mode options

  • web/classic/src/i18n/locales/zh-CN.json only adds the translated option label 无加密; there are no locale keys for SSL/TLS or STARTTLS.
  • web/classic/src/components/settings/SystemSetting.jsx hardcodes the radio labels SSL/TLS and STARTTLS; only the “none” option uses t('无加密').

If the product intent is to localize all three options, add i18n keys for SSL/TLS and STARTTLS and use t(...) for those radios.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/classic/src/i18n/locales/zh-CN.json` at line 224, Add i18n entries for
the missing SMTP encryption option labels and use them in the Settings
component: add locale keys for "SSL/TLS" and "STARTTLS" to the zh-CN.json
(matching the same key naming convention used for the existing "无加密"), then
update web/classic/src/components/settings/SystemSetting.jsx to replace
hardcoded radio labels "SSL/TLS" and "STARTTLS" with t('SSL/TLS') and
t('STARTTLS') (or the chosen key names) so all three options use the i18n helper
consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@common/email.go`:
- Around line 33-35: The helper shouldAuthenticateSMTP() currently returns true
when either SMTPAccount or SMTPToken is set, causing attempted AUTH with partial
credentials; change its logic to require both values (e.g., return SMTPAccount
!= "" && SMTPToken != "") so SMTP AUTH is only attempted when the account and
token are both provided; update the function shouldAuthenticateSMTP()
accordingly and consider trimming or validating SMTPAccount/SMTPToken if needed.
- Around line 63-69: The code currently upgrades to STARTTLS whenever the server
advertises it because the condition uses "SMTPStartTLSEnabled ||
startTLSSupported"; change this to only upgrade when the configuration
explicitly enables STARTTLS and the server supports it (i.e., use
"SMTPStartTLSEnabled && startTLSSupported") so that when both SMTPSSLEnabled and
SMTPStartTLSEnabled are false no TLS upgrade is attempted; update the block
around client.Extension("STARTTLS") and the client.StartTLS(smtpTLSConfig())
call accordingly.

In `@web/classic/src/i18n/locales/ja.json`:
- Line 231: The Japanese locale is missing explicit translation keys for the
SMTP encryption radio labels "SSL/TLS" and "STARTTLS"; add keys alongside
existing SMTP labels (e.g., near "SMTP 加密方式" and "启用SMTP SSL") such as a
Japanese translation for "SSL/TLS" and for "STARTTLS" (and mirror the same keys
into other locale files if they should not be inherited), ensuring the JSON key
names match the UI label identifiers used by the app so the radio options render
correctly.

In `@web/classic/src/i18n/locales/ru.json`:
- Line 3247: Replace the Russian translation for the key "请选择一种 SMTP 传输加密方式" in
the ru.json locale entry so the value reads "Выберите один из режимов защиты
SMTP-транспорта" (fixing the grammar); update the mapping where the diff shows
the current value "Выберите один режим защиты SMTP-транспорта" to the corrected
phrase.

In
`@web/default/src/features/system-settings/integrations/email-settings-section.tsx`:
- Around line 271-272: The SMTP mode labels "SSL/TLS" and "STARTTLS" in the
EmailSettingsSection React component are hardcoded and must be localized;
replace the literal strings inside the Label elements with t('...') calls (e.g.,
t('emailSettings.smtpMode.sslTls') and t('emailSettings.smtpMode.starttls') or
the appropriate existing i18n keys) so they flow through the translation system,
and add corresponding keys to the locale files if missing; update both
occurrences (the one around "SSL/TLS" and the one at lines ~283-284 for
"STARTTLS") in the component.

---

Nitpick comments:
In `@web/classic/src/i18n/locales/zh-CN.json`:
- Line 224: Add i18n entries for the missing SMTP encryption option labels and
use them in the Settings component: add locale keys for "SSL/TLS" and "STARTTLS"
to the zh-CN.json (matching the same key naming convention used for the existing
"无加密"), then update web/classic/src/components/settings/SystemSetting.jsx to
replace hardcoded radio labels "SSL/TLS" and "STARTTLS" with t('SSL/TLS') and
t('STARTTLS') (or the chosen key names) so all three options use the i18n helper
consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 75e5f5e5-f790-4f1d-b008-bfa0aa96a5a7

📥 Commits

Reviewing files that changed from the base of the PR and between 6f41542 and 8c976a0.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (26)
  • common/constants.go
  • common/email.go
  • common/email_ntlm_auth.go
  • common/email_test.go
  • common/init.go
  • go.mod
  • model/option.go
  • web/classic/src/components/settings/SystemSetting.jsx
  • web/classic/src/i18n/locales/en.json
  • web/classic/src/i18n/locales/fr.json
  • web/classic/src/i18n/locales/ja.json
  • web/classic/src/i18n/locales/ru.json
  • web/classic/src/i18n/locales/vi.json
  • web/classic/src/i18n/locales/zh-CN.json
  • web/classic/src/i18n/locales/zh-TW.json
  • web/classic/src/i18n/locales/zh.json
  • web/default/src/features/system-settings/integrations/email-settings-section.tsx
  • web/default/src/features/system-settings/operations/index.tsx
  • web/default/src/features/system-settings/operations/section-registry.tsx
  • web/default/src/features/system-settings/types.ts
  • web/default/src/i18n/locales/en.json
  • web/default/src/i18n/locales/fr.json
  • web/default/src/i18n/locales/ja.json
  • web/default/src/i18n/locales/ru.json
  • web/default/src/i18n/locales/vi.json
  • web/default/src/i18n/locales/zh.json

Comment thread common/email.go
Comment thread common/email.go Outdated
Comment thread web/classic/src/i18n/locales/ja.json
Comment thread web/classic/src/i18n/locales/ru.json Outdated
Comment thread web/default/src/features/system-settings/integrations/email-settings-section.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@common/email_test.go`:
- Around line 109-116: The fake SMTP server currently accepts STARTTLS
regardless of advertiseSTARTTLS, weakening the negative test; in the case
handling where upperCommand == "STARTTLS" check the server's advertiseSTARTTLS
flag (e.g., s.advertiseSTARTTLS) first and if false respond with a rejection
(use writeSMTPLine to send a 503/5.5.1 or similar "STARTTLS not supported"
error) and return, otherwise proceed to send into s.startTLSCommands and write
the "220 Ready to start TLS" response as before.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e205337a-2c42-48da-8130-34470a230bd7

📥 Commits

Reviewing files that changed from the base of the PR and between 8c976a0 and dffc509.

📒 Files selected for processing (18)
  • common/email.go
  • common/email_test.go
  • web/classic/src/components/settings/SystemSetting.jsx
  • web/classic/src/i18n/locales/en.json
  • web/classic/src/i18n/locales/fr.json
  • web/classic/src/i18n/locales/ja.json
  • web/classic/src/i18n/locales/ru.json
  • web/classic/src/i18n/locales/vi.json
  • web/classic/src/i18n/locales/zh-CN.json
  • web/classic/src/i18n/locales/zh-TW.json
  • web/classic/src/i18n/locales/zh.json
  • web/default/src/features/system-settings/integrations/email-settings-section.tsx
  • web/default/src/i18n/locales/en.json
  • web/default/src/i18n/locales/fr.json
  • web/default/src/i18n/locales/ja.json
  • web/default/src/i18n/locales/ru.json
  • web/default/src/i18n/locales/vi.json
  • web/default/src/i18n/locales/zh.json
✅ Files skipped from review due to trivial changes (11)
  • web/classic/src/i18n/locales/en.json
  • web/classic/src/i18n/locales/zh.json
  • web/classic/src/i18n/locales/zh-CN.json
  • web/classic/src/i18n/locales/vi.json
  • web/classic/src/i18n/locales/ru.json
  • web/classic/src/i18n/locales/zh-TW.json
  • web/classic/src/i18n/locales/fr.json
  • web/default/src/i18n/locales/en.json
  • web/default/src/i18n/locales/fr.json
  • web/default/src/i18n/locales/zh.json
  • web/default/src/i18n/locales/vi.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • web/classic/src/components/settings/SystemSetting.jsx
  • common/email.go
  • web/default/src/i18n/locales/ja.json

Comment thread common/email_test.go
@bensonfx bensonfx changed the title fix: support SMTP STARTTLS settings fix: support SMTP STARTLS settings Jun 14, 2026
@benson-devai benson-devai mentioned this pull request Jun 16, 2026
@bensonfx bensonfx changed the title fix: support SMTP STARTLS settings fix: support SMTP STARTTLS mode and NTLM auth Jun 16, 2026
@bensonfx
bensonfx force-pushed the fix/smtp-starttls branch from e8955bf to a29c9d1 Compare June 16, 2026 13:02

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@common/email_test.go`:
- Around line 255-264: The test currently verifies that the email message is
sent correctly but does not confirm that STARTTLS was explicitly issued by the
client. Since the fake server accepts MAIL and DATA commands before TLS, the
test would pass even if STARTTLS was skipped. Add an assertion within the select
case where the message is validated to also check that the startTLSCommands
variable (or equivalent counter tracking STARTTLS invocations) reflects that
STARTTLS was actually executed. This ensures the test protects the core STARTTLS
security objective and prevents regression if STARTTLS enforcement is
accidentally removed.
- Around line 190-200: The certificate template in email_test.go contains
real-looking corporate hostnames that should be replaced with reserved test
domain names to avoid environment-specific identifiers in tests. Update the
CommonName field (currently set to "aixinexchange01.aixin-chip.com") and the
DNSNames array (currently containing "aixinexchange01" and
"aixinexchange01.aixin-chip.com") to use reserved test hostnames such as those
ending in .invalid or .test (for example, "example.test" or "test.invalid").
This ensures the test certificate uses standardized test domains instead of
realistic corporate identifiers.

In `@common/email.go`:
- Around line 44-56: The condition in the newSMTPClient function checks both
SMTPPort == 465 and SMTPSSLEnabled, which causes port 465 to unconditionally
force implicit TLS even when a different encryption mode like
SMTPStartTLSEnabled is explicitly configured. Remove the SMTPPort == 465 check
from the condition so that the implicit TLS path is only taken when
SMTPSSLEnabled is true, allowing the explicit encryption mode configuration to
take precedence over port-based inference.
- Around line 37-40: Add an explicit MinVersion field to the tls.Config struct
initialization in the smtpTLSConfig function to enforce TLS 1.2 as the minimum
version. This prevents accidental downgrades and makes the security requirement
explicit in the code, following best practices even though Go defaults to TLS
1.2.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d9271162-e7bc-4bec-8cee-68e612881335

📥 Commits

Reviewing files that changed from the base of the PR and between 4b1c4b0 and a29c9d1.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (26)
  • common/constants.go
  • common/email.go
  • common/email_ntlm_auth.go
  • common/email_test.go
  • common/init.go
  • go.mod
  • model/option.go
  • web/classic/src/components/settings/SystemSetting.jsx
  • web/classic/src/i18n/locales/en.json
  • web/classic/src/i18n/locales/fr.json
  • web/classic/src/i18n/locales/ja.json
  • web/classic/src/i18n/locales/ru.json
  • web/classic/src/i18n/locales/vi.json
  • web/classic/src/i18n/locales/zh-CN.json
  • web/classic/src/i18n/locales/zh-TW.json
  • web/classic/src/i18n/locales/zh.json
  • web/default/src/features/system-settings/integrations/email-settings-section.tsx
  • web/default/src/features/system-settings/operations/index.tsx
  • web/default/src/features/system-settings/operations/section-registry.tsx
  • web/default/src/features/system-settings/types.ts
  • web/default/src/i18n/locales/en.json
  • web/default/src/i18n/locales/fr.json
  • web/default/src/i18n/locales/ja.json
  • web/default/src/i18n/locales/ru.json
  • web/default/src/i18n/locales/vi.json
  • web/default/src/i18n/locales/zh.json
✅ Files skipped from review due to trivial changes (7)
  • web/classic/src/i18n/locales/en.json
  • web/classic/src/i18n/locales/fr.json
  • web/classic/src/i18n/locales/zh-TW.json
  • web/default/src/i18n/locales/zh.json
  • web/classic/src/i18n/locales/ru.json
  • web/default/src/i18n/locales/fr.json
  • web/default/src/i18n/locales/en.json
🚧 Files skipped from review as they are similar to previous changes (15)
  • common/constants.go
  • go.mod
  • web/default/src/features/system-settings/types.ts
  • web/default/src/features/system-settings/operations/section-registry.tsx
  • common/init.go
  • web/default/src/features/system-settings/operations/index.tsx
  • web/classic/src/i18n/locales/vi.json
  • web/default/src/features/system-settings/integrations/email-settings-section.tsx
  • web/classic/src/i18n/locales/zh.json
  • web/classic/src/i18n/locales/zh-CN.json
  • web/classic/src/i18n/locales/ja.json
  • web/default/src/i18n/locales/vi.json
  • common/email_ntlm_auth.go
  • web/default/src/i18n/locales/ru.json
  • web/default/src/i18n/locales/ja.json

Comment thread common/email_test.go
Comment on lines +190 to +200
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "aixinexchange01.aixin-chip.com",
},
NotBefore: time.Now().Add(-time.Hour),
NotAfter: time.Now().Add(time.Hour),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
DNSNames: []string{"aixinexchange01", "aixinexchange01.aixin-chip.com"},
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use reserved test hostnames in the fixture certificate.

The certificate embeds a real-looking corporate hostname. Replace it with a reserved .invalid/.test name to avoid leaking or normalizing environment-specific identifiers in tests.

Proposed fix
 	template := x509.Certificate{
 		SerialNumber: big.NewInt(1),
 		Subject: pkix.Name{
-			CommonName: "aixinexchange01.aixin-chip.com",
+			CommonName: "smtp.test.invalid",
 		},
 		NotBefore:   time.Now().Add(-time.Hour),
 		NotAfter:    time.Now().Add(time.Hour),
 		KeyUsage:    x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
 		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
-		DNSNames:    []string{"aixinexchange01", "aixinexchange01.aixin-chip.com"},
+		DNSNames:    []string{"smtp.test.invalid", "smtp.test.local"},
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "aixinexchange01.aixin-chip.com",
},
NotBefore: time.Now().Add(-time.Hour),
NotAfter: time.Now().Add(time.Hour),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
DNSNames: []string{"aixinexchange01", "aixinexchange01.aixin-chip.com"},
}
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "smtp.test.invalid",
},
NotBefore: time.Now().Add(-time.Hour),
NotAfter: time.Now().Add(time.Hour),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
DNSNames: []string{"smtp.test.invalid", "smtp.test.local"},
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@common/email_test.go` around lines 190 - 200, The certificate template in
email_test.go contains real-looking corporate hostnames that should be replaced
with reserved test domain names to avoid environment-specific identifiers in
tests. Update the CommonName field (currently set to
"aixinexchange01.aixin-chip.com") and the DNSNames array (currently containing
"aixinexchange01" and "aixinexchange01.aixin-chip.com") to use reserved test
hostnames such as those ending in .invalid or .test (for example, "example.test"
or "test.invalid"). This ensures the test certificate uses standardized test
domains instead of realistic corporate identifiers.

Comment thread common/email_test.go
Comment thread common/email.go
Comment on lines +37 to +40
func smtpTLSConfig() *tls.Config {
return &tls.Config{
ServerName: SMTPServer,
InsecureSkipVerify: SMTPInsecureSkipVerify, // #nosec G402 -- admin-controlled SMTP compatibility option.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Inspect declared Go/toolchain files and TLS configs to confirm explicit MinVersion coverage.
set -euo pipefail

printf 'Declared Go/toolchain files:\n'
fd -t f -HI 'go\.mod|go\.work|\.go-version|\.tool-versions|Dockerfile' . \
  -x sh -c 'printf "\n--- %s ---\n" "$1"; sed -n "1,80p" "$1"' sh {}

printf '\nTLS configs in Go sources:\n'
rg -nP 'tls\.Config\s*\{' -C2 --type go

Repository: QuantumNous/new-api

Length of output: 7063


🏁 Script executed:

# Find all tls.Config instantiations to assess scope
rg -nP 'tls\.Config\s*\{' --type go -A3

Repository: QuantumNous/new-api

Length of output: 811


🌐 Web query:

Go 1.25 default minimum TLS version crypto/tls

💡 Result:

In Go 1.25, the default minimum TLS version is TLS 1.2 [1][2]. This default applies to both TLS clients and servers when the MinVersion field in crypto/tls.Config is not explicitly set [2][3]. While TLS 1.0 remains the minimum version supported by the crypto/tls package, TLS 1.0 and TLS 1.1 are disabled by default [1][2][3]. For backward compatibility, the server-side default can be reverted to TLS 1.0 by setting the GODEBUG environment variable to tls10server=1 [1][2]. This specific backward compatibility setting was introduced in Go 1.22 and is scheduled to be removed in Go 1.27 [3][4].

Citations:


🌐 Web query:

SMTP TLS version requirements minimum TLS 1.2 compatibility

💡 Result:

As of June 2026, the industry standard and security best practice for SMTP is to support and prefer TLS 1.2 and TLS 1.3, while disabling all older, insecure versions [1][2][3]. Minimum TLS Version Requirements The IETF has deprecated TLS 1.0 and 1.1 due to known security vulnerabilities [1][3]. Consequently, the current minimum recommendation is TLS 1.2 [4][5]. Organizations are strongly advised to transition to TLS 1.2 or TLS 1.3 for all email submission, access, and relay traffic [1][6][3]. Major Provider Standards Major email service providers, including Microsoft (Office 365) and Google (Gmail), have moved to enforce these standards [7][8]. - Microsoft 365: Has deprecated TLS 1.0 and 1.1, requiring TLS 1.2 or higher for inbound SMTP connections [7][8]. - Google (Gmail): Requires TLS 1.2+ for bulk senders and strongly encourages it for all connections to ensure deliverability and security [8][9]. - General Industry: Using versions older than TLS 1.2 is widely considered obsolete and is a common cause of delivery failures and security warnings [1][2][8]. Implementation Recommendations To maintain secure and reliable mail flow, administrators should: 1. Configure MTAs to support only TLS 1.2 and 1.3 [1][2][3]. 2. Explicitly disable support for SSL 2.0, 3.0, TLS 1.0, and TLS 1.1 [2][3]. 3. Implement modern security protocols such as MTA-STS (Mail Transfer Agent Strict Transport Security) to enforce TLS requirements and protect against downgrade attacks [2][10]. 4. Where DNSSEC is available, deploy DANE (DNS-based Authentication of Named Entities) to provide further verification of MX certificates [2].

Citations:


Set an explicit minimum TLS version to prevent environment variable downgrades.

Although Go 1.25.1 defaults to TLS 1.2, explicitly setting MinVersion is a security best practice that prevents accidental downgrades via GODEBUG=tls10server=1 and makes the intent unmistakable in code. SMTP requires TLS 1.2+ per industry standards (Microsoft 365, Google, IETF).

Proposed fix
 func smtpTLSConfig() *tls.Config {
 	return &tls.Config{
 		ServerName:         SMTPServer,
+		MinVersion:         tls.VersionTLS12,
 		InsecureSkipVerify: SMTPInsecureSkipVerify, // `#nosec` G402 -- admin-controlled SMTP compatibility option.
 	}
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func smtpTLSConfig() *tls.Config {
return &tls.Config{
ServerName: SMTPServer,
InsecureSkipVerify: SMTPInsecureSkipVerify, // #nosec G402 -- admin-controlled SMTP compatibility option.
func smtpTLSConfig() *tls.Config {
return &tls.Config{
ServerName: SMTPServer,
MinVersion: tls.VersionTLS12,
InsecureSkipVerify: SMTPInsecureSkipVerify, // `#nosec` G402 -- admin-controlled SMTP compatibility option.
}
}
🧰 Tools
🪛 ast-grep (0.43.0)

[warning] 37-40: MinVersionis missing from this TLS configuration. By default, TLS 1.2 is currently used as the minimum when acting as a client, and TLS 1.0 when acting as a server. General purpose web applications should default to TLS 1.3 with all other protocols disabled. Only where it is known that a web server must support legacy clients with unsupported an insecure browsers (such as Internet Explorer 10), it may be necessary to enable TLS 1.0 to provide support. AddMinVersion: tls.VersionTLS13' to the TLS configuration to bump the minimum version to TLS 1.3.
Context: tls.Config{
ServerName: SMTPServer,
InsecureSkipVerify: SMTPInsecureSkipVerify, // #nosec G402 -- admin-controlled SMTP compatibility option.
}
Note: [CWE-327]: Use of a Broken or Risky Cryptographic Algorithm [OWASP A03:2017]: Sensitive Data Exposure [OWASP A02:2021]: Cryptographic Failures

(missing-ssl-minversion-go)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@common/email.go` around lines 37 - 40, Add an explicit MinVersion field to
the tls.Config struct initialization in the smtpTLSConfig function to enforce
TLS 1.2 as the minimum version. This prevents accidental downgrades and makes
the security requirement explicit in the code, following best practices even
though Go defaults to TLS 1.2.

Source: Linters/SAST tools

Comment thread common/email.go
bensonfx added 2 commits June 23, 2026 18:06
Add explicit SMTP STARTTLS configuration for 587-style connections and keep SSL/TLS as the implicit TLS mode.

Prefer PLAIN when advertised, keep LOGIN compatibility, and add NTLM as a fallback for Exchange SMTP servers that require it after STARTTLS.
@bensonfx
bensonfx force-pushed the fix/smtp-starttls branch from aa0e05c to a75da31 Compare June 23, 2026 10:07
@Calcium-Ion Calcium-Ion self-assigned this Jun 23, 2026
@Calcium-Ion

Copy link
Copy Markdown
Member
  • SMTPSSLEnabled=true:使用隐式 SSL/TLS 连接,适用于 465 等端口;

这个修改会导致现有使用465端口的用户出错

@Calcium-Ion

Copy link
Copy Markdown
Member

其他的没问题,方便修改吗,或者我改好推到pr后合并

@bensonfx

Copy link
Copy Markdown
Contributor Author

@Calcium-Ion 已修改

@Calcium-Ion
Calcium-Ion merged commit 2f23a66 into QuantumNous:main Jun 24, 2026
1 check passed
shudonglin added a commit to rayward-external/new-api that referenced this pull request Jun 27, 2026
* chore: avoid duplicate shadcn skill exposure

* fix: support SMTP STARTTLS mode and NTLM auth (QuantumNous#5426)

* fix: support SMTP STARTTLS mode and NTLM auth

Add explicit SMTP STARTTLS configuration for 587-style connections and keep SSL/TLS as the implicit TLS mode.

Prefer PLAIN when advertised, keep LOGIN compatibility, and add NTLM as a fallback for Exchange SMTP servers that require it after STARTTLS.

* fix: respect explicit SMTP encryption mode

* fix: preserve SMTP TLS compatibility

* fix: preserve SMTP PLAIN auth TLS guard

* chore(deps): bump github.com/ClickHouse/ch-go from 0.58.2 to 0.65.0 (QuantumNous#5664)

Bumps [github.com/ClickHouse/ch-go](https://github.com/ClickHouse/ch-go) from 0.58.2 to 0.65.0.
- [Release notes](https://github.com/ClickHouse/ch-go/releases)
- [Commits](ClickHouse/ch-go@v0.58.2...v0.65.0)

---
updated-dependencies:
- dependency-name: github.com/ClickHouse/ch-go
  dependency-version: 0.65.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: update agent skills and project config

- add vercel-react-best-practices skill (SKILL.md + full-guide.md)
- slim CLAUDE.md to import shared AGENTS.md conventions
- promote go-ntlmssp to a direct dependency in go.mod

* fix: date-fns-tz classic theme build error (QuantumNous#5676)

* chore(deps): update clickhouse-go and orb dependencies

* feat: add system task runner (QuantumNous#5680)

* feat: add system instance info panel (QuantumNous#5716)

* feat: add system instance reporting

* feat: show system instance resources

* fix: update translations for heartbeat messages in Russian and Vietnamese

* fix(web): replace default markdown renderer and expand syntax support (QuantumNous#5689)

* fix(markdown): render default markdown with marked

- switch default frontend markdown rendering from react-markdown/remark-gfm to marked to avoid old WebKit parse failures from lookbehind regex literals
- sanitize marked HTML output with DOMPurify and preserve external link target and rel behavior
- remove default direct dependencies on react-markdown, remark-gfm, and rehype-raw while leaving classic unchanged

* fix(markdown): expand default markdown rendering support

- render default markdown with marked extensions for KaTeX formulas, page breaks, and common emoji shortcodes.
- sanitize KaTeX output with an explicit DOMPurify allowlist while preserving external link behavior.
- avoid overriding marked text rendering so lists and inline parsing keep their internal parser context.

* fix(markdown): render diagram code blocks in default UI

- add sanitized SVG rendering for flow and sequence diagram code blocks.
- size flow nodes from their labels and route edges from node anchors to prevent clipping.
- style diagram nodes, arrows, labels, and notes with theme-aware classes.

* fix(web): sync channel card selection state (QuantumNous#5700)

* fix(web): hide wallet entry in profile dropdown when wallet module disabled (QuantumNous#5708)

The profile dropdown rendered the wallet item unconditionally, so it
still showed after an admin disabled the personal/topup (wallet) sidebar
module. Reuse the sidebar module visibility check so the dropdown honours
the same toggle as the sidebar.

Fixes QuantumNous#5696

* feat(system-settings): add user token limit configuration section (QuantumNous#5678)

* feat: add channel async polling delay toggle

Fixes QuantumNous#5717
Fixes QuantumNous#4244

* fix: add token limit save label translations

* feat: enhance i18n-translate skill

* feat: add date-fns and date-fns-tz dependencies

* feat: add date-fns and date-fns-tz paths to build configuration

* chore(deps): bump dompurify from 3.4.5 to 3.4.11 in /web/default (QuantumNous#5718)

Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.4.5 to 3.4.11.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](cure53/DOMPurify@3.4.5...3.4.11)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.4.11
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix(ci): install classic workspace dependencies for releases (QuantumNous#5719)

* fix: use neutral drawing task labels

* perf(web): streamline table actions and destructive dialogs (QuantumNous#5645)

* perf(data-table): autosize action columns

- exclude actions columns from shared table width calculations so action cells size to their content.
- remove fixed size and w-* width overrides from feature action columns to preserve content-based layout.

* perf(data-table): streamline row action controls

- expose common edit and status actions directly while moving secondary actions into overflow menus.
- add shared row action menu helpers so static and table rows use consistent action controls.
- let action columns size to their content instead of relying on fixed widths.

* fix(web): localize destructive dialog copy

- route delete, reset, and batch update confirmation text through i18n.
- add locale entries for affected channel, model, system settings, and user dialogs.

* perf(web): unify destructive dialog actions

- align delete and cleanup confirmation buttons with the shared destructive variant.
- replace custom destructive color overrides with semantic button variants.
- clean up lint errors in touched dialog files before committing.

* fix(web): add user action success translations

- add localized success messages for user delete, status, and role changes.
- keep user management toast copy available across all frontend locales.

* fix(data-table): prevent mobile badge clipping

- expose badge cell slots so mobile card styles can target nested badge wrappers.
- reset badge margins in card rows to keep provider icons fully visible on small screens.

* fix: add Waffo goods info and webhook SDK update (QuantumNous#5704)

* fix: add Waffo goods info and webhook SDK update

* chore: remove Waffo test code from PR

* fix(model-pricing): refresh tiered expression editor when switching models (QuantumNous#5752)

Switching models in the pricing editor kept the previous model's tiers and prices in the expression panel: TieredPricingEditor seeds its internal visual/raw state only on mount, and the initRef guard never re-ran on prop changes, so only the model name updated.

Bump a reload token in the same effect that seeds billingExpr and use it as the editor's key, so a freshly loaded model remounts the editor and re-parses its expression. The token changes in lockstep with billingExpr, and user edits (which only touch state) do not trigger it.

Closes QuantumNous#5750

* chore(deps): sync bun.lock for dompurify 3.4.11 (QuantumNous#5738)

* fix(theme): 切换前端主题后重置到首页,避免路由 404 (QuantumNous#5612)

* fix(theme): 切换前端主题后重置到首页,避免路由 404
经典前端与新版前端的路由路径不同,切换主题后停留在原路径会导致 404:
- 经典前端切换到新版前端时跳转首页,不再原地刷新当前路径
- 新版前端保存时若前端主题发生变化,保存成功后跳转首页

Fixes QuantumNous#4947

* fix: 更新前端切换提示信息,修正页面跳转逻辑

* fix(task): attribute async task usage log to the initiating node (QuantumNous#5684)

Async task usage logs (LogQuotaData node dimension) were recorded
under whichever node happened to poll the task to completion, not the
node that submitted it. For token/adaptor-billed video tasks the
pre-deduction is often 0, so the entire quota landed on the last
polling node.

Snapshot common.NodeName into TaskPrivateData at submit time and use
it when writing the settlement consume log; fall back to the current
node when empty so existing tasks stay compatible.

* chore: update i18n skill

* feat: better admin permissions (QuantumNous#5755)

* feat: add casbin admin permissions

* feat: improve audit logging to associate logs with actual operators and target users

* feat: enhance admin permissions and UI interactions for sensitive actions

* Refactor authz RBAC and tighten channel permissions

* Split channel authz field policy

* Address channel authz review findings

* fix: adapt ClickHouse log LIKE filters

* feat(playground): improve Playground chat experience and Markdown rendering (QuantumNous#5217)

* refactor(playground): streamline chat request state

- extract conversation actions from the page component to keep message flow logic reusable.
- unify streaming and non-streaming generation state, including abort support for non-stream requests.
- simplify message rendering and payload construction while localizing Playground prompts.

* fix(playground): validate persisted chat state

- wrap saved Playground state with a storage version while still reading legacy values.

- validate config, parameter toggles, and messages before restoring them from localStorage.

- cap stored chat history to the latest messages to avoid oversized or stale state.

* refactor(playground): centralize message content access

- route chat rendering, copy actions, and error display through shared message helpers.

- reuse the current-version update helper for non-streaming assistant responses.

- keep message version details behind utility functions to reduce future model churn.

* refactor(playground): split storage schemas

- move Playground storage validation schemas into a dedicated module.

- keep storage read and write logic focused on migration, trimming, and persistence.

- preserve the existing storage envelope and validation behavior.

* refactor(playground): extract options loading hook

- move model and group queries into a dedicated hook so the page component stays focused on layout wiring.
- preserve existing fallback selection and error toast behavior while reusing the hook through the playground barrel export.

* refactor(playground): extract prompt suggestions

- move static prompt suggestion rendering into a focused component so the input stays centered on compose controls.
- preserve translated suggestion submission behavior while isolating icon metadata from the input form.

* refactor(playground): extract input tools

- move attachment and search controls into a dedicated component so the prompt input stays focused on compose state.
- keep existing development toast behavior and disabled handling while centralizing tool metadata.

* refactor(playground): extract input controls

- move model, group, send, and stop controls into a focused component so the input only manages compose state.
- preserve existing disabled states and generation button behavior while isolating control rendering.

* refactor(playground): extract message content display

- move sources, reasoning, loading, error, and response rendering into a dedicated message content component.
- keep the chat list focused on message iteration, edit state, and action wiring without changing display behavior.

* refactor(playground): extract message editor

- move inline message editing controls into a dedicated editor component so the chat list stays focused on rendering flow.
- preserve save, save-and-submit, cancel, and disabled-state behavior for edited messages.

* refactor(playground): extract stream error parsing

- move SSE error payload parsing into a reusable stream utility so the request hook stays focused on lifecycle handling.
- preserve existing error message, error code, and fallback behavior for raw or empty stream errors.

* refactor(playground): extract request error parsing

- move non-stream request error extraction into a shared utility so the chat handler stays focused on request flow.
- preserve the existing response message, error code, and fallback priority for failed chat completions.

* refactor(playground): extract streaming chunk updates

- move reasoning and content chunk application into a message utility so the chat handler only wires stream events.
- preserve error-state skipping, reasoning accumulation, and content streaming behavior for assistant messages.

* refactor(playground): extract message reasoning parser

- move think tag parsing into a dedicated playground message utility.
- export the parser through the shared playground lib barrel for consistent imports.

* refactor(playground): extract message streaming utilities

- move stream chunk application and message finalization into a dedicated utility.
- keep stored message sanitization with the streaming lifecycle helpers.

* refactor(playground): extract message update utilities

- move assistant message update helpers into a focused playground utility.
- keep error-state message updates separate from core message construction helpers.

* refactor(playground): extract completion choice handling

- move non-streaming choice application into the message streaming utilities.
- keep the chat handler focused on request orchestration and message updates.

* refactor(playground): centralize assistant completion state

- add a helper for finalizing assistant messages with complete status.
- reuse the helper in stream completion and stop-generation paths.

* refactor(playground): extract stream message parsing

- move SSE delta parsing into a shared stream utility.
- keep the stream request hook focused on lifecycle handling and update dispatch.

* refactor(playground): extract stream ready state checks

- move SSE ready-state status handling into stream utilities.
- keep weak source status typing outside the stream request hook.

* refactor(playground): extract conversation message helpers

- move send, regenerate, and edit message list construction into focused utilities.
- keep the conversation hook focused on edit state and update dispatch.

* refactor(playground): extract state initialization helpers

- move playground initial state loading into focused utility helpers.
- centralize message state updater resolution outside the React state hook.

* refactor(playground): extract option fallback helpers

- move model and group fallback selection into focused playground utilities.
- keep the options hook focused on query results, toasts, and config updates.

* refactor(playground): extract message action helpers

- move message action state derivation into focused utilities.

- keep the action component focused on guarded handlers and rendering.

* refactor(playground): extract input control state

- move submit, stop, and selector state derivation into a pure helper.

- keep input controls focused on rendering model selectors and action buttons.

* refactor(playground): extract message content state

- move source, reasoning, loader, and body visibility checks into a pure helper.

- use a discriminated state shape so rendered reasoning content stays type-safe.

* refactor(playground): extract message editor state

- move save eligibility and submit visibility checks into a pure helper.

- keep the editor component focused on textarea and button rendering.

* refactor(playground): extract message error state

- move error kind, fallback content, and admin visibility checks into a pure helper.

- centralize the model pricing settings path used by the error action.

* refactor(playground): extract chat render state

- move editing content lookup and per-message render flags into conversation helpers.

- keep the chat component focused on mapping messages to editor and content views.

* refactor(playground): extract suggestion display state

- move suggestion class selection into a pure helper.

- keep the suggestions component focused on translation and rendering.

* refactor(playground): extract assistant message state checks

- move final and pending assistant status checks into streaming utilities.

- keep the chat handler focused on request lifecycle updates.

* refactor(playground): extract input tool state

- move attachment action metadata and development notices into input tool utilities.

- keep the input tools component focused on menu and button rendering.

* refactor(playground): extract stream protocol checks

- move SSE done-message and closed-ready-state checks into stream utilities.

- keep the stream request hook focused on event handling flow.

* refactor(playground): extract message removal helper

- move delete-message filtering into conversation message utilities.

- keep the conversation hook focused on action orchestration.

* refactor(playground): extract option error messages

- move option load error message selection into playground option utilities
- keep the options hook focused on query effects and fallback updates

* refactor(playground): extract input submit text helper

- move prompt submit text validation into input control utilities
- let the input component submit only when a concrete text value is available

* refactor(playground): centralize error message checks

- add a shared helper for identifying error messages
- remove direct status string checks from message content rendering

* refactor(playground): extract message content display checks

- move loader and content visibility decisions into local helper functions
- keep message content state assembly focused on composing render state

* refactor(playground): replace raw message role checks

- use shared message role constants in conversation edit handling
- avoid raw assistant role literals when validating API messages

* refactor(playground): extract non-stream response handling

- move chat completion response choice handling into message streaming utilities
- keep the chat handler focused on request lifecycle and error routing

* refactor(playground): centralize stream cleanup

- reuse one stream cleanup path for completion, errors, startup failures, and manual stops
- preserve the current-source guard when closing SSE streams

* refactor(playground): extract pending assistant check

- centralize pending assistant message detection in streaming utilities
- reuse the helper when sanitizing stored playground messages

* perf(playground): improve mobile input controls

- split mobile input controls into selector and action rows
- keep the desktop input footer compact while reducing mobile control crowding

* perf(playground): add starter empty state

- show starter prompts in the empty playground chat area
- wire empty-state prompt selection into the existing send flow
- add localized copy for the new empty state

* perf(playground): improve mobile message actions

- collapse mobile message actions into a touch-friendly dropdown menu
- keep the desktop hover action strip unchanged for pointer workflows
- share one action list between desktop buttons and the mobile menu

* perf(playground): add error recovery actions

- show retry, edit, and delete actions inside error message alerts
- route edit recovery to the previous user prompt when available
- keep recovery controls touch-friendly on mobile layouts

* perf(playground): refine message editing experience

- present message edits in a focused bordered editor panel
- add unsaved-change state, reset, and cancel confirmation flows
- improve mobile touch targets and keyboard shortcuts for editing

* perf(playground): improve markdown code blocks

- render fenced markdown code with syntax highlighting, line numbers, and fallback plain text
- add copy, download, and collapse controls for playground AI responses
- tighten code block layout and theme token styles for responsive markdown rendering

* fix(playground): constrain markdown code block height

- collapse long playground code blocks after a short preview instead of waiting for very large snippets
- cap expanded code blocks so long responses scroll inside the code block
- keep generic code block usage unconstrained unless a caller opts in

* feat(playground): add chat history clearing

- add a toolbar action that is enabled only when saved playground messages exist.
- confirm destructive clears before removing browser-stored conversation state.
- add localized strings for the action, dialog, and completion toast.

* perf(playground): improve chat markdown rendering

- refine assistant and user message surfaces so chat content matches the app UI.
- normalize markdown typography, tables, images, lists, blockquotes, and details rendering.
- add indentation cues for collapsible reasoning and source sections.

* style: format code block component

* style: format playground frontend files

* feat(playground): render markdown with stream parser

- replace Streamdown with stream-markdown-parser for project-owned markdown rendering and styling.
- split response rendering into focused block, inline, table, alert, details, and footnote modules.
- pass message final state into response parsing so streaming content can be parsed incrementally.

* fix(playground): localize reasoning and chat feedback

- translate reasoning status, message actions, playground errors, and response renderer fallbacks across supported locales.
- keep reasoning duration numeric and tighten the collapsible layout to prevent trigger jitter.
- register dynamic keys so i18n sync keeps runtime labels covered.

* refactor(playground): group files by functional area

- move chat, input, and message components into focused subdirectories to make the UI structure easier to scan.
- split playground helpers into input, message, streaming, storage, options, state, and suggestions modules.
- update barrel exports and imports so existing feature entry points continue to work.

* fix(playground): prevent history replay from freezing page

- defer saved conversation loading so route entry no longer blocks on localStorage parsing and markdown rendering.
- limit initial history rendering and skip expensive markdown parsing for oversized responses.
- normalize corrupted streaming snapshots and cumulative chunks to keep saved playground history bounded.
- add message timing metadata and layout alignment groundwork without introducing live timers.

* feat(playground): allow regenerating from user messages

- show regenerate actions on user messages with saved content.
- truncate following conversation state before starting a fresh assistant response.

* feat(playground): add raw response source view

- add a per-message source toggle for assistant responses.
- render raw response content with the existing code block viewer.
- localize the new source and preview action labels.

* feat(playground): render code with unified editor

- replace Shiki HTML rendering with a read-only CodeMirror view for code blocks and raw responses.
- reuse the same CodeMirror frame for message editing so source and edit modes stay visually aligned.
- add lightweight CodeMirror dependencies while keeping language support scoped to Markdown.

* perf(playground): streamline chat input controls

- combine model and group selection into one compact picker for faster context switching.
- switch playground action buttons to icon-first controls with tooltips to reduce toolbar width.
- refresh input footer styling and submit states so active and destructive actions are clearer.
- bump dompurify lockfile entry to keep the frontend dependency current.

* fix(playground): filter models by selected group

- query user models by the selected playground group instead of reusing the cross-group model union.
- clear unavailable model selections and block sending when the active group has no models.
- align model selector and error action controls with the existing playground interaction style.

* perf(playground): remove input suggestion chips

- remove the prompt suggestion row below the playground input to reduce visual noise.
- delete the now-unused suggestion component and display helper.

* perf(playground): stabilize reasoning trigger layout

- use fixed icon slots around the reasoning label so the left content stays still when toggling.
- limit the open state animation to the chevron rotation for a smoother collapse interaction.

* perf(playground): smooth reasoning expansion

- use the collapsible panel height animation for vertical reasoning reveals.
- sync inner content opacity and position with the panel state.

* fix(auth): align password validation copy (QuantumNous#5759)

* fix(i18n): add missing frontend translations

- add missing locale entries for API key loading, channel model empty states, auth, playground, and model configuration copy.
- correct inaccurate Russian and Vietnamese model empty-state translations to avoid fallback or misleading copy.

* fix(auth): align password validation copy

- remove the login password length gate so existing shorter passwords are not blocked before reaching the server.
- reuse distinct minimum-length and 8-20 character messages based on the actual validation rule.
- drop unused duplicate password locale keys and align the user creation placeholder with the 8-20 character constraint.

* fix(i18n): add auth validation message translations

- cover schema-driven auth form errors that are translated through FormMessage.
- keep password, username, confirmation, and OTP validation messages available in every locale.

* fix(web): render custom HTML and Markdown content consistently (QuantumNous#5760)

* fix(markdown): render announcement markdown consistently

- support soft line breaks for announcement markdown without changing the default parser behavior.
- add explicit markdown element styles so lists, tables, code blocks, and quotes render correctly when typography styles are unavailable.
- apply the announcement markdown mode in both the popover and detail dialog for consistent display.

* refactor(markdown): simplify fallback markdown styles

- remove duplicate typography utility classes now covered by explicit markdown element fallbacks.
- keep the markdown renderer behavior unchanged while reducing class noise.
- modernize small helper expressions to satisfy targeted lint checks.

* fix(content): render custom HTML consistently

- add shared rich content rendering so custom HTML and Markdown use the same path across public pages and announcements.
- reuse common URL and HTML detection instead of duplicating content format checks per page.
- keep custom home content inside the standard public layout while preserving full-page iframe rendering for external URLs.

* fix(security): pin patched frontend transitive dependencies

* fix(web): secure rich content rendering

* fix(web): harden iframe sandboxing

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: CaIon <i@caion.me>
Co-authored-by: Benson Yan <fuxin04@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Seefs <40468931+seefs001@users.noreply.github.com>
Co-authored-by: QuentinHsu <xuquentinyang@gmail.com>
Co-authored-by: yyhhyyyyyy <yyhhyyyyyy8@gmail.com>
Co-authored-by: feitianbubu <feitianbubu@qq.com>
Co-authored-by: RedwindA <128586631+RedwindA@users.noreply.github.com>
Co-authored-by: zhongyuanzhao-alt <zhongyuan.zhao@waffo.com>
Co-authored-by: peakchao <zhangzhichaolove@vip.qq.com>
ruanhangjian pushed a commit to ruanhangjian/new-api that referenced this pull request Jul 11, 2026
* fix: support SMTP STARTTLS mode and NTLM auth

Add explicit SMTP STARTTLS configuration for 587-style connections and keep SSL/TLS as the implicit TLS mode.

Prefer PLAIN when advertised, keep LOGIN compatibility, and add NTLM as a fallback for Exchange SMTP servers that require it after STARTTLS.

* fix: respect explicit SMTP encryption mode

* fix: preserve SMTP TLS compatibility
zhaodechao2008 pushed a commit to zhaodechao2008/new-api that referenced this pull request Jul 27, 2026
* fix: support SMTP STARTTLS mode and NTLM auth

Add explicit SMTP STARTTLS configuration for 587-style connections and keep SSL/TLS as the implicit TLS mode.

Prefer PLAIN when advertised, keep LOGIN compatibility, and add NTLM as a fallback for Exchange SMTP servers that require it after STARTTLS.

* fix: respect explicit SMTP encryption mode

* fix: preserve SMTP TLS compatibility
330079598 pushed a commit to 330079598/new-api that referenced this pull request Aug 19, 2026
* fix: support SMTP STARTTLS mode and NTLM auth

Add explicit SMTP STARTTLS configuration for 587-style connections and keep SSL/TLS as the implicit TLS mode.

Prefer PLAIN when advertised, keep LOGIN compatibility, and add NTLM as a fallback for Exchange SMTP servers that require it after STARTTLS.

* fix: respect explicit SMTP encryption mode

* fix: preserve SMTP TLS compatibility
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: Exchange/微软系 SMTP 在 STARTTLS 后仅支持 NTLM 认证时发送失败

2 participants