feat(mail): Add support for multiple domains per mail service
- Add `Domains` field to MailServiceConfig for managing additional domains under single API - Implement `matchDomain` helper function for precise and subdomain matching logic - Update `GetServiceByDomain` to check both primary domain and additional domains list - Enhance EmailConfig UI to display domain count and allow comma-separated domain input - Add domains field to mail service request/response structures in API handlers - Update frontend types to include domains array in MailService interface - Improve documentation with clarification on primary vs additional domains usage - Allows single mail service API to manage multiple email domains for verification and operations
This commit is contained in:
@@ -140,7 +140,7 @@ func startServer(cfg *config.Config) {
|
||||
mux.HandleFunc("/api/db/owners/clear-used", api.CORS(handleClearUsedOwners)) // 清理已使用
|
||||
mux.HandleFunc("/api/db/owners/delete/", api.CORS(handleDeleteOwner)) // DELETE /api/db/owners/delete/{id}
|
||||
mux.HandleFunc("/api/db/owners/batch-delete", api.CORS(handleBatchDeleteOwners)) // POST 批量删除
|
||||
mux.HandleFunc("/api/db/owners/ids", api.CORS(handleGetOwnerIDs)) // GET 获取所有ID(全选用)
|
||||
mux.HandleFunc("/api/db/owners/ids", api.CORS(handleGetOwnerIDs)) // GET 获取所有ID(全选用)
|
||||
mux.HandleFunc("/api/db/owners/refetch-account-ids", api.CORS(api.HandleRefetchAccountIDs))
|
||||
mux.HandleFunc("/api/upload/validate", api.CORS(api.HandleUploadValidate))
|
||||
|
||||
@@ -739,6 +739,7 @@ func handleMailServices(w http.ResponseWriter, r *http.Request) {
|
||||
"apiBase": s.APIBase,
|
||||
"apiToken": s.APIToken,
|
||||
"domain": s.Domain,
|
||||
"domains": s.Domains,
|
||||
"emailPath": s.EmailPath,
|
||||
"addUserApi": s.AddUserAPI,
|
||||
}
|
||||
@@ -747,12 +748,13 @@ func handleMailServices(w http.ResponseWriter, r *http.Request) {
|
||||
case "POST":
|
||||
var req struct {
|
||||
Services []struct {
|
||||
Name string `json:"name"`
|
||||
APIBase string `json:"apiBase"`
|
||||
APIToken string `json:"apiToken"`
|
||||
Domain string `json:"domain"`
|
||||
EmailPath string `json:"emailPath"`
|
||||
AddUserAPI string `json:"addUserApi"`
|
||||
Name string `json:"name"`
|
||||
APIBase string `json:"apiBase"`
|
||||
APIToken string `json:"apiToken"`
|
||||
Domain string `json:"domain"`
|
||||
Domains []string `json:"domains"`
|
||||
EmailPath string `json:"emailPath"`
|
||||
AddUserAPI string `json:"addUserApi"`
|
||||
} `json:"services"`
|
||||
}
|
||||
|
||||
@@ -778,6 +780,7 @@ func handleMailServices(w http.ResponseWriter, r *http.Request) {
|
||||
APIBase: s.APIBase,
|
||||
APIToken: s.APIToken,
|
||||
Domain: s.Domain,
|
||||
Domains: s.Domains,
|
||||
EmailPath: emailPath,
|
||||
AddUserAPI: addUserAPI,
|
||||
})
|
||||
|
||||
@@ -10,12 +10,13 @@ import (
|
||||
|
||||
// MailServiceConfig 邮箱服务配置
|
||||
type MailServiceConfig struct {
|
||||
Name string `yaml:"name" json:"name"`
|
||||
APIBase string `yaml:"api_base" json:"api_base"`
|
||||
APIToken string `yaml:"api_token" json:"api_token"`
|
||||
Domain string `yaml:"domain" json:"domain"`
|
||||
EmailPath string `yaml:"email_path,omitempty" json:"email_path,omitempty"`
|
||||
AddUserAPI string `yaml:"add_user_api,omitempty" json:"add_user_api,omitempty"`
|
||||
Name string `yaml:"name" json:"name"`
|
||||
APIBase string `yaml:"api_base" json:"api_base"`
|
||||
APIToken string `yaml:"api_token" json:"api_token"`
|
||||
Domain string `yaml:"domain" json:"domain"`
|
||||
Domains []string `yaml:"domains,omitempty" json:"domains,omitempty"` // 附加域名列表(同一个API管理的多个域名)
|
||||
EmailPath string `yaml:"email_path,omitempty" json:"email_path,omitempty"`
|
||||
AddUserAPI string `yaml:"add_user_api,omitempty" json:"add_user_api,omitempty"`
|
||||
}
|
||||
|
||||
// Config 应用配置 (实时从数据库读取)
|
||||
|
||||
@@ -100,14 +100,31 @@ func GetRandomService() config.MailServiceConfig {
|
||||
return currentMailServices[rand.Intn(len(currentMailServices))]
|
||||
}
|
||||
|
||||
// matchDomain 检查邮箱域名是否匹配服务域名(精确匹配或子域名匹配)
|
||||
func matchDomain(emailDomain, serviceDomain string) bool {
|
||||
if serviceDomain == "" {
|
||||
return false
|
||||
}
|
||||
return emailDomain == serviceDomain || strings.HasSuffix(emailDomain, "."+serviceDomain)
|
||||
}
|
||||
|
||||
// GetServiceByDomain 根据域名获取对应的邮箱服务
|
||||
// 会同时检查 Domain(主域名)和 Domains(附加域名列表)
|
||||
func GetServiceByDomain(domain string) *config.MailServiceConfig {
|
||||
mailServicesMutex.RLock()
|
||||
defer mailServicesMutex.RUnlock()
|
||||
|
||||
for _, s := range currentMailServices {
|
||||
if s.Domain == domain || strings.HasSuffix(domain, "."+s.Domain) {
|
||||
return &s
|
||||
for i := range currentMailServices {
|
||||
s := ¤tMailServices[i]
|
||||
// 检查主域名
|
||||
if matchDomain(domain, s.Domain) {
|
||||
return s
|
||||
}
|
||||
// 检查附加域名列表
|
||||
for _, d := range s.Domains {
|
||||
if matchDomain(domain, d) {
|
||||
return s
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user