sophuwu.site > mailboxxer
changed storage of files
sophuwu sophie@skisiel.com
Wed, 24 Jul 2024 07:59:09 +0200
commit

1fca6f1a7fcab63e3dfde8be18af4756f42e26cc

parent

cb78ab19b97973575fca793e32b13fbf3d698361

4 files changed, 93 insertions(+), 62 deletions(-)

jump to
M cli.gocli.go

@@ -2,9 +2,7 @@ package main

import ( "bytes" - "encoding/base64" "fmt" - "github.com/DusanKasan/parsemail" "github.com/andybalholm/brotli" "golang.org/x/crypto/ssh/terminal" "golang.org/x/net/html"

@@ -13,6 +11,7 @@ "net/mail"

"os" "os/exec" "path/filepath" + "slices" "strings" "time" )

@@ -73,32 +72,6 @@ _, err := buf.ReadFrom(reader)

return err } -func Show(b *bytes.Buffer) error { - e, err := parsemail.Parse(b) - if err != nil { - return err - } - var s string - var ishtml bool - if e.HTMLBody != "" { - s = e.HTMLBody - ishtml = true - } else { - s = e.TextBody - ishtml = false - } - var bb []byte - if bb, err = base64.StdEncoding.DecodeString(s); err == nil { - s = string(bb) - } - if ishtml { - s = RenderHTML(s) - } - b.Reset() - b.WriteString(s) - return nil -} - func node(w io.Writer, n *html.Node) { switch n.Type { case html.ElementNode:

@@ -158,7 +131,34 @@ fmt.Printf("%d:\t%s\n", i-page, metas[i].Display())

} } -func OpenMail(metas []EmailMeta, page int, h int, s string) error { +func wrap(w int, s string) string { + var line = "" + var lines, b []string + for _, n := range strings.Split(s, "\n") { + b = strings.Split(n, " ") + for i, v := range b { + if len(v) > w { + lines = append(lines, v[:w-1], v[w-1:]) + continue + } + if len(line)+len(v) < w { + line += v + " " + } else { + lines = append(lines, strings.TrimSuffix(line, " ")) + line = "" + continue + } + if i == len(b)-1 { + lines = append(lines, strings.TrimSuffix(line, " ")) + line = "" + } + } + } + lines = slices.Clip(lines) + return " " + strings.Join(lines, " \n ") +} + +func OpenMail(metas []EmailMeta, page int, h int, s string, w int) error { n := 0 for _, r := range s { if r < '0' || r > '9' {

@@ -174,20 +174,24 @@ if n >= len(metas) || n < 0 {

return fmt.Errorf("invalid number") } id := metas[n].Id - b, err := os.ReadFile(filepath.Join(SAVEPATH, id+".br")) + var b []byte + path, err := filepath.Glob(filepath.Join(SAVEPATH, id, "body.*")) + if len(path) == 0 { + return fmt.Errorf("no email found") + } + b, err = os.ReadFile(path[0]) if err != nil { return err } - var email bytes.Buffer - email.Write(b) - if err = UnBr(&email); err != nil { - return err + s = string(b) + if filepath.Ext(path[0]) == ".html" { + s = RenderHTML(s) } - if err = Show(&email); err != nil { - return err - } - cmd := exec.Command("less") - cmd.Stdin = &email + w -= 4 + s = wrap(w, s) + + cmd := exec.Command("less", "-sR") + cmd.Stdin = strings.NewReader(s) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return cmd.Run()

@@ -199,7 +203,7 @@ fmt.Print("\033[?1049h")

defer fmt.Print("\033[?1049l") page := 0 var s string - _, h := GetTSize() + w, h := GetTSize() h -= 5 if h > 20 { h = 20

@@ -226,7 +230,7 @@ return

case "": continue default: // open mail - if err := OpenMail(*metas, page, h, s); err != nil { + if err := OpenMail(*metas, page, h, s, w); err != nil { fmt.Println(err) } }
M files.gofiles.go

@@ -1,6 +1,7 @@

package main import ( + "bytes" "encoding/base64" "fmt" "io"

@@ -11,7 +12,9 @@ "net/textproto"

"strings" ) -func getfiles(files *map[string][]byte, parts interface{}) { +type FileList map[string][]byte + +func getfiles(files *FileList, parts interface{}) { var body io.Reader var head textproto.MIMEHeader switch part := parts.(type) {

@@ -44,23 +47,31 @@ }

if len(content) == 0 { return } - name := params["name"] - if strings.HasPrefix(mediaType, "text/") || strings.HasPrefix(mediaType, "message/") { - name = "body.txt" - if strings.Contains(mediaType, "html") { - name = "index.html" - } + name := "body.txt" + if params["name"] != "" { + name = params["name"] + } + if strings.Contains(mediaType, "html") { + name = "index.html" } (*files)[name] = append((*files)[name], content...) } -func EmlFiles(eml *mail.Message) map[string][]byte { +func EmlFiles(eml *mail.Message) FileList { s := "" for k := range eml.Header { s += fmt.Sprintf("%s: %s\n", k, eml.Header.Get(k)) } - files := make(map[string][]byte) + files := make(FileList) files["header.txt"] = []byte(s) getfiles(&files, eml) return files } + +func GetFiles(b *bytes.Buffer) (FileList, error) { + e, err := mail.ReadMessage(b) + if err != nil { + return nil, err + } + return EmlFiles(e), nil +}
M main.gomain.go

@@ -94,5 +94,10 @@ if err != nil {

fmt.Fprintln(os.Stderr, err) return } - CLI(&metas) + for _, v := range os.Args[1:] { + if v == "--cli" { + CLI(&metas) + return + } + } }
M parse.goparse.go

@@ -18,7 +18,7 @@

func Brotli(buf *bytes.Buffer) error { data := buf.Bytes() buf.Reset() - writer := brotli.NewWriter(buf) + writer := brotli.NewWriterLevel(buf, brotli.BestCompression) _, err := writer.Write(data) if err != nil { return err

@@ -26,9 +26,16 @@ }

return writer.Close() } -func SaveEmail(em EmailMeta, email bytes.Buffer) error { - path := filepath.Join(SAVEPATH, em.Id+".br") - err := os.WriteFile(path, email.Bytes(), 0600) +func SaveEmail(em EmailMeta, files FileList) error { + path := filepath.Join(SAVEPATH, em.Id) + var err error + _ = os.MkdirAll(path, 0700) + for name, data := range files { + err = os.WriteFile(filepath.Join(path, name), data, 0600) + if err != nil { + return err + } + } return err }

@@ -36,7 +43,7 @@ func NewEntry(f os.DirEntry) (EmailMeta, error) {

if !f.Type().IsRegular() { return EmailMeta{}, fmt.Errorf("unsupported file type in directory") } - meta, email, err := Parse(filepath.Join(INBOX, f.Name())) + meta, files, err := Parse(filepath.Join(INBOX, f.Name())) if err != nil { return meta, err }

@@ -44,7 +51,7 @@ if meta.Date == "" {

s, _ := f.Info() meta.Date = s.ModTime().Format(TimeFormat) } - err = SaveEmail(meta, email) + err = SaveEmail(meta, files) if err != nil { return meta, err }

@@ -68,20 +75,24 @@ }

return nil } -func Parse(path string) (EmailMeta, bytes.Buffer, error) { +func Parse(path string) (EmailMeta, FileList, error) { var email bytes.Buffer var meta EmailMeta + var files FileList b, err := os.ReadFile(path) if err != nil { - return meta, email, err + return meta, files, err } email.Write(b) meta, err = GenerateMeta(email) if err != nil { - return meta, email, err + return meta, files, err } - err = Brotli(&email) - return meta, email, err + files, err = GetFiles(&email) + if err != nil { + return meta, files, err + } + return meta, files, err } func dateHeader(e *mail.Header) string {