修复并非写map造成的panic

Co-authored-by: jinnrry <i@jinnrry.com>
This commit is contained in:
Jinnrry 2024-04-20 09:13:53 +08:00 committed by GitHub
parent 6ecb61ac45
commit 6280264435
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 23 additions and 47 deletions

View File

@ -130,16 +130,12 @@ func Send(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
} }
log.WithContext(ctx).Debugf("插件执行--SendBefore") log.WithContext(ctx).Debugf("插件执行--SendBefore")
as := async.New(ctx)
for _, hook := range hooks.HookList { for _, hook := range hooks.HookList {
if hook == nil { if hook == nil {
continue continue
} }
as.WaitProcess(func(hk any) { hook.SendBefore(ctx, e)
hk.(framework.EmailHook).SendBefore(ctx, e)
}, hook)
} }
as.Wait()
log.WithContext(ctx).Debugf("插件执行--SendBefore End") log.WithContext(ctx).Debugf("插件执行--SendBefore End")
// 邮件落库 // 邮件落库

View File

@ -35,17 +35,12 @@ func (h *HookSender) ReceiveSaveAfter(ctx *context.Context, email *parsemail.Ema
} }
body, _ := json.Marshal(dto) body, _ := json.Marshal(dto)
ret, err := h.httpc.Post("http://plugin/ReceiveSaveAfter", "application/json", strings.NewReader(string(body))) _, err := h.httpc.Post("http://plugin/ReceiveSaveAfter", "application/json", strings.NewReader(string(body)))
if err != nil { if err != nil {
log.WithContext(ctx).Errorf("[%s] Error! %v", h.name, err) log.WithContext(ctx).Errorf("[%s] Error! %v", h.name, err)
return return
} }
body, _ = io.ReadAll(ret.Body)
json.Unmarshal(body, &dto)
ctx = dto.Ctx
email = dto.Email
log.WithContext(ctx).Debugf("[%s]Plugin ReceiveSaveAfter End", h.name) log.WithContext(ctx).Debugf("[%s]Plugin ReceiveSaveAfter End", h.name)
} }
@ -82,18 +77,12 @@ func (h *HookSender) SendAfter(ctx *context.Context, email *parsemail.Email, err
} }
body, _ := json.Marshal(dto) body, _ := json.Marshal(dto)
ret, errL := h.httpc.Post("http://plugin/SendAfter", "application/json", strings.NewReader(string(body))) _, errL := h.httpc.Post("http://plugin/SendAfter", "application/json", strings.NewReader(string(body)))
if errL != nil { if errL != nil {
log.WithContext(ctx).Errorf("[%s] Error! %v", h.name, errL) log.WithContext(ctx).Errorf("[%s] Error! %v", h.name, errL)
return return
} }
body, _ = io.ReadAll(ret.Body)
json.Unmarshal(body, &dto)
ctx = dto.Ctx
email = dto.Email
err = dto.ErrMap
log.WithContext(ctx).Debugf("[%s]Plugin SendAfter End", h.name) log.WithContext(ctx).Debugf("[%s]Plugin SendAfter End", h.name)
} }

View File

@ -16,15 +16,15 @@ import (
) )
type EmailHook interface { type EmailHook interface {
// SendBefore 邮件发送前的数据 // SendBefore 邮件发送前的数据 同步执行
SendBefore(ctx *context.Context, email *parsemail.Email) SendBefore(ctx *context.Context, email *parsemail.Email)
// SendAfter 邮件发送后的数据,err是每个收信服务器的错误信息 // SendAfter 邮件发送后的数据,err是每个收信服务器的错误信息 异步执行
SendAfter(ctx *context.Context, email *parsemail.Email, err map[string]error) SendAfter(ctx *context.Context, email *parsemail.Email, err map[string]error)
// ReceiveParseBefore 接收到邮件,解析之前的原始数据 // ReceiveParseBefore 接收到邮件,解析之前的原始数据 同步执行
ReceiveParseBefore(ctx *context.Context, email *[]byte) ReceiveParseBefore(ctx *context.Context, email *[]byte)
// ReceiveParseAfter 接收到邮件,解析之后的结构化数据 (收信规则前,写数据库前执行) // ReceiveParseAfter 接收到邮件,解析之后的结构化数据 (收信规则前,写数据库前执行) 同步执行
ReceiveParseAfter(ctx *context.Context, email *parsemail.Email) ReceiveParseAfter(ctx *context.Context, email *parsemail.Email)
// ReceiveSaveAfter 邮件落库以后执行(收信规则后执行) // ReceiveSaveAfter 邮件落库以后执行(收信规则后执行) 异步执行
ReceiveSaveAfter(ctx *context.Context, email *parsemail.Email) ReceiveSaveAfter(ctx *context.Context, email *parsemail.Email)
} }

View File

