diff --git a/cmd/recv/main.go b/cmd/recv/main.go index 84eb13b..b8b96ca 100755 --- a/cmd/recv/main.go +++ b/cmd/recv/main.go @@ -5,6 +5,8 @@ import ( "fmt" "io" "io/ioutil" + "mime" + "mime/multipart" "net/mail" "os" "strings" @@ -14,6 +16,32 @@ import ( "gitea.inhome.blapointe.com/local/args" ) +type MultipartReaderReader struct { + buff []byte + r *multipart.Reader +} + +func (mrr *MultipartReaderReader) Read(b []byte) (int, error) { + n := copy(b, mrr.buff) + mrr.buff = mrr.buff[n:] + for n < len(b) { + part, err := mrr.r.NextPart() + if err != nil { + return n, err + } + defer part.Close() + + mrr.buff, err = io.ReadAll(part) + if err != nil { + return n, err + } + m := copy(b, mrr.buff) + mrr.buff = mrr.buff[m:] + n += m + } + return n, nil +} + func main() { emailer := contact.NewEmailer() as := args.NewArgSet() @@ -47,7 +75,17 @@ func main() { } emails := make([]map[string]any, 0, emailer.Limit) for msg := range msgs { - b, _ := ioutil.ReadAll(io.LimitReader(msg.Body, int64(as.GetInt("b")))) + var r io.Reader + if n := int64(as.GetInt("b")); n >= 0 { + r = io.LimitReader(msg.Body, n) + } else if mediaType, params, _ := mime.ParseMediaType(msg.Header.Get("Content-Type")); strings.HasPrefix(mediaType, "multipart/") { + r = &MultipartReaderReader{ + r: multipart.NewReader(msg.Body, params["boundary"]), + } + } else { + r = msg.Body + } + b, _ := ioutil.ReadAll(r) s := strings.ReplaceAll(string(b), "\r\n", "\n") s = strings.ReplaceAll(string(s), "\n", "\n") s = strings.ReplaceAll(string(s), "\r", "\n") diff --git a/cmd/recv/recv b/cmd/recv/recv new file mode 100755 index 0000000..b761ce9 Binary files /dev/null and b/cmd/recv/recv differ