From a1df02b41cdd2b1f4e15af038420f849995dcb7c Mon Sep 17 00:00:00 2001 From: Joe Paul Date: Mon, 27 Jun 2022 15:47:38 +0530 Subject: [PATCH] feat(postback): Add attachment, from email to postback body --- go.mod | 2 +- go.sum | 2 - internal/messenger/postback/postback.go | 58 +++-- .../messenger/postback/postback_easyjson.go | 246 +++++++++++++++--- 4 files changed, 249 insertions(+), 59 deletions(-) diff --git a/go.mod b/go.mod index 349278063..e91a8eeb4 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/mattn/go-colorable v0.1.12 // indirect github.com/mitchellh/mapstructure v1.4.2 // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect - github.com/paulbellamy/ratecounter v0.2.0 // indirect + github.com/paulbellamy/ratecounter v0.2.0 github.com/pelletier/go-toml v1.9.4 // indirect github.com/rhnvrm/simples3 v0.8.2 github.com/spf13/cast v1.4.1 // indirect diff --git a/go.sum b/go.sum index 01066d03a..494ae9a0d 100644 --- a/go.sum +++ b/go.sum @@ -144,8 +144,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= -github.com/rhnvrm/simples3 v0.8.1 h1:jL2yCi9P0pA8hFYkyVWZ4cs5RX3AMgcVsXTOqnCj0/w= -github.com/rhnvrm/simples3 v0.8.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= github.com/rhnvrm/simples3 v0.8.2 h1:O9dj0DLaU8clz4ctuI82k9VH/X+TbtdfKLlivMmF6Xw= github.com/rhnvrm/simples3 v0.8.2/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= diff --git a/internal/messenger/postback/postback.go b/internal/messenger/postback/postback.go index faaa78fda..71019a5a9 100644 --- a/internal/messenger/postback/postback.go +++ b/internal/messenger/postback/postback.go @@ -7,6 +7,7 @@ import ( "io" "io/ioutil" "net/http" + "net/textproto" "time" "github.com/knadh/listmonk/internal/messenger" @@ -16,26 +17,34 @@ import ( // postback is the payload that's posted as JSON to the HTTP Postback server. //easyjson:json type postback struct { - Subject string `json:"subject"` - ContentType string `json:"content_type"` - Body string `json:"body"` - Recipients []recipient `json:"recipients"` - Campaign *campaign `json:"campaign"` + Subject string `json:"subject"` + ContentType string `json:"content_type"` + Body string `json:"body"` + Recipients []recipient `json:"recipients"` + Campaign *campaign `json:"campaign"` + Attachments []attachment `json:"attachments"` } type campaign struct { - UUID string `db:"uuid" json:"uuid"` - Name string `db:"name" json:"name"` - Headers models.Headers `db:"headers" json:"headers"` - Tags []string `db:"tags" json:"tags"` + FromEmail string `json:"from_email"` + UUID string `json:"uuid"` + Name string `json:"name"` + Headers models.Headers `json:"headers"` + Tags []string `json:"tags"` } type recipient struct { - UUID string `db:"uuid" json:"uuid"` - Email string `db:"email" json:"email"` - Name string `db:"name" json:"name"` - Attribs models.SubscriberAttribs `db:"attribs" json:"attribs"` - Status string `db:"status" json:"status"` + UUID string `json:"uuid"` + Email string `json:"email"` + Name string `json:"name"` + Attribs models.SubscriberAttribs `json:"attribs"` + Status string `json:"status"` +} + +type attachment struct { + Name string `json:"name"` + Header textproto.MIMEHeader `json:"header"` + Content []byte `json:"content"` } // Options represents HTTP Postback server options. @@ -101,10 +110,23 @@ func (p *Postback) Push(m messenger.Message) error { if m.Campaign != nil { pb.Campaign = &campaign{ - UUID: m.Campaign.UUID, - Name: m.Campaign.Name, - Headers: m.Campaign.Headers, - Tags: m.Campaign.Tags, + FromEmail: m.Campaign.FromEmail, + UUID: m.Campaign.UUID, + Name: m.Campaign.Name, + Headers: m.Campaign.Headers, + Tags: m.Campaign.Tags, + } + } + + if len(m.Attachments) > 0 { + a := make([]attachment, 0, len(m.Attachments)) + for i := 0; i < len(m.Attachments); i++ { + a[i] = attachment{ + Name: m.Attachments[i].Name, + Header: m.Attachments[i].Header, + Content: make([]byte, len(m.Attachments[i].Content)), + } + copy(a[i].Content, m.Attachments[i].Content) } } diff --git a/internal/messenger/postback/postback_easyjson.go b/internal/messenger/postback/postback_easyjson.go index f2a1e516f..78ac8d0d6 100644 --- a/internal/messenger/postback/postback_easyjson.go +++ b/internal/messenger/postback/postback_easyjson.go @@ -8,6 +8,7 @@ import ( easyjson "github.com/mailru/easyjson" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" + textproto "net/textproto" ) // suppress unused package warning @@ -76,6 +77,29 @@ func easyjsonDf11841fDecodeGithubComKnadhListmonkInternalMessengerPostback(in *j } easyjsonDf11841fDecodeGithubComKnadhListmonkInternalMessengerPostback2(in, out.Campaign) } + case "attachments": + if in.IsNull() { + in.Skip() + out.Attachments = nil + } else { + in.Delim('[') + if out.Attachments == nil { + if !in.IsDelim(']') { + out.Attachments = make([]attachment, 0, 1) + } else { + out.Attachments = []attachment{} + } + } else { + out.Attachments = (out.Attachments)[:0] + } + for !in.IsDelim(']') { + var v2 attachment + easyjsonDf11841fDecodeGithubComKnadhListmonkInternalMessengerPostback3(in, &v2) + out.Attachments = append(out.Attachments, v2) + in.WantComma() + } + in.Delim(']') + } default: in.SkipRecursive() } @@ -112,11 +136,11 @@ func easyjsonDf11841fEncodeGithubComKnadhListmonkInternalMessengerPostback(out * out.RawString("null") } else { out.RawByte('[') - for v2, v3 := range in.Recipients { - if v2 > 0 { + for v3, v4 := range in.Recipients { + if v3 > 0 { out.RawByte(',') } - easyjsonDf11841fEncodeGithubComKnadhListmonkInternalMessengerPostback1(out, v3) + easyjsonDf11841fEncodeGithubComKnadhListmonkInternalMessengerPostback1(out, v4) } out.RawByte(']') } @@ -130,6 +154,22 @@ func easyjsonDf11841fEncodeGithubComKnadhListmonkInternalMessengerPostback(out * easyjsonDf11841fEncodeGithubComKnadhListmonkInternalMessengerPostback2(out, *in.Campaign) } } + { + const prefix string = ",\"attachments\":" + out.RawString(prefix) + if in.Attachments == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { + out.RawString("null") + } else { + out.RawByte('[') + for v5, v6 := range in.Attachments { + if v5 > 0 { + out.RawByte(',') + } + easyjsonDf11841fEncodeGithubComKnadhListmonkInternalMessengerPostback3(out, v6) + } + out.RawByte(']') + } + } out.RawByte('}') } @@ -156,6 +196,129 @@ func (v *postback) UnmarshalJSON(data []byte) error { func (v *postback) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjsonDf11841fDecodeGithubComKnadhListmonkInternalMessengerPostback(l, v) } +func easyjsonDf11841fDecodeGithubComKnadhListmonkInternalMessengerPostback3(in *jlexer.Lexer, out *attachment) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "name": + out.Name = string(in.String()) + case "header": + if in.IsNull() { + in.Skip() + } else { + in.Delim('{') + out.Header = make(textproto.MIMEHeader) + for !in.IsDelim('}') { + key := string(in.String()) + in.WantColon() + var v7 []string + if in.IsNull() { + in.Skip() + v7 = nil + } else { + in.Delim('[') + if v7 == nil { + if !in.IsDelim(']') { + v7 = make([]string, 0, 4) + } else { + v7 = []string{} + } + } else { + v7 = (v7)[:0] + } + for !in.IsDelim(']') { + var v8 string + v8 = string(in.String()) + v7 = append(v7, v8) + in.WantComma() + } + in.Delim(']') + } + (out.Header)[key] = v7 + in.WantComma() + } + in.Delim('}') + } + case "content": + if in.IsNull() { + in.Skip() + out.Content = nil + } else { + out.Content = in.Bytes() + } + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDf11841fEncodeGithubComKnadhListmonkInternalMessengerPostback3(out *jwriter.Writer, in attachment) { + out.RawByte('{') + first := true + _ = first + { + const prefix string = ",\"name\":" + out.RawString(prefix[1:]) + out.String(string(in.Name)) + } + { + const prefix string = ",\"header\":" + out.RawString(prefix) + if in.Header == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 { + out.RawString(`null`) + } else { + out.RawByte('{') + v10First := true + for v10Name, v10Value := range in.Header { + if v10First { + v10First = false + } else { + out.RawByte(',') + } + out.String(string(v10Name)) + out.RawByte(':') + if v10Value == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { + out.RawString("null") + } else { + out.RawByte('[') + for v11, v12 := range v10Value { + if v11 > 0 { + out.RawByte(',') + } + out.String(string(v12)) + } + out.RawByte(']') + } + } + out.RawByte('}') + } + } + { + const prefix string = ",\"content\":" + out.RawString(prefix) + out.Base64Bytes(in.Content) + } + out.RawByte('}') +} func easyjsonDf11841fDecodeGithubComKnadhListmonkInternalMessengerPostback2(in *jlexer.Lexer, out *campaign) { isTopLevel := in.IsStart() if in.IsNull() { @@ -175,6 +338,8 @@ func easyjsonDf11841fDecodeGithubComKnadhListmonkInternalMessengerPostback2(in * continue } switch key { + case "from_email": + out.FromEmail = string(in.String()) case "uuid": out.UUID = string(in.String()) case "name": @@ -195,23 +360,23 @@ func easyjsonDf11841fDecodeGithubComKnadhListmonkInternalMessengerPostback2(in * out.Headers = (out.Headers)[:0] } for !in.IsDelim(']') { - var v4 map[string]string + var v15 map[string]string if in.IsNull() { in.Skip() } else { in.Delim('{') - v4 = make(map[string]string) + v15 = make(map[string]string) for !in.IsDelim('}') { key := string(in.String()) in.WantColon() - var v5 string - v5 = string(in.String()) - (v4)[key] = v5 + var v16 string + v16 = string(in.String()) + (v15)[key] = v16 in.WantComma() } in.Delim('}') } - out.Headers = append(out.Headers, v4) + out.Headers = append(out.Headers, v15) in.WantComma() } in.Delim(']') @@ -232,9 +397,9 @@ func easyjsonDf11841fDecodeGithubComKnadhListmonkInternalMessengerPostback2(in * out.Tags = (out.Tags)[:0] } for !in.IsDelim(']') { - var v6 string - v6 = string(in.String()) - out.Tags = append(out.Tags, v6) + var v17 string + v17 = string(in.String()) + out.Tags = append(out.Tags, v17) in.WantComma() } in.Delim(']') @@ -254,8 +419,13 @@ func easyjsonDf11841fEncodeGithubComKnadhListmonkInternalMessengerPostback2(out first := true _ = first { - const prefix string = ",\"uuid\":" + const prefix string = ",\"from_email\":" out.RawString(prefix[1:]) + out.String(string(in.FromEmail)) + } + { + const prefix string = ",\"uuid\":" + out.RawString(prefix) out.String(string(in.UUID)) } { @@ -270,24 +440,24 @@ func easyjsonDf11841fEncodeGithubComKnadhListmonkInternalMessengerPostback2(out out.RawString("null") } else { out.RawByte('[') - for v7, v8 := range in.Headers { - if v7 > 0 { + for v18, v19 := range in.Headers { + if v18 > 0 { out.RawByte(',') } - if v8 == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 { + if v19 == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 { out.RawString(`null`) } else { out.RawByte('{') - v9First := true - for v9Name, v9Value := range v8 { - if v9First { - v9First = false + v20First := true + for v20Name, v20Value := range v19 { + if v20First { + v20First = false } else { out.RawByte(',') } - out.String(string(v9Name)) + out.String(string(v20Name)) out.RawByte(':') - out.String(string(v9Value)) + out.String(string(v20Value)) } out.RawByte('}') } @@ -302,11 +472,11 @@ func easyjsonDf11841fEncodeGithubComKnadhListmonkInternalMessengerPostback2(out out.RawString("null") } else { out.RawByte('[') - for v10, v11 := range in.Tags { - if v10 > 0 { + for v21, v22 := range in.Tags { + if v21 > 0 { out.RawByte(',') } - out.String(string(v11)) + out.String(string(v22)) } out.RawByte(']') } @@ -347,15 +517,15 @@ func easyjsonDf11841fDecodeGithubComKnadhListmonkInternalMessengerPostback1(in * for !in.IsDelim('}') { key := string(in.String()) in.WantColon() - var v12 interface{} - if m, ok := v12.(easyjson.Unmarshaler); ok { + var v23 interface{} + if m, ok := v23.(easyjson.Unmarshaler); ok { m.UnmarshalEasyJSON(in) - } else if m, ok := v12.(json.Unmarshaler); ok { + } else if m, ok := v23.(json.Unmarshaler); ok { _ = m.UnmarshalJSON(in.Raw()) } else { - v12 = in.Interface() + v23 = in.Interface() } - (out.Attribs)[key] = v12 + (out.Attribs)[key] = v23 in.WantComma() } in.Delim('}') @@ -398,21 +568,21 @@ func easyjsonDf11841fEncodeGithubComKnadhListmonkInternalMessengerPostback1(out out.RawString(`null`) } else { out.RawByte('{') - v13First := true - for v13Name, v13Value := range in.Attribs { - if v13First { - v13First = false + v24First := true + for v24Name, v24Value := range in.Attribs { + if v24First { + v24First = false } else { out.RawByte(',') } - out.String(string(v13Name)) + out.String(string(v24Name)) out.RawByte(':') - if m, ok := v13Value.(easyjson.Marshaler); ok { + if m, ok := v24Value.(easyjson.Marshaler); ok { m.MarshalEasyJSON(out) - } else if m, ok := v13Value.(json.Marshaler); ok { + } else if m, ok := v24Value.(json.Marshaler); ok { out.Raw(m.MarshalJSON()) } else { - out.Raw(json.Marshal(v13Value)) + out.Raw(json.Marshal(v24Value)) } } out.RawByte('}')