@ -8,7 +8,7 @@ import (
) )
type Email struct { type Email struct {
Id int `xorm:"id pk unsigned int autoincr notnull" json:"id"` Id int `xorm:"id pk unsigned int autoincr notnull default(0)" json:"id"`
Type int8 `xorm:"type tinyint(4) notnull default(0) comment('邮件类型,0:收到的邮件,1:发送的邮件')" json:"type"` Type int8 `xorm:"type tinyint(4) notnull default(0) comment('邮件类型,0:收到的邮件,1:发送的邮件')" json:"type"`
GroupId int `xorm:"group_id int notnull default(0) comment('分组id')'" json:"group_id"` GroupId int `xorm:"group_id int notnull default(0) comment('分组id')'" json:"group_id"`
Subject string `xorm:"subject varchar(1000) notnull default('') comment('邮件标题')" json:"subject"` Subject string `xorm:"subject varchar(1000) notnull default('') comment('邮件标题')" json:"subject"`

View File

@ -36,16 +36,12 @@ func (s *Session) Data(r io.Reader) error {
return err return err
} }
log.WithContext(ctx).Debugf("开始执行插件ReceiveParseBefore!") log.WithContext(ctx).Debugf("开始执行插件ReceiveParseBefore!")
as1 := async.New(ctx)
for _, hook := range hooks.HookList { for _, hook := range hooks.HookList {
if hook == nil { if hook == nil {
continue continue
} }
as1.WaitProcess(func(hk any) { hook.ReceiveParseBefore(ctx, &emailData)
hk.(framework.EmailHook).ReceiveParseBefore(ctx, &emailData)
}, hook)
} }
as1.Wait()
log.WithContext(ctx).Debugf("开始执行插件ReceiveParseBefore End!") log.WithContext(ctx).Debugf("开始执行插件ReceiveParseBefore End!")
log.WithContext(ctx).Infof("邮件原始内容: %s", emailData) log.WithContext(ctx).Infof("邮件原始内容: %s", emailData)
@ -67,18 +63,13 @@ func (s *Session) Data(r io.Reader) error {
// 判断是收信还是转发,只要是登陆了,都当成转发处理 // 判断是收信还是转发,只要是登陆了,都当成转发处理
//account, domain := email.From.GetDomainAccount() //account, domain := email.From.GetDomainAccount()
if s.Ctx.UserID > 0 { if s.Ctx.UserID > 0 {
log.WithContext(ctx).Debugf("开始执行插件SendBefore!") log.WithContext(ctx).Debugf("开始执行插件SendBefore!")
as2 := async.New(ctx)
for _, hook := range hooks.HookList { for _, hook := range hooks.HookList {
if hook == nil { if hook == nil {
continue continue
} }
as2.WaitProcess(func(hk any) { hook.SendBefore(ctx, email)
hk.(framework.EmailHook).SendBefore(ctx, email)
}, hook)
} }
as2.Wait()
log.WithContext(ctx).Debugf("开始执行插件SendBefore!End") log.WithContext(ctx).Debugf("开始执行插件SendBefore!End")
if email == nil { if email == nil {
@ -136,16 +127,12 @@ func (s *Session) Data(r io.Reader) error {
SPFStatus = spfCheck(s.RemoteAddress.String(), email.Sender, email.Sender.EmailAddress) SPFStatus = spfCheck(s.RemoteAddress.String(), email.Sender, email.Sender.EmailAddress)
log.WithContext(ctx).Debugf("开始执行插件ReceiveParseAfter!") log.WithContext(ctx).Debugf("开始执行插件ReceiveParseAfter!")
as2 := async.New(ctx)
for _, hook := range hooks.HookList { for _, hook := range hooks.HookList {
if hook == nil { if hook == nil {
continue continue
} }
as2.WaitProcess(func(hk any) { hook.ReceiveParseAfter(ctx, email)
hk.(framework.EmailHook).ReceiveParseAfter(ctx, email)
}, hook)
} }
as2.Wait()
log.WithContext(ctx).Debugf("开始执行插件ReceiveParseAfter!End") log.WithContext(ctx).Debugf("开始执行插件ReceiveParseAfter!End")
if email == nil { if email == nil {

View File

@ -12,6 +12,7 @@ import (
"pmail/utils/context" "pmail/utils/context"
"pmail/utils/smtp" "pmail/utils/smtp"
"strings" "strings"
"sync"
) )
type mxDomain struct { type mxDomain struct {
@ -59,8 +60,6 @@ func Forward(ctx *context.Context, e *parsemail.Email, forwardAddress string) er
var errEmailAddress []string var errEmailAddress []string
errMap := map[string]error{}
as := async.New(ctx) as := async.New(ctx)
for domain, tos := range toByDomain { for domain, tos := range toByDomain {
domain := domain domain := domain
@ -96,7 +95,6 @@ func Forward(ctx *context.Context, e *parsemail.Email, forwardAddress string) er
errEmailAddress = append(errEmailAddress, user.EmailAddress) errEmailAddress = append(errEmailAddress, user.EmailAddress)
} }
} }
errMap[domain.domain] = err
}, nil) }, nil)
} }
as.Wait() as.Wait()
@ -145,7 +143,7 @@ func Send(ctx *context.Context, e *parsemail.Email) (error, map[string]error) {
var errEmailAddress []string var errEmailAddress []string
errMap := map[string]error{} errMap := sync.Map{}
as := async.New(ctx) as := async.New(ctx)
for domain, tos := range toByDomain { for domain, tos := range toByDomain {
@ -183,15 +181,21 @@ func Send(ctx *context.Context, e *parsemail.Email) (error, map[string]error) {
errEmailAddress = append(errEmailAddress, user.EmailAddress) errEmailAddress = append(errEmailAddress, user.EmailAddress)
} }
} }
errMap[domain.domain] = err errMap.Store(domain.domain, err)
}, nil) }, nil)
} }
as.Wait() as.Wait()
orgMap := map[string]error{}
errMap.Range(func(key, value any) bool {
orgMap[key.(string)] = value.(error)
return true
})
if len(errEmailAddress) > 0 { if len(errEmailAddress) > 0 {
return errors.New("以下收件人投递失败:" + array.Join(errEmailAddress, ",")), errMap return errors.New("以下收件人投递失败:" + array.Join(errEmailAddress, ",")), orgMap
} }
return nil, errMap return nil, orgMap
} }