sophuwu.site > mailboxxer
idk
sophuwu sophie@skisiel.com
Sat, 20 Jul 2024 13:05:20 +0200
commit

0c6f5de9ddb0cb6a75666475861e9e8f579796dd

parent

e9b58a5214c9df8f1e8c80d1af8a198134602742

4 files changed, 86 insertions(+), 34 deletions(-)

jump to
M .gitignore.gitignore

@@ -1,2 +1,3 @@

.idea +test build/
M go.modgo.mod

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

go 1.22.5 require ( - github.com/DusanKasan/parsemail v1.2.0 // indirect - github.com/andybalholm/brotli v1.1.0 // indirect + github.com/DusanKasan/parsemail v1.2.0 + github.com/andybalholm/brotli v1.1.0 )
M main.gomain.go

@@ -1,17 +1,34 @@

package main import ( + "fmt" "os" "path/filepath" ) func main() { - if len(os.Args) > 0 && filepath.Base(os.Args[0]) == "mailbox-parser" { - Parse() + if (len(os.Args) > 0 && filepath.Base(os.Args[0]) == "mailbox-parser") || (len(os.Args) > 1 && os.Args[1] == "parse") { + meta, filebr := Parse() + fmt.Println("Email ID: ", meta.Id, filebr.Len()) + fmt.Println("From ", meta.From) + fmt.Println("To", meta.To) return } - if len(os.Args) > 1 && os.Args[1] == "parse" { - Parse() - 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,14 +3,17 @@

import ( "bytes" "crypto/sha1" + "encoding/base32" "fmt" + "github.com/DusanKasan/parsemail" "github.com/andybalholm/brotli" + "mime" "net/mail" "os" "time" ) -func Br(buf *bytes.Buffer) error { +func Brotli(buf *bytes.Buffer) error { data := buf.Bytes() buf.Reset() writer := brotli.NewWriter(buf)

@@ -21,7 +24,7 @@ }

return writer.Close() } -func Parse() { +func Parse() (EmailMeta, bytes.Buffer) { var email bytes.Buffer if _, err := email.ReadFrom(os.Stdin); err != nil { os.Exit(1)

@@ -31,22 +34,11 @@ if err != nil {

os.Exit(1) } _ = meta - if Br(&email) != nil { + err = Brotli(&email) + if err != nil { os.Exit(1) } - fmt.Printf("%v\n", meta) -} - -// firstHeader returns the first email address in the list of headers -func firstHeader(e *mail.Header, s ...string) string { - var addr []*mail.Address - var err error - for _, v := range s { - if addr, err = e.AddressList(v); err == nil && len(addr) > 0 { - return addr[0].String() - } - } - return "Unknown" + return meta, email } func dateHeader(e *mail.Header) int64 {

@@ -59,32 +51,74 @@ }

return d.UTC().Unix() } +func ShaHash(b []byte) string { + h := sha1.New() + h.Write(b) + return base32.StdEncoding.EncodeToString(h.Sum(nil)) +} + // GenerateMeta generates the EmailMeta for the EmailData // This is used to index the email in the database func GenerateMeta(email bytes.Buffer) (EmailMeta, error) { var em EmailMeta - em.Id = fmt.Sprintf("%X", sha1.Sum(email.Bytes())) + em.Id = ShaHash(email.Bytes()) em.Subject = "No Subject" - // e, err := parsemail.Parse(&email) - e, err := mail.ReadMessage(&email) + decode := func(d mime.WordDecoder) func(s *string) { + return func(s *string) { + if ss, ers := d.DecodeHeader(fmt.Sprintf(*s)); ers == nil { + *s = ss + } + } + }(mime.WordDecoder{}) + + // e, err := mail.ReadMessage(&email) + e, err := parsemail.Parse(&email) if err != nil { + fmt.Println("Error parsing email: ", err) return em, err } - em.To = firstHeader(&e.Header, "To", "X-Original-To", "Delivered-To") - em.From = firstHeader(&e.Header, "From", "Reply-To", "Return-Path", "Sender") + + em.To = func() string { + if len(e.To) > 0 { + return e.To[0].String() + } + if e.Header.Get("X-Original-To") != "" { + return e.Header.Get("X-Original-To") + } + if e.Header.Get("Delivered-To") != "" { + return e.Header.Get("Delivered-To") + } + return "Unknown Recipient" + }() + decode(&em.To) + em.From = func() string { + if len(e.From) > 0 { + return e.From[0].String() + } + if len(e.Header.Get("Return-Path")) > 2 { + return e.Header.Get("Return-Path") + } + if e.Header.Get("Sender") != "" { + return e.Header.Get("Sender") + } + return "Unknown Sender" + }() + decode(&em.From) if s := e.Header.Get("Subject"); s != "" { em.Subject = s } + decode(&em.Subject) em.Date = dateHeader(&e.Header) + return em, nil } // EmailMeta contains the fields that will be searchable in the database type EmailMeta struct { - From string `storm:"index" json:"from"` - To string `storm:"index" json:"to"` - Subject string `storm:"index" json:"subject"` - Date int64 `storm:"index" json:"date"` - Id string `storm:"id" json:"id"` + From string + To string + Subject string + Date int64 + Id string }