This commit is contained in:
parent
d4c3994102
commit
9b19268c00
@ -161,6 +161,27 @@ func CurrentMailDomains() MailDomains {
|
||||
return domains
|
||||
}
|
||||
|
||||
func CurrentEmailPolicy() EmailConfig {
|
||||
manager := CurrentManager()
|
||||
if manager != nil {
|
||||
runtime := manager.Snapshot()
|
||||
if runtime.Generation != 0 {
|
||||
return runtime.Email.Policy
|
||||
}
|
||||
}
|
||||
|
||||
cfg := CurrentConfig()
|
||||
if cfg == nil {
|
||||
return EmailConfig{}
|
||||
}
|
||||
return EmailConfig{
|
||||
SMTPPort: cfg.SMTPPort,
|
||||
SpamFilterLevel: cfg.SpamFilterLevel,
|
||||
LoginVerificationPolicy: cfg.LoginPolicy,
|
||||
ExternalRecoveryEnabled: cfg.ExternalRecoveryEnabled,
|
||||
}
|
||||
}
|
||||
|
||||
type SMTPRuntimeSettings struct {
|
||||
Relay SMTPConfig
|
||||
Password string
|
||||
@ -213,22 +234,15 @@ func CurrentSMTPRuntimeSettings() (SMTPRuntimeSettings, error) {
|
||||
|
||||
func CurrentMailPorts() MailPorts {
|
||||
ports := MailPorts{SMTP: 25, IMAP: 143, POP3: 110}
|
||||
manager := CurrentManager()
|
||||
if manager == nil {
|
||||
return ports
|
||||
policy := CurrentEmailPolicy()
|
||||
if policy.SMTPPort > 0 && policy.SMTPPort <= 65535 {
|
||||
ports.SMTP = policy.SMTPPort
|
||||
}
|
||||
runtime := manager.Snapshot()
|
||||
if runtime.Generation == 0 {
|
||||
return ports
|
||||
if policy.IMAPPort > 0 && policy.IMAPPort <= 65535 {
|
||||
ports.IMAP = policy.IMAPPort
|
||||
}
|
||||
if runtime.Email.Policy.SMTPPort > 0 && runtime.Email.Policy.SMTPPort <= 65535 {
|
||||
ports.SMTP = runtime.Email.Policy.SMTPPort
|
||||
}
|
||||
if runtime.Email.Policy.IMAPPort > 0 && runtime.Email.Policy.IMAPPort <= 65535 {
|
||||
ports.IMAP = runtime.Email.Policy.IMAPPort
|
||||
}
|
||||
if runtime.Email.Policy.POP3Port > 0 && runtime.Email.Policy.POP3Port <= 65535 {
|
||||
ports.POP3 = runtime.Email.Policy.POP3Port
|
||||
if policy.POP3Port > 0 && policy.POP3Port <= 65535 {
|
||||
ports.POP3 = policy.POP3Port
|
||||
}
|
||||
return ports
|
||||
}
|
||||
|
||||
@ -75,6 +75,52 @@ func TestCurrentMailPortsUsesSafeDefaultsWithoutRuntimeManager(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrentEmailPolicyReadsPartitionSnapshot(t *testing.T) {
|
||||
previousManager := CurrentManager()
|
||||
defer SetRuntimeManager(previousManager)
|
||||
|
||||
runtime := validRuntimeConfig()
|
||||
runtime.Email.Policy = EmailConfig{
|
||||
SMTPPort: 2525,
|
||||
IMAPPort: 1143,
|
||||
POP3Port: 1110,
|
||||
MaxMessageBytes: 8 << 20,
|
||||
SpamFilterLevel: 2,
|
||||
LoginVerificationPolicy: "new_device",
|
||||
ExternalRecoveryEnabled: true,
|
||||
}
|
||||
SetRuntimeManager(&ConfigManager{snapshots: runtimeAccessSnapshotStore{runtime: runtime}})
|
||||
|
||||
got := CurrentEmailPolicy()
|
||||
if got != runtime.Email.Policy {
|
||||
t.Fatalf("email policy = %+v, want partition snapshot", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrentEmailPolicyFallsBackToLegacyConfig(t *testing.T) {
|
||||
previousManager := CurrentManager()
|
||||
previousInstance := Instance
|
||||
defer func() {
|
||||
SetRuntimeManager(previousManager)
|
||||
Instance = previousInstance
|
||||
PublishConfigSnapshot(previousInstance)
|
||||
}()
|
||||
SetRuntimeManager(nil)
|
||||
|
||||
Instance = &Config{
|
||||
SMTPPort: 2525,
|
||||
SpamFilterLevel: 2,
|
||||
LoginPolicy: "new_device",
|
||||
ExternalRecoveryEnabled: true,
|
||||
}
|
||||
PublishConfigSnapshot(Instance)
|
||||
|
||||
got := CurrentEmailPolicy()
|
||||
if got.SMTPPort != 2525 || got.IMAPPort != 0 || got.POP3Port != 0 || got.MaxMessageBytes != 0 || got.SpamFilterLevel != 2 || got.LoginVerificationPolicy != "new_device" || !got.ExternalRecoveryEnabled {
|
||||
t.Fatalf("legacy email policy = %+v, want mapped fallback", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrentMailPortsReadsEmailPolicySnapshot(t *testing.T) {
|
||||
previousManager := CurrentManager()
|
||||
defer SetRuntimeManager(previousManager)
|
||||
|
||||
@ -60,8 +60,8 @@ type attachment struct {
|
||||
}
|
||||
|
||||
func Send(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
cfg := config.CurrentConfig()
|
||||
if cfg == nil || cfg.Domain == "" || len(cfg.Domains) == 0 {
|
||||
domains := config.CurrentMailDomains()
|
||||
if domains.Primary == "" || len(domains.Accepted) == 0 {
|
||||
response.NewErrorResponse(response.ServerError, "服务配置不可用", "").FPrint(w)
|
||||
return
|
||||
}
|
||||
@ -73,17 +73,17 @@ func Send(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
log.WithContext(ctx).Infof("发送邮件")
|
||||
|
||||
if reqData.From.Email != "" && !validation.IsAuthorizedSender(reqData.From.Email, ctx.UserAccount, ctx.IsAdmin, cfg.Domains) {
|
||||
if reqData.From.Email != "" && !validation.IsAuthorizedSender(reqData.From.Email, ctx.UserAccount, ctx.IsAdmin, domains.Accepted) {
|
||||
response.NewErrorResponse(response.ParamsError, "\u53d1\u4ef6\u4eba\u5730\u5740\u4e0d\u5141\u8bb8", "").FPrint(w)
|
||||
return
|
||||
}
|
||||
if reqData.Sender.Email != "" && !validation.IsAuthorizedSender(reqData.Sender.Email, ctx.UserAccount, ctx.IsAdmin, cfg.Domains) {
|
||||
if reqData.Sender.Email != "" && !validation.IsAuthorizedSender(reqData.Sender.Email, ctx.UserAccount, ctx.IsAdmin, domains.Accepted) {
|
||||
response.NewErrorResponse(response.ParamsError, "\u53d1\u9001\u8005\u5730\u5740\u4e0d\u5141\u8bb8", "").FPrint(w)
|
||||
return
|
||||
}
|
||||
|
||||
if reqData.From.Email == "" {
|
||||
reqData.From.Email = ctx.UserAccount + "@" + cfg.Domain
|
||||
reqData.From.Email = ctx.UserAccount + "@" + domains.Primary
|
||||
}
|
||||
|
||||
if reqData.From.Email == "" {
|
||||
@ -192,7 +192,7 @@ func Send(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
log.WithContext(ctx).Debugf("插件执行--SendBefore End")
|
||||
|
||||
if e.From == nil || e.Sender == nil || !validation.IsAuthorizedSender(e.From.EmailAddress, ctx.UserAccount, ctx.IsAdmin, cfg.Domains) || !validation.IsAuthorizedSender(e.Sender.EmailAddress, ctx.UserAccount, ctx.IsAdmin, cfg.Domains) {
|
||||
if e.From == nil || e.Sender == nil || !validation.IsAuthorizedSender(e.From.EmailAddress, ctx.UserAccount, ctx.IsAdmin, domains.Accepted) || !validation.IsAuthorizedSender(e.Sender.EmailAddress, ctx.UserAccount, ctx.IsAdmin, domains.Accepted) {
|
||||
response.NewErrorResponse(response.ParamsError, "\u63d2\u4ef6\u4fee\u6539\u4e86\u672a\u6388\u6743\u7684\u53d1\u4ef6\u4eba", "").FPrint(w)
|
||||
return
|
||||
}
|
||||
@ -208,7 +208,7 @@ func Send(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
msgID, err := parsemail.GenerateMsgID(cfg.Domain)
|
||||
msgID, err := parsemail.GenerateMsgID(domains.Primary)
|
||||
if err != nil {
|
||||
log.WithContext(ctx).WithError(err).Error("generate outgoing message ID failed")
|
||||
response.NewErrorResponse(response.ServerError, i18n.GetText(ctx.Lang, "send_fail"), "").FPrint(w)
|
||||
|
||||
@ -139,14 +139,13 @@ func UserList(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
|
||||
func Info(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
cfg := config.CurrentConfig()
|
||||
if cfg == nil || cfg.Domain == "" {
|
||||
mailDomains := config.CurrentMailDomains()
|
||||
if mailDomains.Primary == "" {
|
||||
response.NewErrorResponse(response.ServerError, "服务配置不可用", "").FPrint(w)
|
||||
return
|
||||
}
|
||||
domains := cfg.Domains
|
||||
domains = array.Difference(domains, []string{cfg.Domain})
|
||||
domains = append([]string{cfg.Domain}, domains...)
|
||||
domains := array.Difference(mailDomains.Accepted, []string{mailDomains.Primary})
|
||||
domains = append([]string{mailDomains.Primary}, domains...)
|
||||
result := map[string]any{
|
||||
"account": ctx.UserAccount,
|
||||
"name": ctx.UserName,
|
||||
|
||||
@ -140,14 +140,16 @@ func persistInitialAudit(ctx *context.Context, modelEmail models.Email, userIDs
|
||||
}
|
||||
|
||||
func resolveIncomingUsers(ctx *context.Context, email *parsemail.Email, emailType int, reallyTo []string, SPFStatus, dkimStatus bool) ([]*models.User, bool, error) {
|
||||
cfg := config.CurrentConfig()
|
||||
if cfg == nil {
|
||||
return nil, false, stderrors.New("runtime configuration is unavailable")
|
||||
}
|
||||
if emailType != int(consts.EmailTypeReceive) {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
policy := config.CurrentEmailPolicy()
|
||||
domains := config.CurrentMailDomains()
|
||||
if len(domains.Accepted) == 0 {
|
||||
return nil, false, stderrors.New("runtime configuration is unavailable")
|
||||
}
|
||||
|
||||
accounts := incomingAccounts(email, reallyTo)
|
||||
var users []*models.User
|
||||
if len(accounts) > 0 {
|
||||
@ -164,9 +166,9 @@ func resolveIncomingUsers(ctx *context.Context, email *parsemail.Email, emailTyp
|
||||
}
|
||||
|
||||
if DropUnknownRecipientEmails &&
|
||||
((cfg.SpamFilterLevel == 1 && !SPFStatus && !dkimStatus) ||
|
||||
(cfg.SpamFilterLevel == 2 && !SPFStatus) ||
|
||||
(cfg.SpamFilterLevel == 3 && !dkimStatus)) {
|
||||
((policy.SpamFilterLevel == 1 && !SPFStatus && !dkimStatus) ||
|
||||
(policy.SpamFilterLevel == 2 && !SPFStatus) ||
|
||||
(policy.SpamFilterLevel == 3 && !dkimStatus)) {
|
||||
log.WithContext(ctx).Infoln("垃圾邮件,拒信")
|
||||
log.WithContext(ctx).Infof("收件人不存在且DKIM验证失败,丢弃邮件: recipient_count=%d", len(accounts))
|
||||
return nil, true, nil
|
||||
@ -183,10 +185,7 @@ func resolveIncomingUsers(ctx *context.Context, email *parsemail.Email, emailTyp
|
||||
}
|
||||
|
||||
func incomingAccounts(email *parsemail.Email, reallyTo []string) []string {
|
||||
cfg := config.CurrentConfig()
|
||||
if cfg == nil {
|
||||
return nil
|
||||
}
|
||||
domains := config.CurrentMailDomains()
|
||||
var accounts []string
|
||||
if len(reallyTo) > 0 {
|
||||
for _, recipient := range reallyTo {
|
||||
@ -195,7 +194,7 @@ func incomingAccounts(email *parsemail.Email, reallyTo []string) []string {
|
||||
continue
|
||||
}
|
||||
name, domain := account.GetDomainAccount()
|
||||
if array.InArray(domain, cfg.Domains) && name != "" {
|
||||
if array.InArray(domain, domains.Accepted) && name != "" {
|
||||
accounts = append(accounts, strings.ToLower(name))
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,16 +190,13 @@ func forwardToLocalUser(ctx *context.Context, email *parsemail.Email, account, f
|
||||
}
|
||||
|
||||
func isLocalDomain(domain string) bool {
|
||||
cfg := config.CurrentConfig()
|
||||
if cfg == nil {
|
||||
return false
|
||||
}
|
||||
for _, localDomain := range cfg.Domains {
|
||||
domains := config.CurrentMailDomains()
|
||||
for _, localDomain := range domains.Accepted {
|
||||
if strings.EqualFold(domain, localDomain) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return strings.EqualFold(domain, cfg.Domain)
|
||||
return strings.EqualFold(domain, domains.Primary)
|
||||
}
|
||||
|
||||
func doMove(ctx *context.Context, rule *dto.Rule, email *parsemail.Email) error {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user