From 6d4d7e34591d23c6242ab2282c018928b764fa02 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 20 Jan 2022 17:11:43 +0000 Subject: [PATCH] fixed some performance issues when pulling a large amount of messages Signed-off-by: Michael --- go.mod | 2 +- mail/mail.go | 63 ++++++++++++++++++---------------------------------- main.go | 13 ++++------- 3 files changed, 26 insertions(+), 52 deletions(-) diff --git a/go.mod b/go.mod index e09b7d5..9ae5f41 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,6 @@ go 1.16 require ( github.com/emersion/go-imap v1.2.0 github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac // indirect - golang.org/x/net v0.0.0-20211209124913-491a49abca63 + golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ) diff --git a/mail/mail.go b/mail/mail.go index f924edf..18e99bc 100644 --- a/mail/mail.go +++ b/mail/mail.go @@ -3,11 +3,11 @@ package mail import ( "errors" "fmt" + "io" "io/ioutil" "log" "os" "strconv" - "time" "github.com/emersion/go-imap" "github.com/emersion/go-imap/client" @@ -18,19 +18,6 @@ type Mail struct { Client *client.Client } -type Message struct { - SeqNum uint32 - Subject string - To []*imap.Address - From []*imap.Address - Date time.Time - Body imap.Literal -} - -type Messages struct { - Message []Message -} - type Conn struct { Addr string Username string @@ -76,20 +63,19 @@ func Login(conn Conn) (mail *Mail, err error) { return mail, nil } -func (mail *Mail) GetMessages(mailbox string, msgs int32) (*Messages, error) { - var messages Messages +func (mail *Mail) GetMessages(mailbox string, path string) error { mbox, err := mail.Client.Select(mailbox, true) if err != nil { - return nil, err + return err } if mbox.Messages == 0 { - return nil, errors.New("no messages in mailbox") + return errors.New("no messages in mailbox") } seqSet := new(imap.SeqSet) seqSet.AddRange(1, mbox.Messages) var section imap.BodySectionName - imapMessages := make(chan *imap.Message, msgs) + imapMessages := make(chan *imap.Message, mbox.Messages) done := make(chan error, 1) go func() { done <- mail.Client.Fetch(seqSet, []imap.FetchItem{imap.FetchEnvelope, section.FetchItem()}, imapMessages) @@ -98,33 +84,26 @@ func (mail *Mail) GetMessages(mailbox string, msgs int32) (*Messages, error) { for msg := range imapMessages { body := msg.GetBody(§ion) if body == nil { - return nil, errors.New("server didn't returned message body") + return errors.New("server didn't returned message body") } - message := Message{ - SeqNum: msg.SeqNum, - Subject: msg.Envelope.Subject, - To: msg.Envelope.To, - From: msg.Envelope.From, - Date: msg.Envelope.Date, - Body: body, + fmt.Println(msg.Envelope.Subject) + if err := Write(path, msg, body); err != nil { + return err } - messages.Message = append(messages.Message, message) } if err := <-done; err != nil { - return nil, err - } - return &messages, nil -} - -func WriteMessages(path string, messages *Messages) error { - for _, msg := range messages.Message { - body, err := ioutil.ReadAll(msg.Body) - if err != nil { - return err - } - if err := ioutil.WriteFile(path+"/"+strconv.Itoa(int(msg.SeqNum))+"_"+msg.Date.String()+".eml", body, 0644); err != nil { - return err - } + return err + } + return nil +} + +func Write(path string, msg *imap.Message, literal imap.Literal) error { + body, err := io.ReadAll(literal) + if err != nil { + return err + } + if err := ioutil.WriteFile(path+"/"+strconv.Itoa(int(msg.SeqNum))+"_"+msg.Envelope.Date.String()+".eml", body, 0644); err != nil { + return err } return nil } diff --git a/main.go b/main.go index b8ae40b..2259d29 100644 --- a/main.go +++ b/main.go @@ -11,7 +11,7 @@ import ( ) func main() { - cfgFile, mailbox, msgs := ui() + cfgFile, mailbox := ui() cfg := NewConfig(*cfgFile) chErr, chDone := make(chan error), make(chan bool) for _, account := range cfg.Account { @@ -34,17 +34,13 @@ func main() { } } defer conn.Client.Logout() - messages, err := conn.GetMessages(*mailbox, int32(*msgs)) - if err != nil { - chErr <- err - } path := cfg.Path + username + "/" + time.Now().Format("2006-01-02-15:04:05") for _, p := range []string{cfg.Path + username, path} { if _, err := os.Stat(p); os.IsNotExist(err) { os.Mkdir(p, 0775) } } - if err := mail.WriteMessages(path, messages); err != nil { + if err = conn.GetMessages(*mailbox, path); err != nil { chErr <- err } }(account.Addr, account.Username, account.Password, chErr, chDone) @@ -59,7 +55,7 @@ func main() { } } -func ui() (cfgFile, mailbox *string, msgs *int) { +func ui() (cfgFile, mailbox *string) { flag.Usage = func() { fmt.Printf("Usage of %s:\n", os.Args[0]) flag.PrintDefaults() @@ -70,8 +66,7 @@ func ui() (cfgFile, mailbox *string, msgs *int) { } cfgFile = flag.String("cfgFile", home+"/.config/gomail/config.yaml", "path to config file") mailbox = flag.String("mailbox", "inbox", "mailbox to scan messages") - msgs = flag.Int("msgs", 100, "Number of messages to pull") flag.Parse() - return cfgFile, mailbox, msgs + return cfgFile, mailbox }