bug fix
修复并非写map造成的panic
This commit is contained in:
parent
cc4aa851bc
commit
d7fe9ba1a1
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@ -34,6 +34,7 @@ jobs:
|
|||||||
- name: Setup Go environment
|
- name: Setup Go environment
|
||||||
uses: actions/setup-go@v4.1.0
|
uses: actions/setup-go@v4.1.0
|
||||||
with:
|
with:
|
||||||
|
go-version: '1.22'
|
||||||
check-latest: true
|
check-latest: true
|
||||||
- name: Gen output name
|
- name: Gen output name
|
||||||
run: |
|
run: |
|
||||||
@ -79,4 +80,4 @@ jobs:
|
|||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
file: server/${{ env.ZIPNAME }}.zip
|
file: server/${{ env.ZIPNAME }}.zip
|
||||||
tag: ${{ github.ref }}
|
tag: ${{ github.ref }}
|
||||||
file_glob: true
|
file_glob: true
|
||||||
|
|||||||
@ -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")
|
||||||
|
|
||||||
// 邮件落库
|
// 邮件落库
|
||||||
|
|||||||
@ -21,6 +21,7 @@ func AcmeChallenge(w http.ResponseWriter, r *http.Request) {
|
|||||||
if exist {
|
if exist {
|
||||||
w.Write([]byte(auth.KeyAuth))
|
w.Write([]byte(auth.KeyAuth))
|
||||||
} else {
|
} else {
|
||||||
|
log.Errorf("AcmeChallenge Error Token Infos:%+v", instance.AuthInfo)
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
30
server/models/base.go
Normal file
30
server/models/base.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "pmail/db"
|
||||||
|
|
||||||
|
func SyncTables() {
|
||||||
|
err := db.Instance.Sync2(&User{})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = db.Instance.Sync2(&Email{})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = db.Instance.Sync2(&Group{})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = db.Instance.Sync2(&Rule{})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = db.Instance.Sync2(&UserAuth{})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = db.Instance.Sync2(&Sessions{})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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"`
|
||||||
|
|||||||
11
server/models/session.go
Normal file
11
server/models/session.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
type Sessions struct {
|
||||||
|
Token string `xorm:"token char(43) not null pk " json:"token"`
|
||||||
|
Data string `xorm:"data blob" json:"data"`
|
||||||
|
Expiry int `xorm:"expiry timestamp index" json:"expiry"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Sessions) TableName() string {
|
||||||
|
return "sessions"
|
||||||
|
}
|
||||||
@ -38,7 +38,7 @@ func Init(serverVersion string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
syncTables()
|
models.SyncTables()
|
||||||
session.Init()
|
session.Init()
|
||||||
hooks.Init(serverVersion)
|
hooks.Init(serverVersion)
|
||||||
// smtp server start
|
// smtp server start
|
||||||
@ -86,26 +86,3 @@ func dirInit() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncTables() {
|
|
||||||
err := db.Instance.Sync2(&models.User{})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
err = db.Instance.Sync2(&models.Email{})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
err = db.Instance.Sync2(&models.Group{})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
err = db.Instance.Sync2(&models.Rule{})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
err = db.Instance.Sync2(&models.UserAuth{})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -85,6 +85,7 @@ func SetDatabaseSettings(ctx *context.Context, dbType, dbDSN string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err)
|
return errors.Wrap(err)
|
||||||
}
|
}
|
||||||
|
models.SyncTables()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user