fixed some performance issues when pulling a large amount of messages

Signed-off-by: Michael <michael.lindman@gmail.com>
This commit is contained in:
Michael 2022-01-20 17:11:43 +00:00
parent f12e865042
commit 6d4d7e3459
3 changed files with 26 additions and 52 deletions

2
go.mod
View File

@ -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
)

View File

@ -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(&section)
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 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
}

13
main.go
View File

@ -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
}