sophuwu.site > mailboxxer
some stuff probably
sophuwu sophie@skisiel.com
Sat, 20 Jul 2024 18:08:51 +0200
commit

e92e67affefe6b23ea288799bad2793a0717a6d0

parent

62d70a9ef3dbea7c9ff59c09b8318d2c5a6f79df

6 files changed, 153 insertions(+), 51 deletions(-)

jump to
M cli.gocli.go

@@ -2,14 +2,18 @@ package main

import ( "bytes" + "encoding/base64" "fmt" + "github.com/DusanKasan/parsemail" "github.com/andybalholm/brotli" + "golang.org/x/net/html" + "io" "strings" "time" ) -func TimeStr(s int64) string { - t := time.Unix(s, 0).Local() +func TimeStr(t time.Time) string { + t = t.Local() n := time.Now().Local() return strings.ReplaceAll(func() string { if t.Year() != n.Year() {

@@ -41,3 +45,72 @@ reader := brotli.NewReader(bytes.NewReader(data))

_, err := buf.ReadFrom(reader) return err } + +func Show(b []byte) { + e, err := parsemail.Parse(bytes.NewReader(b)) + if err != nil { + fmt.Println(err) + return + } + if e.HTMLBody != "" { + var b []byte + if b, err = base64.StdEncoding.DecodeString(e.HTMLBody); err == nil { + fmt.Println(RenderHTML(string(b))) + } else { + fmt.Println(RenderHTML(e.HTMLBody)) + } + } + for _, a := range e.Attachments { + fmt.Println(a.Filename) + fmt.Println(a.ContentType) + } + for _, h := range e.EmbeddedFiles { + fmt.Println(h.ContentType) + fmt.Println(h.CID) + } +} + +func node(w io.Writer, n *html.Node) { + switch n.Type { + case html.ElementNode: + switch n.Data { + case "script", "style", "head", "img": + return + case "b", "strong": + fmt.Fprint(w, "\033[1m") // Bold + case "i": + fmt.Fprint(w, "\033[2m") // Italic + } + for c := n.FirstChild; c != nil; c = c.NextSibling { + node(w, c) + } + + // Reset styles after the element + switch n.Data { + case "h1", "h2", "p", "br": + fmt.Fprint(w, "\033[0m\n") + case "b", "strong", "i", "em": + fmt.Fprint(w, "\033[0m") + } + + case html.TextNode: + fmt.Fprint(w, n.Data, " ") + + default: + for c := n.FirstChild; c != nil; c = c.NextSibling { + node(w, c) + } + } + +} + +func RenderHTML(htmlContent string) string { + doc, err := html.Parse(bytes.NewBufferString(htmlContent)) + if err != nil { + panic(err) + } + + var buff bytes.Buffer + node(&buff, doc) + return buff.String() +}
A db.go

@@ -0,0 +1,27 @@

+package main + +import ( + "github.com/asdine/storm" + "go.etcd.io/bbolt" +) + +func DB() *storm.DB { // + db, err := storm.Open(DBPATH, storm.BoltOptions(0600, nil)) + if err != nil { + return nil + } + + // update db and add bucket if not exists + if err = db.Update(func(tx *bbolt.Tx) error { + _, err = tx.CreateBucketIfNotExists([]byte("data")) + return err + }); err != nil { + + return nil + } + if err = db.Init(&EmailMeta{}) != nil { + return nil + } + + return db +}
M go.modgo.mod

@@ -5,6 +5,11 @@

require ( github.com/DusanKasan/parsemail v1.2.0 github.com/andybalholm/brotli v1.1.0 + golang.org/x/net v0.27.0 ) -require golang.org/x/text v0.16.0 // indirect +require ( + github.com/asdine/storm v2.1.2+incompatible // indirect + go.etcd.io/bbolt v1.3.10 // indirect + golang.org/x/sys v0.22.0 // indirect +)
M go.sumgo.sum

@@ -2,5 +2,11 @@ github.com/DusanKasan/parsemail v1.2.0 h1:CrzTL1nuPLxB41aO4zE/Tzc9GVD8jjifUftlbTKQQl4=

github.com/DusanKasan/parsemail v1.2.0/go.mod h1:B9lfMbpVe4DMqPImAOCGti7KEwasnRTrKKn66iQefVs= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +github.com/asdine/storm v2.1.2+incompatible h1:dczuIkyqwY2LrtXPz8ixMrU/OFgZp71kbKTHGrXYt/Q= +github.com/asdine/storm v2.1.2+incompatible/go.mod h1:RarYDc9hq1UPLImuiXK3BIWPJLdIygvV3PsInK0FbVQ= +go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= +go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
M main.gomain.go

@@ -2,11 +2,32 @@ package main

import ( "fmt" - "github.com/DusanKasan/parsemail" "os" "path/filepath" ) +var DBPATH, SOCK, LOG string + +func init() { + home, _ := os.UserHomeDir() + if home == "" { + os.Exit(1) + } + DBPATH = filepath.Join(home, ".mailbox", "mail.storm") + SOCK = filepath.Join(home, ".mailbox", "mail.sock") + LOG = filepath.Join(home, ".mailbox", "box.log") +} + +func FtlLog(e error) { + if e == nil { + return + } + log, _ := os.OpenFile(LOG, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664) + fmt.Fprintln(log, "Fatal: ", e.Error()) + log.Close() + os.Exit(1) +} + func main() { if (len(os.Args) > 0 && filepath.Base(os.Args[0]) == "mailbox-parser") || (len(os.Args) > 1 && os.Args[1] == "parse") { meta, filebr := Parse()

@@ -17,30 +38,9 @@ fmt.Println("Subject", meta.Subject)

fmt.Println("Date", TimeStr(meta.Date)) return } - if len(os.Args) > 1 && os.Args[1] == "view" { - e, err := parsemail.Parse(os.Stdin) - if err != nil { - fmt.Println(err) - return - } - fmt.Println(e.HTMLBody, e.TextBody) + if (len(os.Args) > 0 && filepath.Base(os.Args[0]) == "mailbox-db") || (len(os.Args) > 1 && os.Args[1] == "db") { + return } - // Print email details - } - -/*# -CREATE TABLE `info` ( - `id` TEXT PRIMARY KEY, - `from` TEXT, - `to` TEXT, - `subject` TEXT, - `date` TEXT -); -CREATE TABLE `file` ( - `id` TEXT PRIMARY KEY, - `data` TEXT -); -*/
M parse.goparse.go

@@ -3,7 +3,6 @@

import ( "bytes" "crypto/sha1" - "encoding/base32" "fmt" "github.com/andybalholm/brotli" "mime"

@@ -25,35 +24,27 @@ }

func Parse() (EmailMeta, bytes.Buffer) { var email bytes.Buffer - if _, err := email.ReadFrom(os.Stdin); err != nil { - os.Exit(1) - } - + _, err := email.ReadFrom(os.Stdin) + FtlLog(err) meta, err := GenerateMeta(email) - if err != nil { - os.Exit(1) - } - _ = meta - err = Brotli(&email) - if err != nil { - os.Exit(1) - } + FtlLog(err) + FtlLog(Brotli(&email)) return meta, email } -func dateHeader(e *mail.Header) int64 { +func dateHeader(e *mail.Header) time.Time { var d time.Time var err error d, err = e.Date() if err != nil { d = time.Now().Local() } - return d.UTC().Unix() + return d } -func ShaHash(b []byte) string { +func ShaHash(b []byte) []byte { h := sha1.New() h.Write(b) - return base32.StdEncoding.EncodeToString(h.Sum(nil)) + return h.Sum(nil) } // GenerateMeta generates the EmailMeta for the EmailData

@@ -113,9 +104,9 @@ }

// EmailMeta contains the fields that will be searchable in the database type EmailMeta struct { - From string - To string - Subject string - Date int64 - Id string + From string `storm:"index"` + To string `storm:"index"` + Subject string `storm:"index"` + Date time.Time `storm:"index"` + Id []byte `storm:"id,unique,hash"` }