all repos — mdawh @ 6aebc28a1238708ffda9d2c6a01e9e20e217c394

An MDA that creates a webhook on recieval of mail

Init mdawh

The MDA webhook tool
Anirudh Oppiliappan x@icyphox.sh
Wed, 31 Mar 2021 20:19:48 +0530
commit

6aebc28a1238708ffda9d2c6a01e9e20e217c394

4 files changed, 142 insertions(+), 0 deletions(-)

jump to
A .gitignore

@@ -0,0 +1,2 @@

+mdawh +*mail
A go.mod

@@ -0,0 +1,8 @@

+module git.icyphox.sh/forlater/mdawh + +go 1.16 + +require ( + github.com/emersion/go-message v0.14.1 + github.com/microcosm-cc/bluemonday v1.0.5 +)
A go.sum

@@ -0,0 +1,26 @@

+github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU= +github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emersion/go-message v0.14.1 h1:j3rj9F+7VtXE9c8P5UHBq8FTHLW/AjnmvSRre6AHoYI= +github.com/emersion/go-message v0.14.1/go.mod h1:N1JWdZQ2WRUalmdHAX308CWBq747VJ8oUorFI3VCBwU= +github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 h1:IbFBtwoTQyw0fIM5xv1HF+Y+3ZijDR839WMulgxCcUY= +github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/martinlindhe/base36 v1.1.0 h1:cIwvvwYse/0+1CkUPYH5ZvVIYG3JrILmQEIbLuar02Y= +github.com/martinlindhe/base36 v1.1.0/go.mod h1:+AtEs8xrBpCeYgSLoY/aJ6Wf37jtBuR0s35750M27+8= +github.com/microcosm-cc/bluemonday v1.0.5 h1:cF59UCKMmmUgqN1baLvqU/B1ZsMori+duLVTLpgiG3w= +github.com/microcosm-cc/bluemonday v1.0.5/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/text v0.3.5-0.20201125200606-c27b9fd57aec/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
A main.go

@@ -0,0 +1,106 @@

+package main + +import ( + "bufio" + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "os" + "strings" + + "github.com/emersion/go-message/mail" + "github.com/microcosm-cc/bluemonday" +) + +type Mail struct { + From string + Date string + Body string + ContentType string +} + +func makeReq(j []byte) { + req, err := http.NewRequest("POST", "http://localhost:8001/webhook", bytes.NewBuffer(j)) + req.Header.Set("Content-Type", "application/json") + client := http.Client{} + res, err := client.Do(req) + if err != nil { + log.Fatal(err) + } + defer res.Body.Close() +} + +func cleanHTML(body string) string { + bm := bluemonday.StrictPolicy() + bm.AddSpaceWhenStrippingTag(true) + clean := bm.Sanitize(body) + return clean +} + +func jsonMail(p *mail.Part, mr *mail.Reader) ([]byte, error) { + b, _ := ioutil.ReadAll(p.Body) + body := string(b) + ct := p.Header.Get("Content-Type") + from := mr.Header.Get("From") + date := mr.Header.Get("Date") + + // Prefer plaintext part over html + if strings.Contains(ct, "text/plain") { + m := Mail{from, date, body, "text/plain"} + j, err := json.Marshal(m) + if err != nil { + log.Fatal(err) + } + return j, nil + + // If there's no plaintext, fallback on html + // Clean up HTML junk using bluemonday + } else if strings.Contains(ct, "text/html") { + cleanBody := cleanHTML(body) + m := Mail{from, date, cleanBody, "text/html"} + j, err := json.Marshal(m) + if err != nil { + log.Fatal(err) + } + return j, nil + } else { + return nil, errors.New("no plaintext or html parts") + } +} + +func main() { + r := bufio.NewReader(os.Stdin) + mr, err := mail.CreateReader(r) + + if err != nil { + log.Fatal(err) + } + + for { + p, err := mr.NextPart() + if err == io.EOF { + break + } else if err != nil { + log.Fatal(err) + + } + switch h := p.Header.(type) { + case *mail.InlineHeader: + jm, err := jsonMail(p, mr) + fmt.Println(string(jm)) + if err != nil { + log.Fatal(err) + } + makeReq(jm) + + case *mail.AttachmentHeader: + filename, _ := h.Filename() + log.Printf("Got attachment: %v\n", filename) + } + } +}